1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <string.h> 11e1051a39Sopenharmony_ci#include <openssl/opensslconf.h> 12e1051a39Sopenharmony_ci#include <openssl/trace.h> 13e1051a39Sopenharmony_ci#include "apps.h" 14e1051a39Sopenharmony_ci#include "../testutil.h" 15e1051a39Sopenharmony_ci 16e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_TRACE 17e1051a39Sopenharmony_citypedef struct tracedata_st { 18e1051a39Sopenharmony_ci BIO *bio; 19e1051a39Sopenharmony_ci unsigned int ingroup:1; 20e1051a39Sopenharmony_ci} tracedata; 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_cistatic size_t internal_trace_cb(const char *buf, size_t cnt, 23e1051a39Sopenharmony_ci int category, int cmd, void *vdata) 24e1051a39Sopenharmony_ci{ 25e1051a39Sopenharmony_ci int ret = 0; 26e1051a39Sopenharmony_ci tracedata *trace_data = vdata; 27e1051a39Sopenharmony_ci char buffer[256], *hex; 28e1051a39Sopenharmony_ci CRYPTO_THREAD_ID tid; 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_ci switch (cmd) { 31e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_BEGIN: 32e1051a39Sopenharmony_ci trace_data->ingroup = 1; 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_ci tid = CRYPTO_THREAD_get_current_id(); 35e1051a39Sopenharmony_ci hex = OPENSSL_buf2hexstr((const unsigned char *)&tid, sizeof(tid)); 36e1051a39Sopenharmony_ci BIO_snprintf(buffer, sizeof(buffer), "TRACE[%s]:%s: ", 37e1051a39Sopenharmony_ci hex, OSSL_trace_get_category_name(category)); 38e1051a39Sopenharmony_ci OPENSSL_free(hex); 39e1051a39Sopenharmony_ci BIO_set_prefix(trace_data->bio, buffer); 40e1051a39Sopenharmony_ci break; 41e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_WRITE: 42e1051a39Sopenharmony_ci ret = BIO_write(trace_data->bio, buf, cnt); 43e1051a39Sopenharmony_ci break; 44e1051a39Sopenharmony_ci case OSSL_TRACE_CTRL_END: 45e1051a39Sopenharmony_ci trace_data->ingroup = 0; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci BIO_set_prefix(trace_data->bio, NULL); 48e1051a39Sopenharmony_ci break; 49e1051a39Sopenharmony_ci } 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci return ret < 0 ? 0 : ret; 52e1051a39Sopenharmony_ci} 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ciDEFINE_STACK_OF(tracedata) 55e1051a39Sopenharmony_cistatic STACK_OF(tracedata) *trace_data_stack; 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_cistatic void tracedata_free(tracedata *data) 58e1051a39Sopenharmony_ci{ 59e1051a39Sopenharmony_ci BIO_free_all(data->bio); 60e1051a39Sopenharmony_ci OPENSSL_free(data); 61e1051a39Sopenharmony_ci} 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_cistatic STACK_OF(tracedata) *trace_data_stack; 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_cistatic void cleanup_trace(void) 66e1051a39Sopenharmony_ci{ 67e1051a39Sopenharmony_ci sk_tracedata_pop_free(trace_data_stack, tracedata_free); 68e1051a39Sopenharmony_ci} 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_cistatic void setup_trace_category(int category) 71e1051a39Sopenharmony_ci{ 72e1051a39Sopenharmony_ci BIO *channel; 73e1051a39Sopenharmony_ci tracedata *trace_data; 74e1051a39Sopenharmony_ci BIO *bio = NULL; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci if (OSSL_trace_enabled(category)) 77e1051a39Sopenharmony_ci return; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci bio = BIO_new(BIO_f_prefix()); 80e1051a39Sopenharmony_ci channel = BIO_push(bio, 81e1051a39Sopenharmony_ci BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT)); 82e1051a39Sopenharmony_ci trace_data = OPENSSL_zalloc(sizeof(*trace_data)); 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (trace_data == NULL 85e1051a39Sopenharmony_ci || bio == NULL 86e1051a39Sopenharmony_ci || (trace_data->bio = channel) == NULL 87e1051a39Sopenharmony_ci || OSSL_trace_set_callback(category, internal_trace_cb, 88e1051a39Sopenharmony_ci trace_data) == 0 89e1051a39Sopenharmony_ci || sk_tracedata_push(trace_data_stack, trace_data) == 0) { 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci fprintf(stderr, 92e1051a39Sopenharmony_ci "warning: unable to setup trace callback for category '%s'.\n", 93e1051a39Sopenharmony_ci OSSL_trace_get_category_name(category)); 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_ci OSSL_trace_set_callback(category, NULL, NULL); 96e1051a39Sopenharmony_ci BIO_free_all(channel); 97e1051a39Sopenharmony_ci } 98e1051a39Sopenharmony_ci} 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_cistatic void setup_trace(const char *str) 101e1051a39Sopenharmony_ci{ 102e1051a39Sopenharmony_ci char *val; 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_ci /* 105e1051a39Sopenharmony_ci * We add this handler as early as possible to ensure it's executed 106e1051a39Sopenharmony_ci * as late as possible, i.e. after the TRACE code has done its cleanup 107e1051a39Sopenharmony_ci * (which happens last in OPENSSL_cleanup). 108e1051a39Sopenharmony_ci */ 109e1051a39Sopenharmony_ci atexit(cleanup_trace); 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_ci trace_data_stack = sk_tracedata_new_null(); 112e1051a39Sopenharmony_ci val = OPENSSL_strdup(str); 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci if (val != NULL) { 115e1051a39Sopenharmony_ci char *valp = val; 116e1051a39Sopenharmony_ci char *item; 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci for (valp = val; (item = strtok(valp, ",")) != NULL; valp = NULL) { 119e1051a39Sopenharmony_ci int category = OSSL_trace_get_category_num(item); 120e1051a39Sopenharmony_ci 121e1051a39Sopenharmony_ci if (category == OSSL_TRACE_CATEGORY_ALL) { 122e1051a39Sopenharmony_ci while (++category < OSSL_TRACE_CATEGORY_NUM) 123e1051a39Sopenharmony_ci setup_trace_category(category); 124e1051a39Sopenharmony_ci break; 125e1051a39Sopenharmony_ci } else if (category > 0) { 126e1051a39Sopenharmony_ci setup_trace_category(category); 127e1051a39Sopenharmony_ci } else { 128e1051a39Sopenharmony_ci fprintf(stderr, 129e1051a39Sopenharmony_ci "warning: unknown trace category: '%s'.\n", item); 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci } 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci 134e1051a39Sopenharmony_ci OPENSSL_free(val); 135e1051a39Sopenharmony_ci} 136e1051a39Sopenharmony_ci#endif /* OPENSSL_NO_TRACE */ 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ciint global_init(void) 139e1051a39Sopenharmony_ci{ 140e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_TRACE 141e1051a39Sopenharmony_ci setup_trace(getenv("OPENSSL_TRACE")); 142e1051a39Sopenharmony_ci#endif 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci return 1; 145e1051a39Sopenharmony_ci} 146