1 |
|
|
/* $OpenBSD: err.c,v 1.41 2014/11/09 19:17:13 miod Exp $ */ |
2 |
|
|
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 |
|
|
* All rights reserved. |
4 |
|
|
* |
5 |
|
|
* This package is an SSL implementation written |
6 |
|
|
* by Eric Young (eay@cryptsoft.com). |
7 |
|
|
* The implementation was written so as to conform with Netscapes SSL. |
8 |
|
|
* |
9 |
|
|
* This library is free for commercial and non-commercial use as long as |
10 |
|
|
* the following conditions are aheared to. The following conditions |
11 |
|
|
* apply to all code found in this distribution, be it the RC4, RSA, |
12 |
|
|
* lhash, DES, etc., code; not just the SSL code. The SSL documentation |
13 |
|
|
* included with this distribution is covered by the same copyright terms |
14 |
|
|
* except that the holder is Tim Hudson (tjh@cryptsoft.com). |
15 |
|
|
* |
16 |
|
|
* Copyright remains Eric Young's, and as such any Copyright notices in |
17 |
|
|
* the code are not to be removed. |
18 |
|
|
* If this package is used in a product, Eric Young should be given attribution |
19 |
|
|
* as the author of the parts of the library used. |
20 |
|
|
* This can be in the form of a textual message at program startup or |
21 |
|
|
* in documentation (online or textual) provided with the package. |
22 |
|
|
* |
23 |
|
|
* Redistribution and use in source and binary forms, with or without |
24 |
|
|
* modification, are permitted provided that the following conditions |
25 |
|
|
* are met: |
26 |
|
|
* 1. Redistributions of source code must retain the copyright |
27 |
|
|
* notice, this list of conditions and the following disclaimer. |
28 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
29 |
|
|
* notice, this list of conditions and the following disclaimer in the |
30 |
|
|
* documentation and/or other materials provided with the distribution. |
31 |
|
|
* 3. All advertising materials mentioning features or use of this software |
32 |
|
|
* must display the following acknowledgement: |
33 |
|
|
* "This product includes cryptographic software written by |
34 |
|
|
* Eric Young (eay@cryptsoft.com)" |
35 |
|
|
* The word 'cryptographic' can be left out if the rouines from the library |
36 |
|
|
* being used are not cryptographic related :-). |
37 |
|
|
* 4. If you include any Windows specific code (or a derivative thereof) from |
38 |
|
|
* the apps directory (application code) you must include an acknowledgement: |
39 |
|
|
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" |
40 |
|
|
* |
41 |
|
|
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
42 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
43 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
44 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
45 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
46 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
47 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
48 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
49 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
50 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
51 |
|
|
* SUCH DAMAGE. |
52 |
|
|
* |
53 |
|
|
* The licence and distribution terms for any publically available version or |
54 |
|
|
* derivative of this code cannot be changed. i.e. this code cannot simply be |
55 |
|
|
* copied and put under another distribution licence |
56 |
|
|
* [including the GNU Public Licence.] |
57 |
|
|
*/ |
58 |
|
|
/* ==================================================================== |
59 |
|
|
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. |
60 |
|
|
* |
61 |
|
|
* Redistribution and use in source and binary forms, with or without |
62 |
|
|
* modification, are permitted provided that the following conditions |
63 |
|
|
* are met: |
64 |
|
|
* |
65 |
|
|
* 1. Redistributions of source code must retain the above copyright |
66 |
|
|
* notice, this list of conditions and the following disclaimer. |
67 |
|
|
* |
68 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
69 |
|
|
* notice, this list of conditions and the following disclaimer in |
70 |
|
|
* the documentation and/or other materials provided with the |
71 |
|
|
* distribution. |
72 |
|
|
* |
73 |
|
|
* 3. All advertising materials mentioning features or use of this |
74 |
|
|
* software must display the following acknowledgment: |
75 |
|
|
* "This product includes software developed by the OpenSSL Project |
76 |
|
|
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
77 |
|
|
* |
78 |
|
|
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
79 |
|
|
* endorse or promote products derived from this software without |
80 |
|
|
* prior written permission. For written permission, please contact |
81 |
|
|
* openssl-core@openssl.org. |
82 |
|
|
* |
83 |
|
|
* 5. Products derived from this software may not be called "OpenSSL" |
84 |
|
|
* nor may "OpenSSL" appear in their names without prior written |
85 |
|
|
* permission of the OpenSSL Project. |
86 |
|
|
* |
87 |
|
|
* 6. Redistributions of any form whatsoever must retain the following |
88 |
|
|
* acknowledgment: |
89 |
|
|
* "This product includes software developed by the OpenSSL Project |
90 |
|
|
* for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
91 |
|
|
* |
92 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
93 |
|
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
94 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
95 |
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
96 |
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
97 |
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
98 |
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
99 |
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
100 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
101 |
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
102 |
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
103 |
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE. |
104 |
|
|
* ==================================================================== |
105 |
|
|
* |
106 |
|
|
* This product includes cryptographic software written by Eric Young |
107 |
|
|
* (eay@cryptsoft.com). This product includes software written by Tim |
108 |
|
|
* Hudson (tjh@cryptsoft.com). |
109 |
|
|
* |
110 |
|
|
*/ |
111 |
|
|
|
112 |
|
|
#include <stdarg.h> |
113 |
|
|
#include <stdio.h> |
114 |
|
|
#include <string.h> |
115 |
|
|
|
116 |
|
|
#include <openssl/opensslconf.h> |
117 |
|
|
|
118 |
|
|
#include <openssl/bio.h> |
119 |
|
|
#include <openssl/buffer.h> |
120 |
|
|
#include <openssl/crypto.h> |
121 |
|
|
#include <openssl/err.h> |
122 |
|
|
#include <openssl/lhash.h> |
123 |
|
|
|
124 |
|
|
DECLARE_LHASH_OF(ERR_STRING_DATA); |
125 |
|
|
DECLARE_LHASH_OF(ERR_STATE); |
126 |
|
|
|
127 |
|
|
static void err_load_strings(int lib, ERR_STRING_DATA *str); |
128 |
|
|
|
129 |
|
|
static void ERR_STATE_free(ERR_STATE *s); |
130 |
|
|
#ifndef OPENSSL_NO_ERR |
131 |
|
|
static ERR_STRING_DATA ERR_str_libraries[] = { |
132 |
|
|
{ERR_PACK(ERR_LIB_NONE,0,0), "unknown library"}, |
133 |
|
|
{ERR_PACK(ERR_LIB_SYS,0,0), "system library"}, |
134 |
|
|
{ERR_PACK(ERR_LIB_BN,0,0), "bignum routines"}, |
135 |
|
|
{ERR_PACK(ERR_LIB_RSA,0,0), "rsa routines"}, |
136 |
|
|
{ERR_PACK(ERR_LIB_DH,0,0), "Diffie-Hellman routines"}, |
137 |
|
|
{ERR_PACK(ERR_LIB_EVP,0,0), "digital envelope routines"}, |
138 |
|
|
{ERR_PACK(ERR_LIB_BUF,0,0), "memory buffer routines"}, |
139 |
|
|
{ERR_PACK(ERR_LIB_OBJ,0,0), "object identifier routines"}, |
140 |
|
|
{ERR_PACK(ERR_LIB_PEM,0,0), "PEM routines"}, |
141 |
|
|
{ERR_PACK(ERR_LIB_DSA,0,0), "dsa routines"}, |
142 |
|
|
{ERR_PACK(ERR_LIB_X509,0,0), "x509 certificate routines"}, |
143 |
|
|
{ERR_PACK(ERR_LIB_ASN1,0,0), "asn1 encoding routines"}, |
144 |
|
|
{ERR_PACK(ERR_LIB_CONF,0,0), "configuration file routines"}, |
145 |
|
|
{ERR_PACK(ERR_LIB_CRYPTO,0,0), "common libcrypto routines"}, |
146 |
|
|
{ERR_PACK(ERR_LIB_EC,0,0), "elliptic curve routines"}, |
147 |
|
|
{ERR_PACK(ERR_LIB_SSL,0,0), "SSL routines"}, |
148 |
|
|
{ERR_PACK(ERR_LIB_BIO,0,0), "BIO routines"}, |
149 |
|
|
{ERR_PACK(ERR_LIB_PKCS7,0,0), "PKCS7 routines"}, |
150 |
|
|
{ERR_PACK(ERR_LIB_X509V3,0,0), "X509 V3 routines"}, |
151 |
|
|
{ERR_PACK(ERR_LIB_PKCS12,0,0), "PKCS12 routines"}, |
152 |
|
|
{ERR_PACK(ERR_LIB_RAND,0,0), "random number generator"}, |
153 |
|
|
{ERR_PACK(ERR_LIB_DSO,0,0), "DSO support routines"}, |
154 |
|
|
{ERR_PACK(ERR_LIB_TS,0,0), "time stamp routines"}, |
155 |
|
|
{ERR_PACK(ERR_LIB_ENGINE,0,0), "engine routines"}, |
156 |
|
|
{ERR_PACK(ERR_LIB_OCSP,0,0), "OCSP routines"}, |
157 |
|
|
{ERR_PACK(ERR_LIB_FIPS,0,0), "FIPS routines"}, |
158 |
|
|
{ERR_PACK(ERR_LIB_CMS,0,0), "CMS routines"}, |
159 |
|
|
{ERR_PACK(ERR_LIB_HMAC,0,0), "HMAC routines"}, |
160 |
|
|
{ERR_PACK(ERR_LIB_GOST,0,0), "GOST routines"}, |
161 |
|
|
{0, NULL}, |
162 |
|
|
}; |
163 |
|
|
|
164 |
|
|
static ERR_STRING_DATA ERR_str_functs[] = { |
165 |
|
|
{ERR_PACK(0,SYS_F_FOPEN, 0), "fopen"}, |
166 |
|
|
{ERR_PACK(0,SYS_F_CONNECT, 0), "connect"}, |
167 |
|
|
{ERR_PACK(0,SYS_F_GETSERVBYNAME, 0), "getservbyname"}, |
168 |
|
|
{ERR_PACK(0,SYS_F_SOCKET, 0), "socket"}, |
169 |
|
|
{ERR_PACK(0,SYS_F_IOCTLSOCKET, 0), "ioctl"}, |
170 |
|
|
{ERR_PACK(0,SYS_F_BIND, 0), "bind"}, |
171 |
|
|
{ERR_PACK(0,SYS_F_LISTEN, 0), "listen"}, |
172 |
|
|
{ERR_PACK(0,SYS_F_ACCEPT, 0), "accept"}, |
173 |
|
|
{ERR_PACK(0,SYS_F_OPENDIR, 0), "opendir"}, |
174 |
|
|
{ERR_PACK(0,SYS_F_FREAD, 0), "fread"}, |
175 |
|
|
{0, NULL}, |
176 |
|
|
}; |
177 |
|
|
|
178 |
|
|
static ERR_STRING_DATA ERR_str_reasons[] = { |
179 |
|
|
{ERR_R_SYS_LIB, "system lib"}, |
180 |
|
|
{ERR_R_BN_LIB, "BN lib"}, |
181 |
|
|
{ERR_R_RSA_LIB, "RSA lib"}, |
182 |
|
|
{ERR_R_DH_LIB, "DH lib"}, |
183 |
|
|
{ERR_R_EVP_LIB, "EVP lib"}, |
184 |
|
|
{ERR_R_BUF_LIB, "BUF lib"}, |
185 |
|
|
{ERR_R_OBJ_LIB, "OBJ lib"}, |
186 |
|
|
{ERR_R_PEM_LIB, "PEM lib"}, |
187 |
|
|
{ERR_R_DSA_LIB, "DSA lib"}, |
188 |
|
|
{ERR_R_X509_LIB, "X509 lib"}, |
189 |
|
|
{ERR_R_ASN1_LIB, "ASN1 lib"}, |
190 |
|
|
{ERR_R_CONF_LIB, "CONF lib"}, |
191 |
|
|
{ERR_R_CRYPTO_LIB, "CRYPTO lib"}, |
192 |
|
|
{ERR_R_EC_LIB, "EC lib"}, |
193 |
|
|
{ERR_R_SSL_LIB, "SSL lib"}, |
194 |
|
|
{ERR_R_BIO_LIB, "BIO lib"}, |
195 |
|
|
{ERR_R_PKCS7_LIB, "PKCS7 lib"}, |
196 |
|
|
{ERR_R_X509V3_LIB, "X509V3 lib"}, |
197 |
|
|
{ERR_R_PKCS12_LIB, "PKCS12 lib"}, |
198 |
|
|
{ERR_R_RAND_LIB, "RAND lib"}, |
199 |
|
|
{ERR_R_DSO_LIB, "DSO lib"}, |
200 |
|
|
{ERR_R_ENGINE_LIB, "ENGINE lib"}, |
201 |
|
|
{ERR_R_OCSP_LIB, "OCSP lib"}, |
202 |
|
|
{ERR_R_TS_LIB, "TS lib"}, |
203 |
|
|
|
204 |
|
|
{ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"}, |
205 |
|
|
{ERR_R_BAD_ASN1_OBJECT_HEADER, "bad asn1 object header"}, |
206 |
|
|
{ERR_R_BAD_GET_ASN1_OBJECT_CALL, "bad get asn1 object call"}, |
207 |
|
|
{ERR_R_EXPECTING_AN_ASN1_SEQUENCE, "expecting an asn1 sequence"}, |
208 |
|
|
{ERR_R_ASN1_LENGTH_MISMATCH, "asn1 length mismatch"}, |
209 |
|
|
{ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"}, |
210 |
|
|
|
211 |
|
|
{ERR_R_FATAL, "fatal"}, |
212 |
|
|
{ERR_R_MALLOC_FAILURE, "malloc failure"}, |
213 |
|
|
{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, "called a function you should not call"}, |
214 |
|
|
{ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"}, |
215 |
|
|
{ERR_R_INTERNAL_ERROR, "internal error"}, |
216 |
|
|
{ERR_R_DISABLED , "called a function that was disabled at compile-time"}, |
217 |
|
|
|
218 |
|
|
{0, NULL}, |
219 |
|
|
}; |
220 |
|
|
#endif |
221 |
|
|
|
222 |
|
|
|
223 |
|
|
/* Define the predeclared (but externally opaque) "ERR_FNS" type */ |
224 |
|
|
struct st_ERR_FNS { |
225 |
|
|
/* Works on the "error_hash" string table */ |
226 |
|
|
LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create); |
227 |
|
|
void (*cb_err_del)(void); |
228 |
|
|
ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *); |
229 |
|
|
ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *); |
230 |
|
|
ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *); |
231 |
|
|
/* Works on the "thread_hash" error-state table */ |
232 |
|
|
LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create); |
233 |
|
|
void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash); |
234 |
|
|
ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *); |
235 |
|
|
ERR_STATE *(*cb_thread_set_item)(ERR_STATE *); |
236 |
|
|
void (*cb_thread_del_item)(const ERR_STATE *); |
237 |
|
|
/* Returns the next available error "library" numbers */ |
238 |
|
|
int (*cb_get_next_lib)(void); |
239 |
|
|
}; |
240 |
|
|
|
241 |
|
|
/* Predeclarations of the "err_defaults" functions */ |
242 |
|
|
static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create); |
243 |
|
|
static void int_err_del(void); |
244 |
|
|
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); |
245 |
|
|
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *); |
246 |
|
|
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *); |
247 |
|
|
static LHASH_OF(ERR_STATE) *int_thread_get(int create); |
248 |
|
|
static void int_thread_release(LHASH_OF(ERR_STATE) **hash); |
249 |
|
|
static ERR_STATE *int_thread_get_item(const ERR_STATE *); |
250 |
|
|
static ERR_STATE *int_thread_set_item(ERR_STATE *); |
251 |
|
|
static void int_thread_del_item(const ERR_STATE *); |
252 |
|
|
static int int_err_get_next_lib(void); |
253 |
|
|
|
254 |
|
|
/* The static ERR_FNS table using these defaults functions */ |
255 |
|
|
static const ERR_FNS err_defaults = { |
256 |
|
|
int_err_get, |
257 |
|
|
int_err_del, |
258 |
|
|
int_err_get_item, |
259 |
|
|
int_err_set_item, |
260 |
|
|
int_err_del_item, |
261 |
|
|
int_thread_get, |
262 |
|
|
int_thread_release, |
263 |
|
|
int_thread_get_item, |
264 |
|
|
int_thread_set_item, |
265 |
|
|
int_thread_del_item, |
266 |
|
|
int_err_get_next_lib |
267 |
|
|
}; |
268 |
|
|
|
269 |
|
|
/* The replacable table of ERR_FNS functions we use at run-time */ |
270 |
|
|
static const ERR_FNS *err_fns = NULL; |
271 |
|
|
|
272 |
|
|
/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */ |
273 |
|
|
#define ERRFN(a) err_fns->cb_##a |
274 |
|
|
|
275 |
|
|
/* The internal state used by "err_defaults" - as such, the setting, reading, |
276 |
|
|
* creating, and deleting of this data should only be permitted via the |
277 |
|
|
* "err_defaults" functions. This way, a linked module can completely defer all |
278 |
|
|
* ERR state operation (together with requisite locking) to the implementations |
279 |
|
|
* and state in the loading application. */ |
280 |
|
|
static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; |
281 |
|
|
static LHASH_OF(ERR_STATE) *int_thread_hash = NULL; |
282 |
|
|
static int int_thread_hash_references = 0; |
283 |
|
|
static int int_err_library_number = ERR_LIB_USER; |
284 |
|
|
|
285 |
|
|
/* Internal function that checks whether "err_fns" is set and if not, sets it to |
286 |
|
|
* the defaults. */ |
287 |
|
|
static void |
288 |
|
|
err_fns_check(void) |
289 |
|
224851 |
{ |
290 |
✓✓ |
224851 |
if (err_fns) |
291 |
|
224826 |
return; |
292 |
|
|
|
293 |
|
25 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
294 |
✓✗ |
25 |
if (!err_fns) |
295 |
|
25 |
err_fns = &err_defaults; |
296 |
|
25 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
/* API functions to get or set the underlying ERR functions. */ |
300 |
|
|
|
301 |
|
|
const ERR_FNS * |
302 |
|
|
ERR_get_implementation(void) |
303 |
|
|
{ |
304 |
|
|
err_fns_check(); |
305 |
|
|
return err_fns; |
306 |
|
|
} |
307 |
|
|
|
308 |
|
|
int |
309 |
|
|
ERR_set_implementation(const ERR_FNS *fns) |
310 |
|
|
{ |
311 |
|
|
int ret = 0; |
312 |
|
|
|
313 |
|
|
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
314 |
|
|
/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting |
315 |
|
|
* an error is there?! */ |
316 |
|
|
if (!err_fns) { |
317 |
|
|
err_fns = fns; |
318 |
|
|
ret = 1; |
319 |
|
|
} |
320 |
|
|
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
321 |
|
|
return ret; |
322 |
|
|
} |
323 |
|
|
|
324 |
|
|
/* These are the callbacks provided to "lh_new()" when creating the LHASH tables |
325 |
|
|
* internal to the "err_defaults" implementation. */ |
326 |
|
|
|
327 |
|
|
static unsigned long get_error_values(int inc, int top, const char **file, |
328 |
|
|
int *line, const char **data, int *flags); |
329 |
|
|
|
330 |
|
|
/* The internal functions used in the "err_defaults" implementation */ |
331 |
|
|
|
332 |
|
|
static unsigned long |
333 |
|
|
err_string_data_hash(const ERR_STRING_DATA *a) |
334 |
|
222039 |
{ |
335 |
|
|
unsigned long ret, l; |
336 |
|
|
|
337 |
|
222039 |
l = a->error; |
338 |
|
222039 |
ret = l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); |
339 |
|
222039 |
return (ret^ret % 19*13); |
340 |
|
|
} |
341 |
|
222039 |
static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA) |
342 |
|
|
|
343 |
|
|
static int |
344 |
|
|
err_string_data_cmp(const ERR_STRING_DATA *a, const ERR_STRING_DATA *b) |
345 |
|
194862 |
{ |
346 |
|
194862 |
return (int)(a->error - b->error); |
347 |
|
|
} |
348 |
|
194862 |
static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA) |
349 |
|
|
|
350 |
|
|
static |
351 |
|
|
LHASH_OF(ERR_STRING_DATA) *int_err_get(int create) |
352 |
|
222040 |
{ |
353 |
|
222040 |
LHASH_OF(ERR_STRING_DATA) *ret = NULL; |
354 |
|
|
|
355 |
|
222040 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
356 |
✓✓ |
222040 |
if (!int_error_hash && create) { |
357 |
|
18 |
CRYPTO_push_info("int_err_get (err.c)"); |
358 |
|
18 |
int_error_hash = lh_ERR_STRING_DATA_new(); |
359 |
|
18 |
CRYPTO_pop_info(); |
360 |
|
|
} |
361 |
✓✓ |
222040 |
if (int_error_hash) |
362 |
|
222039 |
ret = int_error_hash; |
363 |
|
222040 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
364 |
|
|
|
365 |
|
222040 |
return ret; |
366 |
|
|
} |
367 |
|
|
|
368 |
|
|
static void |
369 |
|
|
int_err_del(void) |
370 |
|
15 |
{ |
371 |
|
15 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
372 |
✓✓ |
15 |
if (int_error_hash) { |
373 |
|
13 |
lh_ERR_STRING_DATA_free(int_error_hash); |
374 |
|
13 |
int_error_hash = NULL; |
375 |
|
|
} |
376 |
|
15 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
377 |
|
15 |
} |
378 |
|
|
|
379 |
|
|
static ERR_STRING_DATA * |
380 |
|
|
int_err_get_item(const ERR_STRING_DATA *d) |
381 |
|
453 |
{ |
382 |
|
|
ERR_STRING_DATA *p; |
383 |
|
|
LHASH_OF(ERR_STRING_DATA) *hash; |
384 |
|
|
|
385 |
|
453 |
err_fns_check(); |
386 |
|
453 |
hash = ERRFN(err_get)(0); |
387 |
✓✓ |
453 |
if (!hash) |
388 |
|
1 |
return NULL; |
389 |
|
|
|
390 |
|
452 |
CRYPTO_r_lock(CRYPTO_LOCK_ERR); |
391 |
|
452 |
p = lh_ERR_STRING_DATA_retrieve(hash, d); |
392 |
|
452 |
CRYPTO_r_unlock(CRYPTO_LOCK_ERR); |
393 |
|
|
|
394 |
|
452 |
return p; |
395 |
|
|
} |
396 |
|
|
|
397 |
|
|
static ERR_STRING_DATA * |
398 |
|
|
int_err_set_item(ERR_STRING_DATA *d) |
399 |
|
221587 |
{ |
400 |
|
|
ERR_STRING_DATA *p; |
401 |
|
|
LHASH_OF(ERR_STRING_DATA) *hash; |
402 |
|
|
|
403 |
|
221587 |
err_fns_check(); |
404 |
|
221587 |
hash = ERRFN(err_get)(1); |
405 |
✗✓ |
221587 |
if (!hash) |
406 |
|
|
return NULL; |
407 |
|
|
|
408 |
|
221587 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
409 |
|
221587 |
p = lh_ERR_STRING_DATA_insert(hash, d); |
410 |
|
221587 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
411 |
|
|
|
412 |
|
221587 |
return p; |
413 |
|
|
} |
414 |
|
|
|
415 |
|
|
static ERR_STRING_DATA * |
416 |
|
|
int_err_del_item(ERR_STRING_DATA *d) |
417 |
|
|
{ |
418 |
|
|
ERR_STRING_DATA *p; |
419 |
|
|
LHASH_OF(ERR_STRING_DATA) *hash; |
420 |
|
|
|
421 |
|
|
err_fns_check(); |
422 |
|
|
hash = ERRFN(err_get)(0); |
423 |
|
|
if (!hash) |
424 |
|
|
return NULL; |
425 |
|
|
|
426 |
|
|
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
427 |
|
|
p = lh_ERR_STRING_DATA_delete(hash, d); |
428 |
|
|
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
429 |
|
|
|
430 |
|
|
return p; |
431 |
|
|
} |
432 |
|
|
|
433 |
|
|
static unsigned long |
434 |
|
|
err_state_hash(const ERR_STATE *a) |
435 |
|
705 |
{ |
436 |
|
705 |
return CRYPTO_THREADID_hash(&a->tid) * 13; |
437 |
|
|
} |
438 |
|
705 |
static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE) |
439 |
|
|
|
440 |
|
|
static int |
441 |
|
|
err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) |
442 |
|
685 |
{ |
443 |
|
685 |
return CRYPTO_THREADID_cmp(&a->tid, &b->tid); |
444 |
|
|
} |
445 |
|
685 |
static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE) |
446 |
|
|
|
447 |
|
|
static |
448 |
|
|
LHASH_OF(ERR_STATE) *int_thread_get(int create) |
449 |
|
730 |
{ |
450 |
|
730 |
LHASH_OF(ERR_STATE) *ret = NULL; |
451 |
|
|
|
452 |
|
730 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
453 |
✓✓ |
730 |
if (!int_thread_hash && create) { |
454 |
|
20 |
CRYPTO_push_info("int_thread_get (err.c)"); |
455 |
|
20 |
int_thread_hash = lh_ERR_STATE_new(); |
456 |
|
20 |
CRYPTO_pop_info(); |
457 |
|
|
} |
458 |
✓✓ |
730 |
if (int_thread_hash) { |
459 |
|
705 |
int_thread_hash_references++; |
460 |
|
705 |
ret = int_thread_hash; |
461 |
|
|
} |
462 |
|
730 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
463 |
|
730 |
return ret; |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
static void |
467 |
|
|
int_thread_release(LHASH_OF(ERR_STATE) **hash) |
468 |
|
705 |
{ |
469 |
|
|
int i; |
470 |
|
|
|
471 |
✓✗✓✗
|
705 |
if (hash == NULL || *hash == NULL) |
472 |
|
|
return; |
473 |
|
|
|
474 |
|
705 |
i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR); |
475 |
✗✓ |
705 |
if (i > 0) |
476 |
|
|
return; |
477 |
|
|
|
478 |
|
705 |
*hash = NULL; |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
static ERR_STATE * |
482 |
|
|
int_thread_get_item(const ERR_STATE *d) |
483 |
|
693 |
{ |
484 |
|
|
ERR_STATE *p; |
485 |
|
|
LHASH_OF(ERR_STATE) *hash; |
486 |
|
|
|
487 |
|
693 |
err_fns_check(); |
488 |
|
693 |
hash = ERRFN(thread_get)(0); |
489 |
✓✓ |
693 |
if (!hash) |
490 |
|
20 |
return NULL; |
491 |
|
|
|
492 |
|
673 |
CRYPTO_r_lock(CRYPTO_LOCK_ERR); |
493 |
|
673 |
p = lh_ERR_STATE_retrieve(hash, d); |
494 |
|
673 |
CRYPTO_r_unlock(CRYPTO_LOCK_ERR); |
495 |
|
|
|
496 |
|
673 |
ERRFN(thread_release)(&hash); |
497 |
|
673 |
return p; |
498 |
|
|
} |
499 |
|
|
|
500 |
|
|
static ERR_STATE * |
501 |
|
|
int_thread_set_item(ERR_STATE *d) |
502 |
|
20 |
{ |
503 |
|
|
ERR_STATE *p; |
504 |
|
|
LHASH_OF(ERR_STATE) *hash; |
505 |
|
|
|
506 |
|
20 |
err_fns_check(); |
507 |
|
20 |
hash = ERRFN(thread_get)(1); |
508 |
✗✓ |
20 |
if (!hash) |
509 |
|
|
return NULL; |
510 |
|
|
|
511 |
|
20 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
512 |
|
20 |
p = lh_ERR_STATE_insert(hash, d); |
513 |
|
20 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
514 |
|
|
|
515 |
|
20 |
ERRFN(thread_release)(&hash); |
516 |
|
20 |
return p; |
517 |
|
|
} |
518 |
|
|
|
519 |
|
|
static void |
520 |
|
|
int_thread_del_item(const ERR_STATE *d) |
521 |
|
17 |
{ |
522 |
|
|
ERR_STATE *p; |
523 |
|
|
LHASH_OF(ERR_STATE) *hash; |
524 |
|
|
|
525 |
|
17 |
err_fns_check(); |
526 |
|
17 |
hash = ERRFN(thread_get)(0); |
527 |
✓✓ |
17 |
if (!hash) |
528 |
|
5 |
return; |
529 |
|
|
|
530 |
|
12 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
531 |
|
12 |
p = lh_ERR_STATE_delete(hash, d); |
532 |
|
|
/* make sure we don't leak memory */ |
533 |
✓✗✓✗ ✓✗ |
12 |
if (int_thread_hash_references == 1 && |
534 |
|
|
int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0) { |
535 |
|
12 |
lh_ERR_STATE_free(int_thread_hash); |
536 |
|
12 |
int_thread_hash = NULL; |
537 |
|
|
} |
538 |
|
12 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
539 |
|
|
|
540 |
|
12 |
ERRFN(thread_release)(&hash); |
541 |
✓✗ |
12 |
if (p) |
542 |
|
12 |
ERR_STATE_free(p); |
543 |
|
|
} |
544 |
|
|
|
545 |
|
|
static int |
546 |
|
|
int_err_get_next_lib(void) |
547 |
|
|
{ |
548 |
|
|
int ret; |
549 |
|
|
|
550 |
|
|
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
551 |
|
|
ret = int_err_library_number++; |
552 |
|
|
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
553 |
|
|
|
554 |
|
|
return ret; |
555 |
|
|
} |
556 |
|
|
|
557 |
|
|
|
558 |
|
|
#ifndef OPENSSL_NO_ERR |
559 |
|
|
#define NUM_SYS_STR_REASONS 127 |
560 |
|
|
#define LEN_SYS_STR_REASON 32 |
561 |
|
|
|
562 |
|
|
static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1]; |
563 |
|
|
/* SYS_str_reasons is filled with copies of strerror() results at |
564 |
|
|
* initialization. |
565 |
|
|
* 'errno' values up to 127 should cover all usual errors, |
566 |
|
|
* others will be displayed numerically by ERR_error_string. |
567 |
|
|
* It is crucial that we have something for each reason code |
568 |
|
|
* that occurs in ERR_str_reasons, or bogus reason strings |
569 |
|
|
* will be returned for SYSerr(), which always gets an errno |
570 |
|
|
* value and never one of those 'standard' reason codes. */ |
571 |
|
|
|
572 |
|
|
static void |
573 |
|
|
build_SYS_str_reasons(void) |
574 |
|
923 |
{ |
575 |
|
|
/* malloc cannot be used here, use static storage instead */ |
576 |
|
|
static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON]; |
577 |
|
|
int i; |
578 |
|
|
static int init = 1; |
579 |
|
|
|
580 |
|
923 |
CRYPTO_r_lock(CRYPTO_LOCK_ERR); |
581 |
✓✓ |
923 |
if (!init) { |
582 |
|
905 |
CRYPTO_r_unlock(CRYPTO_LOCK_ERR); |
583 |
|
905 |
return; |
584 |
|
|
} |
585 |
|
|
|
586 |
|
18 |
CRYPTO_r_unlock(CRYPTO_LOCK_ERR); |
587 |
|
18 |
CRYPTO_w_lock(CRYPTO_LOCK_ERR); |
588 |
✗✓ |
18 |
if (!init) { |
589 |
|
|
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
590 |
|
|
return; |
591 |
|
|
} |
592 |
|
|
|
593 |
✓✓ |
2304 |
for (i = 1; i <= NUM_SYS_STR_REASONS; i++) { |
594 |
|
2286 |
ERR_STRING_DATA *str = &SYS_str_reasons[i - 1]; |
595 |
|
|
|
596 |
|
2286 |
str->error = (unsigned long)i; |
597 |
✓✗ |
2286 |
if (str->string == NULL) { |
598 |
|
|
char (*dest)[LEN_SYS_STR_REASON] = |
599 |
|
2286 |
&(strerror_tab[i - 1]); |
600 |
|
2286 |
const char *src = strerror(i); |
601 |
✓✗ |
2286 |
if (src != NULL) { |
602 |
|
2286 |
strlcpy(*dest, src, sizeof *dest); |
603 |
|
2286 |
str->string = *dest; |
604 |
|
|
} |
605 |
|
|
} |
606 |
✗✓ |
2286 |
if (str->string == NULL) |
607 |
|
|
str->string = "unknown"; |
608 |
|
|
} |
609 |
|
|
|
610 |
|
|
/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, |
611 |
|
|
* as required by ERR_load_strings. */ |
612 |
|
|
|
613 |
|
18 |
init = 0; |
614 |
|
|
|
615 |
|
18 |
CRYPTO_w_unlock(CRYPTO_LOCK_ERR); |
616 |
|
|
} |
617 |
|
|
#endif |
618 |
|
|
|
619 |
|
|
#define err_clear_data(p,i) \ |
620 |
|
|
do { \ |
621 |
|
|
if (((p)->err_data[i] != NULL) && \ |
622 |
|
|
(p)->err_data_flags[i] & ERR_TXT_MALLOCED) { \ |
623 |
|
|
free((p)->err_data[i]); \ |
624 |
|
|
(p)->err_data[i] = NULL; \ |
625 |
|
|
} \ |
626 |
|
|
(p)->err_data_flags[i] = 0; \ |
627 |
|
|
} while(0) |
628 |
|
|
|
629 |
|
|
#define err_clear(p,i) \ |
630 |
|
|
do { \ |
631 |
|
|
(p)->err_flags[i] = 0; \ |
632 |
|
|
(p)->err_buffer[i] = 0; \ |
633 |
|
|
err_clear_data(p, i); \ |
634 |
|
|
(p)->err_file[i] = NULL; \ |
635 |
|
|
(p)->err_line[i] = -1; \ |
636 |
|
|
} while(0) |
637 |
|
|
|
638 |
|
|
static void |
639 |
|
|
ERR_STATE_free(ERR_STATE *s) |
640 |
|
12 |
{ |
641 |
|
|
int i; |
642 |
|
|
|
643 |
✗✓ |
12 |
if (s == NULL) |
644 |
|
|
return; |
645 |
|
|
|
646 |
✓✓ |
204 |
for (i = 0; i < ERR_NUM_ERRORS; i++) { |
647 |
✗✓✗✗
|
192 |
err_clear_data(s, i); |
648 |
|
|
} |
649 |
|
12 |
free(s); |
650 |
|
|
} |
651 |
|
|
|
652 |
|
|
void |
653 |
|
|
ERR_load_ERR_strings(void) |
654 |
|
923 |
{ |
655 |
|
923 |
err_fns_check(); |
656 |
|
|
#ifndef OPENSSL_NO_ERR |
657 |
|
923 |
err_load_strings(0, ERR_str_libraries); |
658 |
|
923 |
err_load_strings(0, ERR_str_reasons); |
659 |
|
923 |
err_load_strings(ERR_LIB_SYS, ERR_str_functs); |
660 |
|
923 |
build_SYS_str_reasons(); |
661 |
|
923 |
err_load_strings(ERR_LIB_SYS, SYS_str_reasons); |
662 |
|
|
#endif |
663 |
|
923 |
} |
664 |
|
|
|
665 |
|
|
static void |
666 |
|
|
err_load_strings(int lib, ERR_STRING_DATA *str) |
667 |
|
4598 |
{ |
668 |
✓✓ |
230783 |
while (str->error) { |
669 |
✓✓ |
221587 |
if (lib) |
670 |
|
126451 |
str->error |= ERR_PACK(lib, 0, 0); |
671 |
|
221587 |
ERRFN(err_set_item)(str); |
672 |
|
221587 |
str++; |
673 |
|
|
} |
674 |
|
4598 |
} |
675 |
|
|
|
676 |
|
|
void |
677 |
|
|
ERR_load_strings(int lib, ERR_STRING_DATA *str) |
678 |
|
906 |
{ |
679 |
|
906 |
ERR_load_ERR_strings(); |
680 |
|
906 |
err_load_strings(lib, str); |
681 |
|
906 |
} |
682 |
|
|
|
683 |
|
|
void |
684 |
|
|
ERR_unload_strings(int lib, ERR_STRING_DATA *str) |
685 |
|
|
{ |
686 |
|
|
while (str->error) { |
687 |
|
|
if (lib) |
688 |
|
|
str->error |= ERR_PACK(lib, 0, 0); |
689 |
|
|
ERRFN(err_del_item)(str); |
690 |
|
|
str++; |
691 |
|
|
} |
692 |
|
|
} |
693 |
|
|
|
694 |
|
|
void |
695 |
|
|
ERR_free_strings(void) |
696 |
|
15 |
{ |
697 |
|
15 |
err_fns_check(); |
698 |
|
15 |
ERRFN(err_del)(); |
699 |
|
15 |
} |
700 |
|
|
|
701 |
|
|
/********************************************************/ |
702 |
|
|
|
703 |
|
|
void |
704 |
|
|
ERR_put_error(int lib, int func, int reason, const char *file, int line) |
705 |
|
455 |
{ |
706 |
|
|
ERR_STATE *es; |
707 |
|
455 |
int save_errno = errno; |
708 |
|
|
|
709 |
|
455 |
es = ERR_get_state(); |
710 |
|
|
|
711 |
|
455 |
es->top = (es->top + 1) % ERR_NUM_ERRORS; |
712 |
✓✓ |
455 |
if (es->top == es->bottom) |
713 |
|
156 |
es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS; |
714 |
|
455 |
es->err_flags[es->top] = 0; |
715 |
|
455 |
es->err_buffer[es->top] = ERR_PACK(lib, func, reason); |
716 |
|
455 |
es->err_file[es->top] = file; |
717 |
|
455 |
es->err_line[es->top] = line; |
718 |
✗✓✗✗
|
455 |
err_clear_data(es, es->top); |
719 |
|
455 |
errno = save_errno; |
720 |
|
455 |
} |
721 |
|
|
|
722 |
|
|
void |
723 |
|
|
ERR_clear_error(void) |
724 |
|
103 |
{ |
725 |
|
|
int i; |
726 |
|
|
ERR_STATE *es; |
727 |
|
|
|
728 |
|
103 |
es = ERR_get_state(); |
729 |
|
|
|
730 |
✓✓ |
1751 |
for (i = 0; i < ERR_NUM_ERRORS; i++) { |
731 |
✓✓✓✗
|
1648 |
err_clear(es, i); |
732 |
|
|
} |
733 |
|
103 |
es->top = es->bottom = 0; |
734 |
|
103 |
} |
735 |
|
|
|
736 |
|
|
|
737 |
|
|
unsigned long |
738 |
|
|
ERR_get_error(void) |
739 |
|
|
{ |
740 |
|
|
return (get_error_values(1, 0, NULL, NULL, NULL, NULL)); |
741 |
|
|
} |
742 |
|
|
|
743 |
|
|
unsigned long |
744 |
|
|
ERR_get_error_line(const char **file, int *line) |
745 |
|
|
{ |
746 |
|
|
return (get_error_values(1, 0, file, line, NULL, NULL)); |
747 |
|
|
} |
748 |
|
|
|
749 |
|
|
unsigned long |
750 |
|
|
ERR_get_error_line_data(const char **file, int *line, |
751 |
|
|
const char **data, int *flags) |
752 |
|
18 |
{ |
753 |
|
18 |
return (get_error_values(1, 0, file, line, data, flags)); |
754 |
|
|
} |
755 |
|
|
|
756 |
|
|
|
757 |
|
|
unsigned long |
758 |
|
|
ERR_peek_error(void) |
759 |
|
|
{ |
760 |
|
|
return (get_error_values(0, 0, NULL, NULL, NULL, NULL)); |
761 |
|
|
} |
762 |
|
|
|
763 |
|
|
unsigned long |
764 |
|
|
ERR_peek_error_line(const char **file, int *line) |
765 |
|
|
{ |
766 |
|
|
return (get_error_values(0, 0, file, line, NULL, NULL)); |
767 |
|
|
} |
768 |
|
|
|
769 |
|
|
unsigned long |
770 |
|
|
ERR_peek_error_line_data(const char **file, int *line, |
771 |
|
|
const char **data, int *flags) |
772 |
|
|
{ |
773 |
|
|
return (get_error_values(0, 0, file, line, data, flags)); |
774 |
|
|
} |
775 |
|
|
|
776 |
|
|
unsigned long |
777 |
|
|
ERR_peek_last_error(void) |
778 |
|
2 |
{ |
779 |
|
2 |
return (get_error_values(0, 1, NULL, NULL, NULL, NULL)); |
780 |
|
|
} |
781 |
|
|
|
782 |
|
|
unsigned long |
783 |
|
|
ERR_peek_last_error_line(const char **file, int *line) |
784 |
|
|
{ |
785 |
|
|
return (get_error_values(0, 1, file, line, NULL, NULL)); |
786 |
|
|
} |
787 |
|
|
|
788 |
|
|
unsigned long |
789 |
|
|
ERR_peek_last_error_line_data(const char **file, int *line, |
790 |
|
|
const char **data, int *flags) |
791 |
|
|
{ |
792 |
|
|
return (get_error_values(0, 1, file, line, data, flags)); |
793 |
|
|
} |
794 |
|
|
|
795 |
|
|
static unsigned long |
796 |
|
|
get_error_values(int inc, int top, const char **file, int *line, |
797 |
|
|
const char **data, int *flags) |
798 |
|
20 |
{ |
799 |
|
20 |
int i = 0; |
800 |
|
|
ERR_STATE *es; |
801 |
|
|
unsigned long ret; |
802 |
|
|
|
803 |
|
20 |
es = ERR_get_state(); |
804 |
|
|
|
805 |
✗✓ |
20 |
if (inc && top) { |
806 |
|
|
if (file) |
807 |
|
|
*file = ""; |
808 |
|
|
if (line) |
809 |
|
|
*line = 0; |
810 |
|
|
if (data) |
811 |
|
|
*data = ""; |
812 |
|
|
if (flags) |
813 |
|
|
*flags = 0; |
814 |
|
|
|
815 |
|
|
return ERR_R_INTERNAL_ERROR; |
816 |
|
|
} |
817 |
|
|
|
818 |
✓✓ |
20 |
if (es->bottom == es->top) |
819 |
|
18 |
return 0; |
820 |
✓✗ |
2 |
if (top) |
821 |
|
2 |
i = es->top; /* last error */ |
822 |
|
|
else |
823 |
|
|
i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */ |
824 |
|
|
|
825 |
|
2 |
ret = es->err_buffer[i]; |
826 |
✗✓ |
2 |
if (inc) { |
827 |
|
|
es->bottom = i; |
828 |
|
|
es->err_buffer[i] = 0; |
829 |
|
|
} |
830 |
|
|
|
831 |
✗✓ |
2 |
if ((file != NULL) && (line != NULL)) { |
832 |
|
|
if (es->err_file[i] == NULL) { |
833 |
|
|
*file = "NA"; |
834 |
|
|
if (line != NULL) |
835 |
|
|
*line = 0; |
836 |
|
|
} else { |
837 |
|
|
*file = es->err_file[i]; |
838 |
|
|
if (line != NULL) |
839 |
|
|
*line = es->err_line[i]; |
840 |
|
|
} |
841 |
|
|
} |
842 |
|
|
|
843 |
✓✗ |
2 |
if (data == NULL) { |
844 |
✗✓ |
2 |
if (inc) { |
845 |
|
|
err_clear_data(es, i); |
846 |
|
|
} |
847 |
|
|
} else { |
848 |
|
|
if (es->err_data[i] == NULL) { |
849 |
|
|
*data = ""; |
850 |
|
|
if (flags != NULL) |
851 |
|
|
*flags = 0; |
852 |
|
|
} else { |
853 |
|
|
*data = es->err_data[i]; |
854 |
|
|
if (flags != NULL) |
855 |
|
|
*flags = es->err_data_flags[i]; |
856 |
|
|
} |
857 |
|
|
} |
858 |
|
2 |
return ret; |
859 |
|
|
} |
860 |
|
|
|
861 |
|
|
void |
862 |
|
|
ERR_error_string_n(unsigned long e, char *buf, size_t len) |
863 |
|
|
{ |
864 |
|
|
char lsbuf[30], fsbuf[30], rsbuf[30]; |
865 |
|
|
const char *ls, *fs, *rs; |
866 |
|
|
int l, f, r, ret; |
867 |
|
|
|
868 |
|
|
l = ERR_GET_LIB(e); |
869 |
|
|
f = ERR_GET_FUNC(e); |
870 |
|
|
r = ERR_GET_REASON(e); |
871 |
|
|
|
872 |
|
|
ls = ERR_lib_error_string(e); |
873 |
|
|
fs = ERR_func_error_string(e); |
874 |
|
|
rs = ERR_reason_error_string(e); |
875 |
|
|
|
876 |
|
|
if (ls == NULL) { |
877 |
|
|
(void) snprintf(lsbuf, sizeof(lsbuf), "lib(%d)", l); |
878 |
|
|
ls = lsbuf; |
879 |
|
|
} |
880 |
|
|
if (fs == NULL) { |
881 |
|
|
(void) snprintf(fsbuf, sizeof(fsbuf), "func(%d)", f); |
882 |
|
|
fs = fsbuf; |
883 |
|
|
} |
884 |
|
|
if (rs == NULL) { |
885 |
|
|
(void) snprintf(rsbuf, sizeof(rsbuf), "reason(%d)", r); |
886 |
|
|
rs = rsbuf; |
887 |
|
|
} |
888 |
|
|
|
889 |
|
|
ret = snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs); |
890 |
|
|
if (ret == -1) |
891 |
|
|
return; /* can't happen, and can't do better if it does */ |
892 |
|
|
if (ret >= len) { |
893 |
|
|
/* output may be truncated; make sure we always have 5 |
894 |
|
|
* colon-separated fields, i.e. 4 colons ... */ |
895 |
|
|
#define NUM_COLONS 4 |
896 |
|
|
if (len > NUM_COLONS) /* ... if possible */ |
897 |
|
|
{ |
898 |
|
|
int i; |
899 |
|
|
char *s = buf; |
900 |
|
|
|
901 |
|
|
for (i = 0; i < NUM_COLONS; i++) { |
902 |
|
|
char *colon = strchr(s, ':'); |
903 |
|
|
if (colon == NULL || |
904 |
|
|
colon > &buf[len - 1] - NUM_COLONS + i) { |
905 |
|
|
/* set colon no. i at last possible position |
906 |
|
|
* (buf[len-1] is the terminating 0)*/ |
907 |
|
|
colon = &buf[len - 1] - NUM_COLONS + i; |
908 |
|
|
*colon = ':'; |
909 |
|
|
} |
910 |
|
|
s = colon + 1; |
911 |
|
|
} |
912 |
|
|
} |
913 |
|
|
} |
914 |
|
|
} |
915 |
|
|
|
916 |
|
|
/* BAD for multi-threading: uses a local buffer if ret == NULL */ |
917 |
|
|
/* ERR_error_string_n should be used instead for ret != NULL |
918 |
|
|
* as ERR_error_string cannot know how large the buffer is */ |
919 |
|
|
char * |
920 |
|
|
ERR_error_string(unsigned long e, char *ret) |
921 |
|
|
{ |
922 |
|
|
static char buf[256]; |
923 |
|
|
|
924 |
|
|
if (ret == NULL) |
925 |
|
|
ret = buf; |
926 |
|
|
ERR_error_string_n(e, ret, 256); |
927 |
|
|
|
928 |
|
|
return ret; |
929 |
|
|
} |
930 |
|
|
|
931 |
|
|
LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void) |
932 |
|
|
{ |
933 |
|
|
err_fns_check(); |
934 |
|
|
return ERRFN(err_get)(0); |
935 |
|
|
} |
936 |
|
|
|
937 |
|
|
LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void) |
938 |
|
|
{ |
939 |
|
|
err_fns_check(); |
940 |
|
|
return ERRFN(thread_get)(0); |
941 |
|
|
} |
942 |
|
|
|
943 |
|
|
void |
944 |
|
|
ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash) |
945 |
|
|
{ |
946 |
|
|
err_fns_check(); |
947 |
|
|
ERRFN(thread_release)(hash); |
948 |
|
|
} |
949 |
|
|
|
950 |
|
|
const char * |
951 |
|
|
ERR_lib_error_string(unsigned long e) |
952 |
|
|
{ |
953 |
|
|
ERR_STRING_DATA d, *p; |
954 |
|
|
unsigned long l; |
955 |
|
|
|
956 |
|
|
err_fns_check(); |
957 |
|
|
l = ERR_GET_LIB(e); |
958 |
|
|
d.error = ERR_PACK(l, 0, 0); |
959 |
|
|
p = ERRFN(err_get_item)(&d); |
960 |
|
|
return ((p == NULL) ? NULL : p->string); |
961 |
|
|
} |
962 |
|
|
|
963 |
|
|
const char * |
964 |
|
|
ERR_func_error_string(unsigned long e) |
965 |
|
453 |
{ |
966 |
|
|
ERR_STRING_DATA d, *p; |
967 |
|
|
unsigned long l, f; |
968 |
|
|
|
969 |
|
453 |
err_fns_check(); |
970 |
|
453 |
l = ERR_GET_LIB(e); |
971 |
|
453 |
f = ERR_GET_FUNC(e); |
972 |
|
453 |
d.error = ERR_PACK(l, f, 0); |
973 |
|
453 |
p = ERRFN(err_get_item)(&d); |
974 |
✗✓ |
453 |
return ((p == NULL) ? NULL : p->string); |
975 |
|
|
} |
976 |
|
|
|
977 |
|
|
const char * |
978 |
|
|
ERR_reason_error_string(unsigned long e) |
979 |
|
|
{ |
980 |
|
|
ERR_STRING_DATA d, *p = NULL; |
981 |
|
|
unsigned long l, r; |
982 |
|
|
|
983 |
|
|
err_fns_check(); |
984 |
|
|
l = ERR_GET_LIB(e); |
985 |
|
|
r = ERR_GET_REASON(e); |
986 |
|
|
d.error = ERR_PACK(l, 0, r); |
987 |
|
|
p = ERRFN(err_get_item)(&d); |
988 |
|
|
if (!p) { |
989 |
|
|
d.error = ERR_PACK(0, 0, r); |
990 |
|
|
p = ERRFN(err_get_item)(&d); |
991 |
|
|
} |
992 |
|
|
return ((p == NULL) ? NULL : p->string); |
993 |
|
|
} |
994 |
|
|
|
995 |
|
|
void |
996 |
|
|
ERR_remove_thread_state(const CRYPTO_THREADID *id) |
997 |
|
17 |
{ |
998 |
|
|
ERR_STATE tmp; |
999 |
|
|
|
1000 |
✗✓ |
17 |
if (id) |
1001 |
|
|
CRYPTO_THREADID_cpy(&tmp.tid, id); |
1002 |
|
|
else |
1003 |
|
17 |
CRYPTO_THREADID_current(&tmp.tid); |
1004 |
|
17 |
err_fns_check(); |
1005 |
|
|
/* thread_del_item automatically destroys the LHASH if the number of |
1006 |
|
|
* items reaches zero. */ |
1007 |
|
17 |
ERRFN(thread_del_item)(&tmp); |
1008 |
|
17 |
} |
1009 |
|
|
|
1010 |
|
|
#ifndef OPENSSL_NO_DEPRECATED |
1011 |
|
|
void |
1012 |
|
|
ERR_remove_state(unsigned long pid) |
1013 |
|
|
{ |
1014 |
|
|
ERR_remove_thread_state(NULL); |
1015 |
|
|
} |
1016 |
|
|
#endif |
1017 |
|
|
|
1018 |
|
|
ERR_STATE * |
1019 |
|
|
ERR_get_state(void) |
1020 |
|
673 |
{ |
1021 |
|
|
static ERR_STATE fallback; |
1022 |
|
673 |
ERR_STATE *ret, tmp, *tmpp = NULL; |
1023 |
|
|
int i; |
1024 |
|
|
CRYPTO_THREADID tid; |
1025 |
|
|
|
1026 |
|
673 |
err_fns_check(); |
1027 |
|
673 |
CRYPTO_THREADID_current(&tid); |
1028 |
|
673 |
CRYPTO_THREADID_cpy(&tmp.tid, &tid); |
1029 |
|
673 |
ret = ERRFN(thread_get_item)(&tmp); |
1030 |
|
|
|
1031 |
|
|
/* ret == the error state, if NULL, make a new one */ |
1032 |
✓✓ |
673 |
if (ret == NULL) { |
1033 |
|
20 |
ret = malloc(sizeof(ERR_STATE)); |
1034 |
✗✓ |
20 |
if (ret == NULL) |
1035 |
|
|
return (&fallback); |
1036 |
|
20 |
CRYPTO_THREADID_cpy(&ret->tid, &tid); |
1037 |
|
20 |
ret->top = 0; |
1038 |
|
20 |
ret->bottom = 0; |
1039 |
✓✓ |
340 |
for (i = 0; i < ERR_NUM_ERRORS; i++) { |
1040 |
|
320 |
ret->err_data[i] = NULL; |
1041 |
|
320 |
ret->err_data_flags[i] = 0; |
1042 |
|
|
} |
1043 |
|
20 |
tmpp = ERRFN(thread_set_item)(ret); |
1044 |
|
|
/* To check if insertion failed, do a get. */ |
1045 |
✗✓ |
20 |
if (ERRFN(thread_get_item)(ret) != ret) { |
1046 |
|
|
ERR_STATE_free(ret); /* could not insert it */ |
1047 |
|
|
return (&fallback); |
1048 |
|
|
} |
1049 |
|
|
/* If a race occured in this function and we came second, tmpp |
1050 |
|
|
* is the first one that we just replaced. */ |
1051 |
✗✓ |
20 |
if (tmpp) |
1052 |
|
|
ERR_STATE_free(tmpp); |
1053 |
|
|
} |
1054 |
|
673 |
return ret; |
1055 |
|
|
} |
1056 |
|
|
|
1057 |
|
|
int |
1058 |
|
|
ERR_get_next_error_library(void) |
1059 |
|
|
{ |
1060 |
|
|
err_fns_check(); |
1061 |
|
|
return ERRFN(get_next_lib)(); |
1062 |
|
|
} |
1063 |
|
|
|
1064 |
|
|
void |
1065 |
|
|
ERR_set_error_data(char *data, int flags) |
1066 |
|
95 |
{ |
1067 |
|
|
ERR_STATE *es; |
1068 |
|
|
int i; |
1069 |
|
|
|
1070 |
|
95 |
es = ERR_get_state(); |
1071 |
|
|
|
1072 |
|
95 |
i = es->top; |
1073 |
✗✓ |
95 |
if (i == 0) |
1074 |
|
|
i = ERR_NUM_ERRORS - 1; |
1075 |
|
|
|
1076 |
✗✓✗✗
|
95 |
err_clear_data(es, i); |
1077 |
|
95 |
es->err_data[i] = data; |
1078 |
|
95 |
es->err_data_flags[i] = flags; |
1079 |
|
95 |
} |
1080 |
|
|
|
1081 |
|
|
void |
1082 |
|
95 |
ERR_asprintf_error_data(char * format, ...) { |
1083 |
|
95 |
char *errbuf = NULL; |
1084 |
|
|
va_list ap; |
1085 |
|
|
int r; |
1086 |
|
|
|
1087 |
|
95 |
va_start(ap, format); |
1088 |
|
95 |
r = vasprintf(&errbuf, format, ap); |
1089 |
|
95 |
va_end(ap); |
1090 |
✗✓ |
95 |
if (r == -1) |
1091 |
|
|
ERR_set_error_data("malloc failed", ERR_TXT_STRING); |
1092 |
|
|
else |
1093 |
|
95 |
ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING); |
1094 |
|
95 |
} |
1095 |
|
|
void |
1096 |
|
|
ERR_add_error_data(int num, ...) |
1097 |
|
|
{ |
1098 |
|
|
va_list args; |
1099 |
|
|
va_start(args, num); |
1100 |
|
|
ERR_add_error_vdata(num, args); |
1101 |
|
|
va_end(args); |
1102 |
|
|
} |
1103 |
|
|
|
1104 |
|
|
void |
1105 |
|
|
ERR_add_error_vdata(int num, va_list args) |
1106 |
|
|
{ |
1107 |
|
|
char format[129]; |
1108 |
|
|
char *errbuf; |
1109 |
|
|
int i; |
1110 |
|
|
|
1111 |
|
|
format[0] = '\0'; |
1112 |
|
|
for (i = 0; i < num; i++) { |
1113 |
|
|
if (strlcat(format, "%s", sizeof(format)) >= sizeof(format)) { |
1114 |
|
|
ERR_set_error_data("too many errors", ERR_TXT_STRING); |
1115 |
|
|
return; |
1116 |
|
|
} |
1117 |
|
|
} |
1118 |
|
|
if (vasprintf(&errbuf, format, args) == -1) |
1119 |
|
|
ERR_set_error_data("malloc failed", ERR_TXT_STRING); |
1120 |
|
|
else |
1121 |
|
|
ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING); |
1122 |
|
|
} |
1123 |
|
|
|
1124 |
|
|
int |
1125 |
|
|
ERR_set_mark(void) |
1126 |
|
|
{ |
1127 |
|
|
ERR_STATE *es; |
1128 |
|
|
|
1129 |
|
|
es = ERR_get_state(); |
1130 |
|
|
|
1131 |
|
|
if (es->bottom == es->top) |
1132 |
|
|
return 0; |
1133 |
|
|
es->err_flags[es->top] |= ERR_FLAG_MARK; |
1134 |
|
|
return 1; |
1135 |
|
|
} |
1136 |
|
|
|
1137 |
|
|
int |
1138 |
|
|
ERR_pop_to_mark(void) |
1139 |
|
|
{ |
1140 |
|
|
ERR_STATE *es; |
1141 |
|
|
|
1142 |
|
|
es = ERR_get_state(); |
1143 |
|
|
|
1144 |
|
|
while (es->bottom != es->top && |
1145 |
|
|
(es->err_flags[es->top] & ERR_FLAG_MARK) == 0) { |
1146 |
|
|
err_clear(es, es->top); |
1147 |
|
|
es->top -= 1; |
1148 |
|
|
if (es->top == -1) |
1149 |
|
|
es->top = ERR_NUM_ERRORS - 1; |
1150 |
|
|
} |
1151 |
|
|
|
1152 |
|
|
if (es->bottom == es->top) |
1153 |
|
|
return 0; |
1154 |
|
|
es->err_flags[es->top]&=~ERR_FLAG_MARK; |
1155 |
|
|
return 1; |
1156 |
|
|
} |