]> git.saurik.com Git - apple/security.git/blob - libsecurity_apple_csp/open_ssl/err/err.c
Security-55471.tar.gz
[apple/security.git] / libsecurity_apple_csp / open_ssl / err / err.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /* crypto/err/err.c */
20 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
21 * All rights reserved.
22 *
23 * This package is an SSL implementation written
24 * by Eric Young (eay@cryptsoft.com).
25 * The implementation was written so as to conform with Netscapes SSL.
26 *
27 * This library is free for commercial and non-commercial use as long as
28 * the following conditions are aheared to. The following conditions
29 * apply to all code found in this distribution, be it the RC4, RSA,
30 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
31 * included with this distribution is covered by the same copyright terms
32 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
33 *
34 * Copyright remains Eric Young's, and as such any Copyright notices in
35 * the code are not to be removed.
36 * If this package is used in a product, Eric Young should be given attribution
37 * as the author of the parts of the library used.
38 * This can be in the form of a textual message at program startup or
39 * in documentation (online or textual) provided with the package.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * "This product includes cryptographic software written by
52 * Eric Young (eay@cryptsoft.com)"
53 * The word 'cryptographic' can be left out if the rouines from the library
54 * being used are not cryptographic related :-).
55 * 4. If you include any Windows specific code (or a derivative thereof) from
56 * the apps directory (application code) you must include an acknowledgement:
57 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
58 *
59 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 *
71 * The licence and distribution terms for any publically available version or
72 * derivative of this code cannot be changed. i.e. this code cannot simply be
73 * copied and put under another distribution licence
74 * [including the GNU Public Licence.]
75 */
76 /* ====================================================================
77 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
78 *
79 * Redistribution and use in source and binary forms, with or without
80 * modification, are permitted provided that the following conditions
81 * are met:
82 *
83 * 1. Redistributions of source code must retain the above copyright
84 * notice, this list of conditions and the following disclaimer.
85 *
86 * 2. Redistributions in binary form must reproduce the above copyright
87 * notice, this list of conditions and the following disclaimer in
88 * the documentation and/or other materials provided with the
89 * distribution.
90 *
91 * 3. All advertising materials mentioning features or use of this
92 * software must display the following acknowledgment:
93 * "This product includes software developed by the OpenSSL Project
94 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
95 *
96 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
97 * endorse or promote products derived from this software without
98 * prior written permission. For written permission, please contact
99 * openssl-core@openssl.org.
100 *
101 * 5. Products derived from this software may not be called "OpenSSL"
102 * nor may "OpenSSL" appear in their names without prior written
103 * permission of the OpenSSL Project.
104 *
105 * 6. Redistributions of any form whatsoever must retain the following
106 * acknowledgment:
107 * "This product includes software developed by the OpenSSL Project
108 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
109 *
110 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
111 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
112 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
113 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
114 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
115 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
116 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
117 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
118 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
119 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
120 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
121 * OF THE POSSIBILITY OF SUCH DAMAGE.
122 * ====================================================================
123 *
124 * This product includes cryptographic software written by Eric Young
125 * (eay@cryptsoft.com). This product includes software written by Tim
126 * Hudson (tjh@cryptsoft.com).
127 *
128 */
129
130 #include <stdio.h>
131 #include <stdarg.h>
132 #include <string.h>
133 #include <openssl/opensslconf.h>
134 #include <openssl/lhash.h>
135 #include <openssl/crypto.h>
136 #include "cryptlib.h"
137 #include <openssl/buffer.h>
138 #include <openssl/err.h>
139 #include <openssl/crypto.h>
140
141
142 static LHASH *error_hash=NULL;
143 static LHASH *thread_hash=NULL;
144
145 static unsigned long err_hash(ERR_STRING_DATA *a);
146 static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b);
147 static unsigned long pid_hash(ERR_STATE *pid);
148 static int pid_cmp(ERR_STATE *a,ERR_STATE *pid);
149 static unsigned long get_error_values(int inc,const char **file,int *line,
150 const char **data,int *flags);
151 static void ERR_STATE_free(ERR_STATE *s);
152 #ifndef NO_ERR
153 static ERR_STRING_DATA ERR_str_libraries[]=
154 {
155 {ERR_PACK(ERR_LIB_NONE,0,0) ,"unknown library"},
156 {ERR_PACK(ERR_LIB_SYS,0,0) ,"system library"},
157 {ERR_PACK(ERR_LIB_BN,0,0) ,"bignum routines"},
158 {ERR_PACK(ERR_LIB_RSA,0,0) ,"rsa routines"},
159 {ERR_PACK(ERR_LIB_DH,0,0) ,"Diffie-Hellman routines"},
160 {ERR_PACK(ERR_LIB_EVP,0,0) ,"digital envelope routines"},
161 {ERR_PACK(ERR_LIB_BUF,0,0) ,"memory buffer routines"},
162 {ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"},
163 {ERR_PACK(ERR_LIB_OBJ,0,0) ,"object identifier routines"},
164 {ERR_PACK(ERR_LIB_PEM,0,0) ,"PEM routines"},
165 {ERR_PACK(ERR_LIB_ASN1,0,0) ,"asn1 encoding routines"},
166 {ERR_PACK(ERR_LIB_X509,0,0) ,"x509 certificate routines"},
167 {ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"},
168 {ERR_PACK(ERR_LIB_METH,0,0) ,"X509 lookup 'method' routines"},
169 {ERR_PACK(ERR_LIB_SSL,0,0) ,"SSL routines"},
170 {ERR_PACK(ERR_LIB_RSAREF,0,0) ,"RSAref routines"},
171 {ERR_PACK(ERR_LIB_PROXY,0,0) ,"Proxy routines"},
172 {ERR_PACK(ERR_LIB_BIO,0,0) ,"BIO routines"},
173 {ERR_PACK(ERR_LIB_PKCS7,0,0) ,"PKCS7 routines"},
174 {ERR_PACK(ERR_LIB_X509V3,0,0) ,"X509 V3 routines"},
175 {ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"},
176 {ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"},
177 {0,NULL},
178 };
179
180 static ERR_STRING_DATA ERR_str_functs[]=
181 {
182 {ERR_PACK(0,SYS_F_FOPEN,0), "fopen"},
183 {ERR_PACK(0,SYS_F_CONNECT,0), "connect"},
184 {ERR_PACK(0,SYS_F_GETSERVBYNAME,0), "getservbyname"},
185 {ERR_PACK(0,SYS_F_SOCKET,0), "socket"},
186 {ERR_PACK(0,SYS_F_IOCTLSOCKET,0), "ioctlsocket"},
187 {ERR_PACK(0,SYS_F_BIND,0), "bind"},
188 {ERR_PACK(0,SYS_F_LISTEN,0), "listen"},
189 {ERR_PACK(0,SYS_F_ACCEPT,0), "accept"},
190 #ifdef WINDOWS
191 {ERR_PACK(0,SYS_F_WSASTARTUP,0), "WSAstartup"},
192 #endif
193 {ERR_PACK(0,SYS_F_OPENDIR,0), "opendir"},
194 {0,NULL},
195 };
196
197 static ERR_STRING_DATA ERR_str_reasons[]=
198 {
199 {ERR_R_FATAL ,"fatal"},
200 {ERR_R_SYS_LIB ,"system lib"},
201 {ERR_R_BN_LIB ,"BN lib"},
202 {ERR_R_RSA_LIB ,"RSA lib"},
203 {ERR_R_DH_LIB ,"DH lib"},
204 {ERR_R_EVP_LIB ,"EVP lib"},
205 {ERR_R_BUF_LIB ,"BUF lib"},
206 {ERR_R_BIO_LIB ,"BIO lib"},
207 {ERR_R_OBJ_LIB ,"OBJ lib"},
208 {ERR_R_PEM_LIB ,"PEM lib"},
209 {ERR_R_X509_LIB ,"X509 lib"},
210 {ERR_R_METH_LIB ,"METH lib"},
211 {ERR_R_ASN1_LIB ,"ASN1 lib"},
212 {ERR_R_CONF_LIB ,"CONF lib"},
213 {ERR_R_SSL_LIB ,"SSL lib"},
214 {ERR_R_PROXY_LIB ,"PROXY lib"},
215 {ERR_R_BIO_LIB ,"BIO lib"},
216 {ERR_R_PKCS7_LIB ,"PKCS7 lib"},
217 {ERR_R_PKCS12_LIB ,"PKCS12 lib"},
218 {ERR_R_MALLOC_FAILURE ,"Malloc failure"},
219 {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED ,"called a function you should not call"},
220 {ERR_R_PASSED_NULL_PARAMETER ,"passed a null parameter"},
221 {ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"},
222 {ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"},
223 {ERR_R_BAD_GET_ASN1_OBJECT_CALL ,"bad get asn1 object call"},
224 {ERR_R_EXPECTING_AN_ASN1_SEQUENCE ,"expecting an asn1 sequence"},
225 {ERR_R_ASN1_LENGTH_MISMATCH ,"asn1 length mismatch"},
226 {ERR_R_MISSING_ASN1_EOS ,"missing asn1 eos"},
227
228 {0,NULL},
229 };
230
231
232 #define NUM_SYS_STR_REASONS 127
233 #define LEN_SYS_STR_REASON 32
234
235 static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
236 /* SYS_str_reasons is filled with copies of strerror() results at
237 * initialization.
238 * 'errno' values up to 127 should cover all usual errors,
239 * others will be displayed numerically by ERR_error_string.
240 * It is crucial that we have something for each reason code
241 * that occurs in ERR_str_reasons, or bogus reason strings
242 * will be returned for SYSerr(), which always gets an errno
243 * value and never one of those 'standard' reason codes. */
244
245 static void build_SYS_str_reasons()
246 {
247 /* Malloc cannot be used here, use static storage instead */
248 static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
249 int i;
250
251 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
252
253 for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
254 {
255 ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
256
257 str->error = (unsigned long)i;
258 if (str->string == NULL)
259 {
260 char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
261 char *src = strerror(i);
262 if (src != NULL)
263 {
264 strncpy(*dest, src, sizeof *dest);
265 (*dest)[sizeof *dest - 1] = '\0';
266 str->string = *dest;
267 }
268 }
269 if (str->string == NULL)
270 str->string = "unknown";
271 }
272
273 /* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
274 * as required by ERR_load_strings. */
275
276 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
277 }
278 #endif
279
280 #define err_clear_data(p,i) \
281 if (((p)->err_data[i] != NULL) && \
282 (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
283 { \
284 Free((p)->err_data[i]); \
285 (p)->err_data[i]=NULL; \
286 } \
287 (p)->err_data_flags[i]=0;
288
289 static void ERR_STATE_free(ERR_STATE *s)
290 {
291 int i;
292
293 if(s == NULL)
294 return;
295
296 for (i=0; i<ERR_NUM_ERRORS; i++)
297 {
298 err_clear_data(s,i);
299 }
300 Free(s);
301 }
302
303 void ERR_load_ERR_strings(void)
304 {
305 static int init=1;
306
307 if (init)
308 {
309 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
310 if (init == 0)
311 {
312 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
313 return;
314 }
315 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
316
317 #ifndef NO_ERR
318 ERR_load_strings(0,ERR_str_libraries);
319 ERR_load_strings(0,ERR_str_reasons);
320 ERR_load_strings(ERR_LIB_SYS,ERR_str_functs);
321 build_SYS_str_reasons();
322 ERR_load_strings(ERR_LIB_SYS,SYS_str_reasons);
323 #endif
324 init=0;
325 }
326 }
327
328 void ERR_load_strings(int lib, ERR_STRING_DATA *str)
329 {
330 if (error_hash == NULL)
331 {
332 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
333 error_hash=lh_new(err_hash,err_cmp);
334 if (error_hash == NULL)
335 {
336 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
337 return;
338 }
339 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
340
341 ERR_load_ERR_strings();
342 }
343
344 CRYPTO_w_lock(CRYPTO_LOCK_ERR_HASH);
345 while (str->error)
346 {
347 str->error|=ERR_PACK(lib,0,0);
348 lh_insert(error_hash,str);
349 str++;
350 }
351 CRYPTO_w_unlock(CRYPTO_LOCK_ERR_HASH);
352 }
353
354 void ERR_free_strings(void)
355 {
356 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
357
358 if (error_hash != NULL)
359 {
360 lh_free(error_hash);
361 error_hash=NULL;
362 }
363
364 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
365 }
366
367 /********************************************************/
368
369 void ERR_put_error(int lib, int func, int reason, const char *file,
370 int line)
371 {
372 ERR_STATE *es;
373
374 #ifdef _OSD_POSIX
375 /* In the BS2000-OSD POSIX subsystem, the compiler generates
376 * path names in the form "*POSIX(/etc/passwd)".
377 * This dirty hack strips them to something sensible.
378 * @@@ We shouldn't modify a const string, though.
379 */
380 if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
381 char *end;
382
383 /* Skip the "*POSIX(" prefix */
384 file += sizeof("*POSIX(")-1;
385 end = &file[strlen(file)-1];
386 if (*end == ')')
387 *end = '\0';
388 /* Optional: use the basename of the path only. */
389 if ((end = strrchr(file, '/')) != NULL)
390 file = &end[1];
391 }
392 #endif
393 es=ERR_get_state();
394
395 es->top=(es->top+1)%ERR_NUM_ERRORS;
396 if (es->top == es->bottom)
397 es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
398 es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
399 es->err_file[es->top]=file;
400 es->err_line[es->top]=line;
401 err_clear_data(es,es->top);
402 }
403
404 void ERR_clear_error(void)
405 {
406 ERR_STATE *es;
407
408 es=ERR_get_state();
409
410 #if 0
411 /* hmm... is this needed */
412 for (i=0; i<ERR_NUM_ERRORS; i++)
413 {
414 es->err_buffer[i]=0;
415 es->err_file[i]=NULL;
416 es->err_line[i]= -1;
417 err_clear_data(es,i);
418 }
419 #endif
420 es->top=es->bottom=0;
421 }
422
423
424 unsigned long ERR_get_error(void)
425 { return(get_error_values(1,NULL,NULL,NULL,NULL)); }
426
427 unsigned long ERR_get_error_line(const char **file,
428 int *line)
429 { return(get_error_values(1,file,line,NULL,NULL)); }
430
431 unsigned long ERR_get_error_line_data(const char **file, int *line,
432 const char **data, int *flags)
433 { return(get_error_values(1,file,line,
434 data,flags)); }
435
436 unsigned long ERR_peek_error(void)
437 { return(get_error_values(0,NULL,NULL,NULL,NULL)); }
438
439 unsigned long ERR_peek_error_line(const char **file,
440 int *line)
441 { return(get_error_values(0,file,line,NULL,NULL)); }
442
443 unsigned long ERR_peek_error_line_data(const char **file, int *line,
444 const char **data, int *flags)
445 { return(get_error_values(0,file,line,
446 data,flags)); }
447
448 static unsigned long get_error_values(int inc, const char **file, int *line,
449 const char **data, int *flags)
450 {
451 int i=0;
452 ERR_STATE *es;
453 unsigned long ret;
454
455 es=ERR_get_state();
456
457 if (es->bottom == es->top) return(0);
458 i=(es->bottom+1)%ERR_NUM_ERRORS;
459
460 ret=es->err_buffer[i];
461 if (inc)
462 {
463 es->bottom=i;
464 es->err_buffer[i]=0;
465 }
466
467 if ((file != NULL) && (line != NULL))
468 {
469 if (es->err_file[i] == NULL)
470 {
471 *file="NA";
472 if (line != NULL) *line=0;
473 }
474 else
475 {
476 *file=es->err_file[i];
477 if (line != NULL) *line=es->err_line[i];
478 }
479 }
480
481 if (data != NULL)
482 {
483 if (es->err_data[i] == NULL)
484 {
485 *data="";
486 if (flags != NULL) *flags=0;
487 }
488 else
489 {
490 *data=es->err_data[i];
491 if (flags != NULL) *flags=es->err_data_flags[i];
492 }
493 }
494 return(ret);
495 }
496
497 /* BAD for multi-threaded, uses a local buffer if ret == NULL */
498 char *ERR_error_string(unsigned long e, char *ret)
499 {
500 #ifdef NO_ERR
501 if(ret != NULL) {
502 strcpy(ret, "No Error String Info.");
503 }
504 return "No Error String info.";
505 #else
506 static char buf[256];
507 const char *ls,*fs,*rs;
508 unsigned long l,f,r;
509 size_t i;
510
511 l=ERR_GET_LIB(e);
512 f=ERR_GET_FUNC(e);
513 r=ERR_GET_REASON(e);
514
515 ls=ERR_lib_error_string(e);
516 fs=ERR_func_error_string(e);
517 rs=ERR_reason_error_string(e);
518
519 if (ret == NULL) ret=buf;
520
521 sprintf(&(ret[0]),"error:%08lX:",e);
522 i=strlen(ret);
523 if (ls == NULL)
524 sprintf(&(ret[i]),":lib(%lu) ",l);
525 else sprintf(&(ret[i]),"%s",ls);
526 i=strlen(ret);
527 if (fs == NULL)
528 sprintf(&(ret[i]),":func(%lu) ",f);
529 else sprintf(&(ret[i]),":%s",fs);
530 i=strlen(ret);
531 if (rs == NULL)
532 sprintf(&(ret[i]),":reason(%lu)",r);
533 else sprintf(&(ret[i]),":%s",rs);
534
535 return(ret);
536 #endif
537 }
538
539 LHASH *ERR_get_string_table(void)
540 {
541 return(error_hash);
542 }
543
544 LHASH *ERR_get_err_state_table(void)
545 {
546 return(thread_hash);
547 }
548
549 const char *ERR_lib_error_string(unsigned long e)
550 {
551 ERR_STRING_DATA d,*p=NULL;
552 unsigned long l;
553
554 l=ERR_GET_LIB(e);
555
556 CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH);
557
558 if (error_hash != NULL)
559 {
560 d.error=ERR_PACK(l,0,0);
561 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
562 }
563
564 CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH);
565
566 return((p == NULL)?NULL:p->string);
567 }
568
569 const char *ERR_func_error_string(unsigned long e)
570 {
571 ERR_STRING_DATA d,*p=NULL;
572 unsigned long l,f;
573
574 l=ERR_GET_LIB(e);
575 f=ERR_GET_FUNC(e);
576
577 CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH);
578
579 if (error_hash != NULL)
580 {
581 d.error=ERR_PACK(l,f,0);
582 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
583 }
584
585 CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH);
586
587 return((p == NULL)?NULL:p->string);
588 }
589
590 const char *ERR_reason_error_string(unsigned long e)
591 {
592 ERR_STRING_DATA d,*p=NULL;
593 unsigned long l,r;
594
595 l=ERR_GET_LIB(e);
596 r=ERR_GET_REASON(e);
597
598 CRYPTO_r_lock(CRYPTO_LOCK_ERR_HASH);
599
600 if (error_hash != NULL)
601 {
602 d.error=ERR_PACK(l,0,r);
603 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
604 if (p == NULL)
605 {
606 d.error=ERR_PACK(0,0,r);
607 p=(ERR_STRING_DATA *)lh_retrieve(error_hash,&d);
608 }
609 }
610
611 CRYPTO_r_unlock(CRYPTO_LOCK_ERR_HASH);
612
613 return((p == NULL)?NULL:p->string);
614 }
615
616 static unsigned long err_hash(ERR_STRING_DATA *a)
617 {
618 unsigned long ret,l;
619
620 l=a->error;
621 ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
622 return(ret^ret%19*13);
623 }
624
625 static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b)
626 {
627 return((int)(a->error-b->error));
628 }
629
630 static unsigned long pid_hash(ERR_STATE *a)
631 {
632 return(a->pid*13);
633 }
634
635 static int pid_cmp(ERR_STATE *a, ERR_STATE *b)
636 {
637 return((int)((long)a->pid - (long)b->pid));
638 }
639
640 void ERR_remove_state(unsigned long pid)
641 {
642 ERR_STATE *p,tmp;
643
644 if (thread_hash == NULL)
645 return;
646 if (pid == 0)
647 pid=(unsigned long)CRYPTO_thread_id();
648 tmp.pid=pid;
649 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
650 p=(ERR_STATE *)lh_delete(thread_hash,&tmp);
651 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
652
653 if (p != NULL) ERR_STATE_free(p);
654 }
655
656 static ERR_STATE *fallback = NULL;
657 static ERR_STATE *getFallback()
658 {
659 if(fallback == NULL) {
660 fallback = (ERR_STATE *)Malloc(sizeof(ERR_STATE));
661 }
662 return fallback;
663 }
664
665 ERR_STATE *ERR_get_state(void)
666 {
667 ERR_STATE *ret=NULL,tmp,*tmpp;
668 int i;
669 unsigned long pid;
670
671 pid=(unsigned long)CRYPTO_thread_id();
672
673 CRYPTO_r_lock(CRYPTO_LOCK_ERR);
674 if (thread_hash == NULL)
675 {
676 CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
677 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
678 if (thread_hash == NULL)
679 {
680 MemCheck_off();
681 thread_hash=lh_new(pid_hash,pid_cmp);
682 MemCheck_on();
683 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
684 if (thread_hash == NULL) return(getFallback());
685 }
686 else
687 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
688 }
689 else
690 {
691 tmp.pid=pid;
692 ret=(ERR_STATE *)lh_retrieve(thread_hash,&tmp);
693 CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
694 }
695
696 /* ret == the error state, if NULL, make a new one */
697 if (ret == NULL)
698 {
699 ret=(ERR_STATE *)Malloc(sizeof(ERR_STATE));
700 if (ret == NULL) return(getFallback());
701 ret->pid=pid;
702 ret->top=0;
703 ret->bottom=0;
704 for (i=0; i<ERR_NUM_ERRORS; i++)
705 {
706 ret->err_data[i]=NULL;
707 ret->err_data_flags[i]=0;
708 }
709 CRYPTO_w_lock(CRYPTO_LOCK_ERR);
710 tmpp=(ERR_STATE *)lh_insert(thread_hash,ret);
711 CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
712 if (tmpp != NULL) /* old entry - should not happen */
713 {
714 ERR_STATE_free(tmpp);
715 }
716 }
717 return(ret);
718 }
719
720 int ERR_get_next_error_library(void)
721 {
722 static int value=ERR_LIB_USER;
723
724 return(value++);
725 }
726
727 void ERR_set_error_data(char *data, int flags)
728 {
729 ERR_STATE *es;
730 int i;
731
732 es=ERR_get_state();
733
734 i=es->top;
735 if (i == 0)
736 i=ERR_NUM_ERRORS-1;
737
738 es->err_data[i]=data;
739 es->err_data_flags[es->top]=flags;
740 }
741
742 void ERR_add_error_data(int num, ...)
743 {
744 va_list args;
745 int i,n,s;
746 char *str,*p,*a;
747
748 s=64;
749 str=Malloc(s+1);
750 if (str == NULL) return;
751 str[0]='\0';
752
753 va_start(args, num);
754 n=0;
755 for (i=0; i<num; i++)
756 {
757 a=va_arg(args, char*);
758 /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
759 if (a != NULL)
760 {
761 n+=strlen(a);
762 if (n > s)
763 {
764 s=n+20;
765 p=Realloc(str,s+1);
766 if (p == NULL)
767 {
768 Free(str);
769 return;
770 }
771 else
772 str=p;
773 }
774 strcat(str,a);
775 }
776 }
777 ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);
778
779 va_end(args);
780 }
781