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