1 | /*
|
---|
2 | * Copyright 1995-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 | #define OSSL_FORCE_ERR_STATE
|
---|
11 |
|
---|
12 | #include <stdio.h>
|
---|
13 | #include "internal/cryptlib.h"
|
---|
14 | #include <openssl/crypto.h>
|
---|
15 | #include <openssl/buffer.h>
|
---|
16 | #include <openssl/err.h>
|
---|
17 | #include "err_local.h"
|
---|
18 |
|
---|
19 | #define ERR_PRINT_BUF_SIZE 4096
|
---|
20 | void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
|
---|
21 | void *u)
|
---|
22 | {
|
---|
23 | CRYPTO_THREAD_ID tid = CRYPTO_THREAD_get_current_id();
|
---|
24 | unsigned long l;
|
---|
25 | const char *file, *data, *func;
|
---|
26 | int line, flags;
|
---|
27 |
|
---|
28 | while ((l = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) {
|
---|
29 | char buf[ERR_PRINT_BUF_SIZE] = "";
|
---|
30 | char *hex = NULL;
|
---|
31 | int offset;
|
---|
32 |
|
---|
33 | if ((flags & ERR_TXT_STRING) == 0)
|
---|
34 | data = "";
|
---|
35 |
|
---|
36 | hex = ossl_buf2hexstr_sep((const unsigned char *)&tid, sizeof(tid), '\0');
|
---|
37 | BIO_snprintf(buf, sizeof(buf), "%s:", hex == NULL ? "<null>" : hex);
|
---|
38 | offset = strlen(buf);
|
---|
39 | ossl_err_string_int(l, func, buf + offset, sizeof(buf) - offset);
|
---|
40 | offset += strlen(buf + offset);
|
---|
41 | BIO_snprintf(buf + offset, sizeof(buf) - offset, ":%s:%d:%s\n",
|
---|
42 | file, line, data);
|
---|
43 | OPENSSL_free(hex);
|
---|
44 | if (cb(buf, strlen(buf), u) <= 0)
|
---|
45 | break; /* abort outputting the error report */
|
---|
46 | }
|
---|
47 | }
|
---|
48 |
|
---|
49 | /* auxiliary function for incrementally reporting texts via the error queue */
|
---|
50 | static void put_error(int lib, const char *func, int reason,
|
---|
51 | const char *file, int line)
|
---|
52 | {
|
---|
53 | ERR_new();
|
---|
54 | ERR_set_debug(file, line, func);
|
---|
55 | ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */);
|
---|
56 | }
|
---|
57 |
|
---|
58 | #define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100
|
---|
59 | #define MAX_DATA_LEN (ERR_PRINT_BUF_SIZE - TYPICAL_MAX_OUTPUT_BEFORE_DATA)
|
---|
60 | void ERR_add_error_txt(const char *separator, const char *txt)
|
---|
61 | {
|
---|
62 | const char *file = NULL;
|
---|
63 | int line;
|
---|
64 | const char *func = NULL;
|
---|
65 | const char *data = NULL;
|
---|
66 | int flags;
|
---|
67 | unsigned long err = ERR_peek_last_error();
|
---|
68 |
|
---|
69 | if (separator == NULL)
|
---|
70 | separator = "";
|
---|
71 | if (err == 0)
|
---|
72 | put_error(ERR_LIB_NONE, NULL, 0, "", 0);
|
---|
73 |
|
---|
74 | do {
|
---|
75 | size_t available_len, data_len;
|
---|
76 | const char *curr = txt, *next = txt;
|
---|
77 | const char *leading_separator = separator;
|
---|
78 | int trailing_separator = 0;
|
---|
79 | char *tmp;
|
---|
80 |
|
---|
81 | ERR_peek_last_error_all(&file, &line, &func, &data, &flags);
|
---|
82 | if ((flags & ERR_TXT_STRING) == 0) {
|
---|
83 | data = "";
|
---|
84 | leading_separator = "";
|
---|
85 | }
|
---|
86 | data_len = strlen(data);
|
---|
87 |
|
---|
88 | /* workaround for limit of ERR_print_errors_cb() */
|
---|
89 | if (data_len >= MAX_DATA_LEN
|
---|
90 | || strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len))
|
---|
91 | available_len = 0;
|
---|
92 | else
|
---|
93 | available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1;
|
---|
94 | /* MAX_DATA_LEN > available_len >= 0 */
|
---|
95 |
|
---|
96 | if (*separator == '\0') {
|
---|
97 | const size_t len_next = strlen(next);
|
---|
98 |
|
---|
99 | if (len_next <= available_len) {
|
---|
100 | next += len_next;
|
---|
101 | curr = NULL; /* no need to split */
|
---|
102 | } else {
|
---|
103 | next += available_len;
|
---|
104 | curr = next; /* will split at this point */
|
---|
105 | }
|
---|
106 | } else {
|
---|
107 | while (*next != '\0' && (size_t)(next - txt) <= available_len) {
|
---|
108 | curr = next;
|
---|
109 | next = strstr(curr, separator);
|
---|
110 | if (next != NULL) {
|
---|
111 | next += strlen(separator);
|
---|
112 | trailing_separator = *next == '\0';
|
---|
113 | } else {
|
---|
114 | next = curr + strlen(curr);
|
---|
115 | }
|
---|
116 | }
|
---|
117 | if ((size_t)(next - txt) <= available_len)
|
---|
118 | curr = NULL; /* the above loop implies *next == '\0' */
|
---|
119 | }
|
---|
120 | if (curr != NULL) {
|
---|
121 | /* split error msg at curr since error data would get too long */
|
---|
122 | if (curr != txt) {
|
---|
123 | tmp = OPENSSL_strndup(txt, curr - txt);
|
---|
124 | if (tmp == NULL)
|
---|
125 | return;
|
---|
126 | ERR_add_error_data(2, separator, tmp);
|
---|
127 | OPENSSL_free(tmp);
|
---|
128 | }
|
---|
129 | put_error(ERR_GET_LIB(err), func, err, file, line);
|
---|
130 | txt = curr;
|
---|
131 | } else {
|
---|
132 | if (trailing_separator) {
|
---|
133 | tmp = OPENSSL_strndup(txt, next - strlen(separator) - txt);
|
---|
134 | if (tmp == NULL)
|
---|
135 | return;
|
---|
136 | /* output txt without the trailing separator */
|
---|
137 | ERR_add_error_data(2, leading_separator, tmp);
|
---|
138 | OPENSSL_free(tmp);
|
---|
139 | } else {
|
---|
140 | ERR_add_error_data(2, leading_separator, txt);
|
---|
141 | }
|
---|
142 | txt = next; /* finished */
|
---|
143 | }
|
---|
144 | } while (*txt != '\0');
|
---|
145 | }
|
---|
146 |
|
---|
147 | void ERR_add_error_mem_bio(const char *separator, BIO *bio)
|
---|
148 | {
|
---|
149 | if (bio != NULL) {
|
---|
150 | char *str;
|
---|
151 | long len = BIO_get_mem_data(bio, &str);
|
---|
152 |
|
---|
153 | if (len > 0) {
|
---|
154 | if (str[len - 1] != '\0') {
|
---|
155 | if (BIO_write(bio, "", 1) <= 0)
|
---|
156 | return;
|
---|
157 |
|
---|
158 | len = BIO_get_mem_data(bio, &str);
|
---|
159 | }
|
---|
160 | if (len > 1)
|
---|
161 | ERR_add_error_txt(separator, str);
|
---|
162 | }
|
---|
163 | }
|
---|
164 | }
|
---|
165 |
|
---|
166 | static int print_bio(const char *str, size_t len, void *bp)
|
---|
167 | {
|
---|
168 | return BIO_write((BIO *)bp, str, len);
|
---|
169 | }
|
---|
170 |
|
---|
171 | void ERR_print_errors(BIO *bp)
|
---|
172 | {
|
---|
173 | ERR_print_errors_cb(print_bio, bp);
|
---|
174 | }
|
---|
175 |
|
---|
176 | #ifndef OPENSSL_NO_STDIO
|
---|
177 | void ERR_print_errors_fp(FILE *fp)
|
---|
178 | {
|
---|
179 | BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE);
|
---|
180 | if (bio == NULL)
|
---|
181 | return;
|
---|
182 |
|
---|
183 | ERR_print_errors_cb(print_bio, bio);
|
---|
184 | BIO_free(bio);
|
---|
185 | }
|
---|
186 | #endif
|
---|