]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/err/err.c
Use new-style system-id macros everywhere possible. I hope I haven't
[thirdparty/openssl.git] / crypto / err / err.c
CommitLineData
d02b48c6 1/* crypto/err/err.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
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 */
0a150c5c
BM
58/* ====================================================================
59 * Copyright (c) 1998-2000 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 */
d02b48c6
RE
111
112#include <stdio.h>
4565c3e3 113#include <stdarg.h>
0a150c5c 114#include <string.h>
ec577822
BM
115#include <openssl/lhash.h>
116#include <openssl/crypto.h>
d02b48c6 117#include "cryptlib.h"
ec577822 118#include <openssl/buffer.h>
e5c84d51 119#include <openssl/bio.h>
dcba2534 120#include <openssl/err.h>
d02b48c6
RE
121
122
123static LHASH *error_hash=NULL;
124static LHASH *thread_hash=NULL;
125
d0fa136c 126/* static unsigned long err_hash(ERR_STRING_DATA *a); */
8d28d5f8 127static unsigned long err_hash(const void *a_void);
d0fa136c 128/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
8d28d5f8 129static int err_cmp(const void *a_void, const void *b_void);
d0fa136c 130/* static unsigned long pid_hash(ERR_STATE *pid); */
8d28d5f8 131static unsigned long pid_hash(const void *pid_void);
d0fa136c 132/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
8d28d5f8 133static int pid_cmp(const void *a_void,const void *pid_void);
e778802f
BL
134static unsigned long get_error_values(int inc,const char **file,int *line,
135 const char **data,int *flags);
97b17195 136
58964a49 137static void ERR_STATE_free(ERR_STATE *s);
cf1b7d96 138#ifndef OPENSSL_NO_ERR
d02b48c6
RE
139static ERR_STRING_DATA ERR_str_libraries[]=
140 {
141{ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"},
142{ERR_PACK(ERR_LIB_SYS,0,0) ,"system library"},
143{ERR_PACK(ERR_LIB_BN,0,0) ,"bignum routines"},
144{ERR_PACK(ERR_LIB_RSA,0,0) ,"rsa routines"},
b4b41f48 145{ERR_PACK(ERR_LIB_DSA,0,0) ,"dsa routines"},
d02b48c6
RE
146{ERR_PACK(ERR_LIB_DH,0,0) ,"Diffie-Hellman routines"},
147{ERR_PACK(ERR_LIB_EVP,0,0) ,"digital envelope routines"},
148{ERR_PACK(ERR_LIB_BUF,0,0) ,"memory buffer routines"},
149{ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"},
150{ERR_PACK(ERR_LIB_OBJ,0,0) ,"object identifier routines"},
151{ERR_PACK(ERR_LIB_PEM,0,0) ,"PEM routines"},
152{ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"},
153{ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"},
657e60fa 154{ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"},
d02b48c6
RE
155{ERR_PACK(ERR_LIB_METH,0,0) ,"X509 lookup 'method' routines"},
156{ERR_PACK(ERR_LIB_SSL,0,0) ,"SSL routines"},
157{ERR_PACK(ERR_LIB_RSAREF,0,0) ,"RSAref routines"},
158{ERR_PACK(ERR_LIB_PROXY,0,0) ,"Proxy routines"},
159{ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"},
160{ERR_PACK(ERR_LIB_PKCS7,0,0) ,"PKCS7 routines"},
834eeef9 161{ERR_PACK(ERR_LIB_X509V3,0,0) ,"X509 V3 routines"},
67d5ac03 162{ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"},
eb952088 163{ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"},
9ec0126e 164{ERR_PACK(ERR_LIB_DSO,0,0) ,"DSO support routines"},
5270e702 165{ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"},
8e961835 166{ERR_PACK(ERR_LIB_OCSP,0,0) ,"OCSP routines"},
d02b48c6
RE
167{0,NULL},
168 };
169
170static ERR_STRING_DATA ERR_str_functs[]=
171 {
172 {ERR_PACK(0,SYS_F_FOPEN,0), "fopen"},
173 {ERR_PACK(0,SYS_F_CONNECT,0), "connect"},
174 {ERR_PACK(0,SYS_F_GETSERVBYNAME,0), "getservbyname"},
175 {ERR_PACK(0,SYS_F_SOCKET,0), "socket"},
176 {ERR_PACK(0,SYS_F_IOCTLSOCKET,0), "ioctlsocket"},
177 {ERR_PACK(0,SYS_F_BIND,0), "bind"},
178 {ERR_PACK(0,SYS_F_LISTEN,0), "listen"},
179 {ERR_PACK(0,SYS_F_ACCEPT,0), "accept"},
bc36ee62 180#ifdef OPENSSL_SYS_WINDOWS
d02b48c6
RE
181 {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"},
182#endif
a40f6dce 183 {ERR_PACK(0,SYS_F_OPENDIR,0), "opendir"},
d02b48c6
RE
184 {0,NULL},
185 };
186
187static ERR_STRING_DATA ERR_str_reasons[]=
188 {
189{ERR_R_FATAL ,"fatal"},
190{ERR_R_SYS_LIB ,"system lib"},
191{ERR_R_BN_LIB ,"BN lib"},
192{ERR_R_RSA_LIB ,"RSA lib"},
193{ERR_R_DH_LIB ,"DH lib"},
194{ERR_R_EVP_LIB ,"EVP lib"},
195{ERR_R_BUF_LIB ,"BUF lib"},
196{ERR_R_BIO_LIB ,"BIO lib"},
197{ERR_R_OBJ_LIB ,"OBJ lib"},
198{ERR_R_PEM_LIB ,"PEM lib"},
199{ERR_R_X509_LIB ,"X509 lib"},
200{ERR_R_METH_LIB ,"METH lib"},
201{ERR_R_ASN1_LIB ,"ASN1 lib"},
202{ERR_R_CONF_LIB ,"CONF lib"},
203{ERR_R_SSL_LIB ,"SSL lib"},
204{ERR_R_PROXY_LIB ,"PROXY lib"},
205{ERR_R_BIO_LIB ,"BIO lib"},
206{ERR_R_PKCS7_LIB ,"PKCS7 lib"},
67d5ac03 207{ERR_R_PKCS12_LIB ,"PKCS12 lib"},
d02b48c6 208{ERR_R_MALLOC_FAILURE ,"Malloc failure"},
d9f0016b 209{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a function you should not call"},
dfeab068
RE
210{ERR_R_PASSED_NULL_PARAMETER ,"passed a null parameter"},
211{ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"},
212{ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"},
213{ERR_R_BAD_GET_ASN1_OBJECT_CALL ,"bad get asn1 object call"},
214{ERR_R_EXPECTING_AN_ASN1_SEQUENCE ,"expecting an asn1 sequence"},
215{ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"},
216{ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"},
9ec0126e 217{ERR_R_DSO_LIB ,"DSO lib"},
5270e702 218{ERR_R_ENGINE_LIB ,"ENGINE lib"},
dfeab068 219
d02b48c6
RE
220{0,NULL},
221 };
0a150c5c
BM
222
223
224#define NUM_SYS_STR_REASONS 127
225#define LEN_SYS_STR_REASON 32
226
227static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
228/* SYS_str_reasons is filled with copies of strerror() results at
229 * initialization.
230 * 'errno' values up to 127 should cover all usual errors,
231 * others will be displayed numerically by ERR_error_string.
232 * It is crucial that we have something for each reason code
233 * that occurs in ERR_str_reasons, or bogus reason strings
234 * will be returned for SYSerr(), which always gets an errno
235 * value and never one of those 'standard' reason codes. */
236
237static void build_SYS_str_reasons()
238 {
26a3a48d 239 /* OPENSSL_malloc cannot be used here, use static storage instead */
0a150c5c
BM
240 static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
241 int i;
242
243 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
244
245 for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
246 {
247 ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
248
249 str->error = (unsigned long)i;
250 if (str->string == NULL)
251 {
252 char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
253 char *src = strerror(i);
254 if (src != NULL)
255 {
256 strncpy(*dest, src, sizeof *dest);
257 (*dest)[sizeof *dest - 1] = '\0';
258 str->string = *dest;
259 }
260 }
261 if (str->string == NULL)
262 str->string = "unknown";
263 }
264
265 /* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
266 * as required by ERR_load_strings. */
267
268 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
269 }
d02b48c6
RE
270#endif
271
58964a49
RE
272#define err_clear_data(p,i) \
273 if (((p)->err_data[i] != NULL) && \
274 (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
275 { \
26a3a48d 276 OPENSSL_free((p)->err_data[i]); \
58964a49
RE
277 (p)->err_data[i]=NULL; \
278 } \
279 (p)->err_data_flags[i]=0;
280
6b691a5c 281static void ERR_STATE_free(ERR_STATE *s)
58964a49
RE
282 {
283 int i;
284
e03ddfae
BL
285 if(s == NULL)
286 return;
287
58964a49
RE
288 for (i=0; i<ERR_NUM_ERRORS; i++)
289 {
290 err_clear_data(s,i);
291 }
26a3a48d 292 OPENSSL_free(s);
58964a49
RE
293 }
294
6b691a5c 295void ERR_load_ERR_strings(void)
d02b48c6
RE
296 {
297 static int init=1;
298
299 if (init)
300 {
301 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
302 if (init == 0)
303 {
304 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
305 return;
306 }
d02b48c6
RE
307 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
308
cf1b7d96 309#ifndef OPENSSL_NO_ERR
d02b48c6
RE
310 ERR_load_strings(0,ERR_str_libraries);
311 ERR_load_strings(0,ERR_str_reasons);
312 ERR_load_strings(ERR_LIB_SYS,ERR_str_functs);
0a150c5c
BM
313 build_SYS_str_reasons();
314 ERR_load_strings(ERR_LIB_SYS,SYS_str_reasons);
d02b48c6 315#endif
0a150c5c 316 init=0;
d02b48c6
RE
317 }
318 }
319
6b691a5c 320void ERR_load_strings(int lib, ERR_STRING_DATA *str)
d02b48c6
RE
321 {
322 if (error_hash == NULL)
323 {
324 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
d0fa136c 325 error_hash=lh_new(err_hash, err_cmp);
d02b48c6
RE
326 if (error_hash == NULL)
327 {
328 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
329 return;
330 }
331 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
332
333 ERR_load_ERR_strings();
334 }
335
336 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
337 while (str->error)
338 {
339 str->error|=ERR_PACK(lib,0,0);
9d1a01be 340 lh_insert(error_hash,str);
d02b48c6
RE
341 str++;
342 }
343 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
344 }
345
6b691a5c 346void ERR_free_strings(void)
d02b48c6
RE
347 {
348 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
349
350 if (error_hash != NULL)
351 {
352 lh_free(error_hash);
353 error_hash=NULL;
354 }
355
356 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
357 }
358
58964a49
RE
359/********************************************************/
360
6b691a5c
UM
361void ERR_put_error(int lib, int func, int reason, const char *file,
362 int line)
d02b48c6
RE
363 {
364 ERR_STATE *es;
365
a53955d8
UM
366#ifdef _OSD_POSIX
367 /* In the BS2000-OSD POSIX subsystem, the compiler generates
368 * path names in the form "*POSIX(/etc/passwd)".
369 * This dirty hack strips them to something sensible.
370 * @@@ We shouldn't modify a const string, though.
371 */
372 if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
373 char *end;
374
375 /* Skip the "*POSIX(" prefix */
376 file += sizeof("*POSIX(")-1;
377 end = &file[strlen(file)-1];
378 if (*end == ')')
379 *end = '\0';
380 /* Optional: use the basename of the path only. */
381 if ((end = strrchr(file, '/')) != NULL)
382 file = &end[1];
383 }
384#endif
d02b48c6
RE
385 es=ERR_get_state();
386
387 es->top=(es->top+1)%ERR_NUM_ERRORS;
388 if (es->top == es->bottom)
389 es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
390 es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
391 es->err_file[es->top]=file;
392 es->err_line[es->top]=line;
58964a49 393 err_clear_data(es,es->top);
d02b48c6
RE
394 }
395
6b691a5c 396void ERR_clear_error(void)
d02b48c6 397 {
d02b48c6
RE
398 ERR_STATE *es;
399
400 es=ERR_get_state();
401
58964a49
RE
402#if 0
403 /* hmm... is this needed */
d02b48c6
RE
404 for (i=0; i<ERR_NUM_ERRORS; i++)
405 {
406 es->err_buffer[i]=0;
407 es->err_file[i]=NULL;
408 es->err_line[i]= -1;
58964a49 409 err_clear_data(es,i);
d02b48c6 410 }
58964a49 411#endif
d02b48c6
RE
412 es->top=es->bottom=0;
413 }
414
d02b48c6 415
6b691a5c 416unsigned long ERR_get_error(void)
58964a49 417 { return(get_error_values(1,NULL,NULL,NULL,NULL)); }
d02b48c6 418
6b691a5c
UM
419unsigned long ERR_get_error_line(const char **file,
420 int *line)
58964a49 421 { return(get_error_values(1,file,line,NULL,NULL)); }
d02b48c6 422
6b691a5c
UM
423unsigned long ERR_get_error_line_data(const char **file, int *line,
424 const char **data, int *flags)
425 { return(get_error_values(1,file,line,
426 data,flags)); }
d02b48c6 427
6b691a5c 428unsigned long ERR_peek_error(void)
58964a49 429 { return(get_error_values(0,NULL,NULL,NULL,NULL)); }
d02b48c6 430
6b691a5c
UM
431unsigned long ERR_peek_error_line(const char **file,
432 int *line)
58964a49 433 { return(get_error_values(0,file,line,NULL,NULL)); }
d02b48c6 434
6b691a5c
UM
435unsigned long ERR_peek_error_line_data(const char **file, int *line,
436 const char **data, int *flags)
437 { return(get_error_values(0,file,line,
438 data,flags)); }
439
440static unsigned long get_error_values(int inc, const char **file, int *line,
441 const char **data, int *flags)
58964a49
RE
442 {
443 int i=0;
d02b48c6 444 ERR_STATE *es;
58964a49 445 unsigned long ret;
d02b48c6
RE
446
447 es=ERR_get_state();
448
58964a49 449 if (es->bottom == es->top) return(0);
d02b48c6 450 i=(es->bottom+1)%ERR_NUM_ERRORS;
58964a49
RE
451
452 ret=es->err_buffer[i];
453 if (inc)
d02b48c6 454 {
58964a49
RE
455 es->bottom=i;
456 es->err_buffer[i]=0;
d02b48c6 457 }
58964a49
RE
458
459 if ((file != NULL) && (line != NULL))
d02b48c6 460 {
58964a49
RE
461 if (es->err_file[i] == NULL)
462 {
463 *file="NA";
464 if (line != NULL) *line=0;
465 }
466 else
467 {
468 *file=es->err_file[i];
469 if (line != NULL) *line=es->err_line[i];
470 }
d02b48c6 471 }
d02b48c6 472
58964a49
RE
473 if (data != NULL)
474 {
475 if (es->err_data[i] == NULL)
476 {
477 *data="";
478 if (flags != NULL) *flags=0;
479 }
480 else
481 {
482 *data=es->err_data[i];
483 if (flags != NULL) *flags=es->err_data_flags[i];
484 }
485 }
d02b48c6
RE
486 return(ret);
487 }
488
e5c84d51 489void ERR_error_string_n(unsigned long e, char *buf, size_t len)
d02b48c6 490 {
e5c84d51 491 char lsbuf[64], fsbuf[64], rsbuf[64];
e778802f 492 const char *ls,*fs,*rs;
d02b48c6 493 unsigned long l,f,r;
d02b48c6
RE
494
495 l=ERR_GET_LIB(e);
496 f=ERR_GET_FUNC(e);
497 r=ERR_GET_REASON(e);
498
499 ls=ERR_lib_error_string(e);
500 fs=ERR_func_error_string(e);
501 rs=ERR_reason_error_string(e);
502
e5c84d51
BM
503 if (ls == NULL)
504 BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
d02b48c6 505 if (fs == NULL)
e5c84d51 506 BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
d02b48c6 507 if (rs == NULL)
e5c84d51
BM
508 BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
509
510 BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf,
511 fs?fs:fsbuf, rs?rs:rsbuf);
512 if (strlen(buf) == len-1)
513 {
514 /* output may be truncated; make sure we always have 5
515 * colon-separated fields, i.e. 4 colons ... */
516#define NUM_COLONS 4
517 if (len > NUM_COLONS) /* ... if possible */
518 {
519 int i;
520 char *s = buf;
521
522 for (i = 0; i < NUM_COLONS; i++)
523 {
524 char *colon = strchr(s, ':');
525 if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
526 {
527 /* set colon no. i at last possible position
528 * (buf[len-1] is the terminating 0)*/
529 colon = &buf[len-1] - NUM_COLONS + i;
530 *colon = ':';
531 }
532 s = colon + 1;
533 }
534 }
535 }
536 }
537
538/* BAD for multi-threading: uses a local buffer if ret == NULL */
539/* ERR_error_string_n should be used instead for ret != NULL
540 * as ERR_error_string cannot know how large the buffer is */
541char *ERR_error_string(unsigned long e, char *ret)
542 {
543 static char buf[256];
544
545 if (ret == NULL) ret=buf;
065866b2 546 ERR_error_string_n(e, ret, 256);
d02b48c6
RE
547
548 return(ret);
549 }
550
6b691a5c 551LHASH *ERR_get_string_table(void)
d02b48c6
RE
552 {
553 return(error_hash);
554 }
555
dcba2534 556/* not thread-safe */
6b691a5c 557LHASH *ERR_get_err_state_table(void)
d02b48c6
RE
558 {
559 return(thread_hash);
560 }
561
6b691a5c 562const char *ERR_lib_error_string(unsigned long e)
d02b48c6
RE
563 {
564 ERR_STRING_DATA d,*p=NULL;
565 unsigned long l;
566
567 l=ERR_GET_LIB(e);
568
2d789604 569 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
570
571 if (error_hash != NULL)
572 {
573 d.error=ERR_PACK(l,0,0);
9d1a01be 574 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
d02b48c6
RE
575 }
576
2d789604 577 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
578
579 return((p == NULL)?NULL:p->string);
580 }
581
6b691a5c 582const char *ERR_func_error_string(unsigned long e)
d02b48c6
RE
583 {
584 ERR_STRING_DATA d,*p=NULL;
585 unsigned long l,f;
586
587 l=ERR_GET_LIB(e);
588 f=ERR_GET_FUNC(e);
589
2d789604 590 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
591
592 if (error_hash != NULL)
593 {
594 d.error=ERR_PACK(l,f,0);
9d1a01be 595 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
d02b48c6
RE
596 }
597
2d789604 598 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
599
600 return((p == NULL)?NULL:p->string);
601 }
602
6b691a5c 603const char *ERR_reason_error_string(unsigned long e)
d02b48c6
RE
604 {
605 ERR_STRING_DATA d,*p=NULL;
606 unsigned long l,r;
607
608 l=ERR_GET_LIB(e);
609 r=ERR_GET_REASON(e);
610
2d789604 611 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
612
613 if (error_hash != NULL)
614 {
615 d.error=ERR_PACK(l,0,r);
9d1a01be 616 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
d02b48c6
RE
617 if (p == NULL)
618 {
619 d.error=ERR_PACK(0,0,r);
9d1a01be 620 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
d02b48c6
RE
621 }
622 }
623
2d789604 624 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
d02b48c6
RE
625
626 return((p == NULL)?NULL:p->string);
627 }
628
d0fa136c 629/* static unsigned long err_hash(ERR_STRING_DATA *a) */
8d28d5f8 630static unsigned long err_hash(const void *a_void)
d02b48c6
RE
631 {
632 unsigned long ret,l;
633
d0fa136c 634 l=((ERR_STRING_DATA *)a_void)->error;
d02b48c6
RE
635 ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
636 return(ret^ret%19*13);
637 }
638
d0fa136c 639/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
8d28d5f8 640static int err_cmp(const void *a_void, const void *b_void)
d02b48c6 641 {
d0fa136c
GT
642 return((int)(((ERR_STRING_DATA *)a_void)->error -
643 ((ERR_STRING_DATA *)b_void)->error));
d02b48c6
RE
644 }
645
d0fa136c 646/* static unsigned long pid_hash(ERR_STATE *a) */
8d28d5f8 647static unsigned long pid_hash(const void *a_void)
d02b48c6 648 {
d0fa136c 649 return(((ERR_STATE *)a_void)->pid*13);
d02b48c6
RE
650 }
651
d0fa136c 652/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
8d28d5f8 653static int pid_cmp(const void *a_void, const void *b_void)
d02b48c6 654 {
d0fa136c
GT
655 return((int)((long)((ERR_STATE *)a_void)->pid -
656 (long)((ERR_STATE *)b_void)->pid));
d02b48c6
RE
657 }
658
6b691a5c 659void ERR_remove_state(unsigned long pid)
d02b48c6 660 {
033d001e 661 ERR_STATE *p = NULL,tmp;
d02b48c6
RE
662
663 if (thread_hash == NULL)
664 return;
665 if (pid == 0)
666 pid=(unsigned long)CRYPTO_thread_id();
667 tmp.pid=pid;
668 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
34f0fe9d 669 if (thread_hash)
dcba2534 670 {
34f0fe9d
RL
671 p=(ERR_STATE *)lh_delete(thread_hash,&tmp);
672 if (lh_num_items(thread_hash) == 0)
673 {
674 /* make sure we don't leak memory */
675 lh_free(thread_hash);
676 thread_hash = NULL;
677 }
dcba2534 678 }
d02b48c6 679 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
58964a49
RE
680
681 if (p != NULL) ERR_STATE_free(p);
d02b48c6
RE
682 }
683
6b691a5c 684ERR_STATE *ERR_get_state(void)
d02b48c6
RE
685 {
686 static ERR_STATE fallback;
aa9fb57b 687 ERR_STATE *ret=NULL,tmp,*tmpp=NULL;
dcba2534 688 int thread_state_exists;
58964a49 689 int i;
d02b48c6
RE
690 unsigned long pid;
691
692 pid=(unsigned long)CRYPTO_thread_id();
693
2d789604 694 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
dcba2534 695 if (thread_hash != NULL)
d02b48c6
RE
696 {
697 tmp.pid=pid;
9d1a01be 698 ret=(ERR_STATE *)lh_retrieve(thread_hash,&tmp);
d02b48c6 699 }
2d789604 700 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
d02b48c6
RE
701
702 /* ret == the error state, if NULL, make a new one */
703 if (ret == NULL)
704 {
26a3a48d 705 ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
d02b48c6
RE
706 if (ret == NULL) return(&fallback);
707 ret->pid=pid;
708 ret->top=0;
709 ret->bottom=0;
58964a49
RE
710 for (i=0; i<ERR_NUM_ERRORS; i++)
711 {
712 ret->err_data[i]=NULL;
713 ret->err_data_flags[i]=0;
714 }
dcba2534 715
d02b48c6 716 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
dcba2534
BM
717
718 /* no entry yet in thread_hash for current thread -
719 * thus, it may have changed since we last looked at it */
720 if (thread_hash == NULL)
d0fa136c 721 thread_hash = lh_new(pid_hash, pid_cmp);
dcba2534
BM
722 if (thread_hash == NULL)
723 thread_state_exists = 0; /* allocation error */
724 else
725 {
726 tmpp=(ERR_STATE *)lh_insert(thread_hash,ret);
727 thread_state_exists = 1;
728 }
729
d02b48c6 730 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
dcba2534
BM
731
732 if (!thread_state_exists)
733 {
734 ERR_STATE_free(ret); /* could not insert it */
735 return(&fallback);
736 }
737
d02b48c6 738 if (tmpp != NULL) /* old entry - should not happen */
58964a49
RE
739 {
740 ERR_STATE_free(tmpp);
741 }
d02b48c6
RE
742 }
743 return(ret);
744 }
745
6b691a5c 746int ERR_get_next_error_library(void)
58964a49
RE
747 {
748 static int value=ERR_LIB_USER;
749
750 return(value++);
751 }
752
6b691a5c 753void ERR_set_error_data(char *data, int flags)
58964a49
RE
754 {
755 ERR_STATE *es;
756 int i;
757
758 es=ERR_get_state();
759
760 i=es->top;
761 if (i == 0)
762 i=ERR_NUM_ERRORS-1;
763
764 es->err_data[i]=data;
765 es->err_data_flags[es->top]=flags;
766 }
767
4565c3e3 768void ERR_add_error_data(int num, ...)
b1c4fe36 769 {
4565c3e3 770 va_list args;
58964a49
RE
771 int i,n,s;
772 char *str,*p,*a;
773
774 s=64;
26a3a48d 775 str=OPENSSL_malloc(s+1);
58964a49
RE
776 if (str == NULL) return;
777 str[0]='\0';
778
4565c3e3 779 va_start(args, num);
58964a49
RE
780 n=0;
781 for (i=0; i<num; i++)
782 {
4565c3e3 783 a=va_arg(args, char*);
dfeab068
RE
784 /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
785 if (a != NULL)
58964a49 786 {
dfeab068
RE
787 n+=strlen(a);
788 if (n > s)
58964a49 789 {
dfeab068 790 s=n+20;
26a3a48d 791 p=OPENSSL_realloc(str,s+1);
dfeab068
RE
792 if (p == NULL)
793 {
26a3a48d 794 OPENSSL_free(str);
dfeab068
RE
795 return;
796 }
797 else
798 str=p;
58964a49 799 }
dfeab068 800 strcat(str,a);
58964a49 801 }
58964a49
RE
802 }
803 ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
804
4565c3e3 805 va_end(args);
58964a49
RE
806 }
807