err.c 29.5 KB
Newer Older
1
/* crypto/err/err.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */
58
/* ====================================================================
59
 * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
111 112

#include <stdio.h>
U
Ulf Möller 已提交
113
#include <stdarg.h>
114
#include <string.h>
115
#include "cryptlib.h"
116 117 118
#include <openssl/lhash.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
B
Bodo Möller 已提交
119
#include <openssl/bio.h>
120
#include <openssl/err.h>
121

122 123
static void err_load_strings(int lib, ERR_STRING_DATA *str);

124
static void ERR_STATE_free(ERR_STATE *s);
125
#ifndef OPENSSL_NO_ERR
126 127 128 129 130 131 132 133 134 135 136
static ERR_STRING_DATA ERR_str_libraries[]=
	{
{ERR_PACK(ERR_LIB_NONE,0,0)		,"unknown library"},
{ERR_PACK(ERR_LIB_SYS,0,0)		,"system library"},
{ERR_PACK(ERR_LIB_BN,0,0)		,"bignum routines"},
{ERR_PACK(ERR_LIB_RSA,0,0)		,"rsa routines"},
{ERR_PACK(ERR_LIB_DH,0,0)		,"Diffie-Hellman routines"},
{ERR_PACK(ERR_LIB_EVP,0,0)		,"digital envelope routines"},
{ERR_PACK(ERR_LIB_BUF,0,0)		,"memory buffer routines"},
{ERR_PACK(ERR_LIB_OBJ,0,0)		,"object identifier routines"},
{ERR_PACK(ERR_LIB_PEM,0,0)		,"PEM routines"},
B
Bodo Möller 已提交
137
{ERR_PACK(ERR_LIB_DSA,0,0)		,"dsa routines"},
138
{ERR_PACK(ERR_LIB_X509,0,0)		,"x509 certificate routines"},
B
Bodo Möller 已提交
139
{ERR_PACK(ERR_LIB_ASN1,0,0)		,"asn1 encoding routines"},
U
Ulf Möller 已提交
140
{ERR_PACK(ERR_LIB_CONF,0,0)		,"configuration file routines"},
B
Bodo Möller 已提交
141 142
{ERR_PACK(ERR_LIB_CRYPTO,0,0)		,"common libcrypto routines"},
{ERR_PACK(ERR_LIB_EC,0,0)		,"elliptic curve routines"},
143 144 145
{ERR_PACK(ERR_LIB_SSL,0,0)		,"SSL routines"},
{ERR_PACK(ERR_LIB_BIO,0,0)		,"BIO routines"},
{ERR_PACK(ERR_LIB_PKCS7,0,0)		,"PKCS7 routines"},
146
{ERR_PACK(ERR_LIB_X509V3,0,0)		,"X509 V3 routines"},
147
{ERR_PACK(ERR_LIB_PKCS12,0,0)		,"PKCS12 routines"},
148
{ERR_PACK(ERR_LIB_RAND,0,0)		,"random number generator"},
149
{ERR_PACK(ERR_LIB_DSO,0,0)		,"DSO support routines"},
150
{ERR_PACK(ERR_LIB_TS,0,0)		,"time stamp routines"},
151
{ERR_PACK(ERR_LIB_ENGINE,0,0)		,"engine routines"},
152
{ERR_PACK(ERR_LIB_OCSP,0,0)		,"OCSP routines"},
153
{ERR_PACK(ERR_LIB_HMAC,0,0)		,"HMAC routines"},
D
Dr. Stephen Henson 已提交
154
{ERR_PACK(ERR_LIB_CMS,0,0)		,"CMS routines"},
155 156 157 158 159 160 161 162 163 164 165 166 167
{0,NULL},
	};

static ERR_STRING_DATA ERR_str_functs[]=
	{
	{ERR_PACK(0,SYS_F_FOPEN,0),     	"fopen"},
	{ERR_PACK(0,SYS_F_CONNECT,0),		"connect"},
	{ERR_PACK(0,SYS_F_GETSERVBYNAME,0),	"getservbyname"},
	{ERR_PACK(0,SYS_F_SOCKET,0),		"socket"}, 
	{ERR_PACK(0,SYS_F_IOCTLSOCKET,0),	"ioctlsocket"},
	{ERR_PACK(0,SYS_F_BIND,0),		"bind"},
	{ERR_PACK(0,SYS_F_LISTEN,0),		"listen"},
	{ERR_PACK(0,SYS_F_ACCEPT,0),		"accept"},
168
#ifdef OPENSSL_SYS_WINDOWS
169 170
	{ERR_PACK(0,SYS_F_WSASTARTUP,0),	"WSAstartup"},
#endif
171
	{ERR_PACK(0,SYS_F_OPENDIR,0),		"opendir"},
B
Ben Laurie 已提交
172
	{ERR_PACK(0,SYS_F_FREAD,0),		"fread"},
173 174 175 176 177 178 179 180 181 182 183 184 185
	{0,NULL},
	};

static ERR_STRING_DATA ERR_str_reasons[]=
	{
{ERR_R_SYS_LIB				,"system lib"},
{ERR_R_BN_LIB				,"BN lib"},
{ERR_R_RSA_LIB				,"RSA lib"},
{ERR_R_DH_LIB				,"DH lib"},
{ERR_R_EVP_LIB				,"EVP lib"},
{ERR_R_BUF_LIB				,"BUF lib"},
{ERR_R_OBJ_LIB				,"OBJ lib"},
{ERR_R_PEM_LIB				,"PEM lib"},
B
Bodo Möller 已提交
186
{ERR_R_DSA_LIB				,"DSA lib"},
187 188 189
{ERR_R_X509_LIB				,"X509 lib"},
{ERR_R_ASN1_LIB				,"ASN1 lib"},
{ERR_R_CONF_LIB				,"CONF lib"},
B
Bodo Möller 已提交
190 191
{ERR_R_CRYPTO_LIB			,"CRYPTO lib"},
{ERR_R_EC_LIB				,"EC lib"},
192 193 194
{ERR_R_SSL_LIB				,"SSL lib"},
{ERR_R_BIO_LIB				,"BIO lib"},
{ERR_R_PKCS7_LIB			,"PKCS7 lib"},
B
Bodo Möller 已提交
195
{ERR_R_X509V3_LIB			,"X509V3 lib"},
196
{ERR_R_PKCS12_LIB			,"PKCS12 lib"},
B
Bodo Möller 已提交
197 198 199 200
{ERR_R_RAND_LIB				,"RAND lib"},
{ERR_R_DSO_LIB				,"DSO lib"},
{ERR_R_ENGINE_LIB			,"ENGINE lib"},
{ERR_R_OCSP_LIB				,"OCSP lib"},
201
{ERR_R_TS_LIB				,"TS lib"},
B
Bodo Möller 已提交
202

203 204 205 206 207 208
{ERR_R_NESTED_ASN1_ERROR		,"nested asn1 error"},
{ERR_R_BAD_ASN1_OBJECT_HEADER		,"bad asn1 object header"},
{ERR_R_BAD_GET_ASN1_OBJECT_CALL		,"bad get asn1 object call"},
{ERR_R_EXPECTING_AN_ASN1_SEQUENCE	,"expecting an asn1 sequence"},
{ERR_R_ASN1_LENGTH_MISMATCH		,"asn1 length mismatch"},
{ERR_R_MISSING_ASN1_EOS			,"missing asn1 eos"},
B
Bodo Möller 已提交
209 210 211 212 213 214

{ERR_R_FATAL                            ,"fatal"},
{ERR_R_MALLOC_FAILURE			,"malloc failure"},
{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED	,"called a function you should not call"},
{ERR_R_PASSED_NULL_PARAMETER		,"passed a null parameter"},
{ERR_R_INTERNAL_ERROR			,"internal error"},
B
Bodo Möller 已提交
215
{ERR_R_DISABLED				,"called a function that was disabled at compile-time"},
216

217 218
{0,NULL},
	};
219
#endif
220 221


222 223 224 225
/* Define the predeclared (but externally opaque) "ERR_FNS" type */
struct st_ERR_FNS
	{
	/* Works on the "error_hash" string table */
B
Bodo Möller 已提交
226
	LHASH *(*cb_err_get)(int create);
227 228 229
	void (*cb_err_del)(void);
	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
	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 */
B
Bodo Möller 已提交
232
	LHASH *(*cb_thread_get)(int create);
233
	void (*cb_thread_release)(LHASH **hash);
234 235 236 237 238 239 240 241
	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
	void (*cb_thread_del_item)(const ERR_STATE *);
	/* Returns the next available error "library" numbers */
	int (*cb_get_next_lib)(void);
	};

/* Predeclarations of the "err_defaults" functions */
B
Bodo Möller 已提交
242
static LHASH *int_err_get(int create);
243 244 245
static void int_err_del(void);
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
246
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
B
Bodo Möller 已提交
247
static LHASH *int_thread_get(int create);
248
static void int_thread_release(LHASH **hash);
249 250 251 252 253 254 255 256 257 258 259
static ERR_STATE *int_thread_get_item(const ERR_STATE *);
static ERR_STATE *int_thread_set_item(ERR_STATE *);
static void int_thread_del_item(const ERR_STATE *);
static int int_err_get_next_lib(void);
/* The static ERR_FNS table using these defaults functions */
static const ERR_FNS err_defaults =
	{
	int_err_get,
	int_err_del,
	int_err_get_item,
	int_err_set_item,
260
	int_err_del_item,
261
	int_thread_get,
262
	int_thread_release,
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
	int_thread_get_item,
	int_thread_set_item,
	int_thread_del_item,
	int_err_get_next_lib
	};

/* The replacable table of ERR_FNS functions we use at run-time */
static const ERR_FNS *err_fns = NULL;

/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */
#define ERRFN(a) err_fns->cb_##a

/* The internal state used by "err_defaults" - as such, the setting, reading,
 * creating, and deleting of this data should only be permitted via the
 * "err_defaults" functions. This way, a linked module can completely defer all
 * ERR state operation (together with requisite locking) to the implementations
 * and state in the loading application. */
280 281
static LHASH *int_error_hash = NULL;
static LHASH *int_thread_hash = NULL;
282
static int int_thread_hash_references = 0;
283
static int int_err_library_number= ERR_LIB_USER;
284 285 286 287 288

/* Internal function that checks whether "err_fns" is set and if not, sets it to
 * the defaults. */
static void err_fns_check(void)
	{
289 290
	if (err_fns) return;
	
291
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
292
	if (!err_fns)
293 294 295 296 297 298 299 300 301 302 303 304 305 306
		err_fns = &err_defaults;
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
	}

/* API functions to get or set the underlying ERR functions. */

const ERR_FNS *ERR_get_implementation(void)
	{
	err_fns_check();
	return err_fns;
	}

int ERR_set_implementation(const ERR_FNS *fns)
	{
307 308
	int ret = 0;

309 310 311
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
	/* It's too late if 'err_fns' is non-NULL. BTW: not much point setting
	 * an error is there?! */
312
	if (!err_fns)
313 314
		{
		err_fns = fns;
315
		ret = 1;
316 317
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
318
	return ret;
319 320 321 322 323 324 325 326 327 328 329 330 331
	}

/* These are the callbacks provided to "lh_new()" when creating the LHASH tables
 * internal to the "err_defaults" implementation. */

/* static unsigned long err_hash(ERR_STRING_DATA *a); */
static unsigned long err_hash(const void *a_void);
/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
static int err_cmp(const void *a_void, const void *b_void);
/* static unsigned long pid_hash(ERR_STATE *pid); */
static unsigned long pid_hash(const void *pid_void);
/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
static int pid_cmp(const void *a_void,const void *pid_void);
B
Bodo Möller 已提交
332
static unsigned long get_error_values(int inc,int top,const char **file,int *line,
333 334 335 336
				      const char **data,int *flags);

/* The internal functions used in the "err_defaults" implementation */

B
Bodo Möller 已提交
337
static LHASH *int_err_get(int create)
338
	{
339 340
	LHASH *ret = NULL;

341
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
342 343 344
	if (!int_error_hash && create)
		{
		CRYPTO_push_info("int_err_get (err.c)");
345
		int_error_hash = lh_new(err_hash, err_cmp);
B
Bodo Möller 已提交
346 347
		CRYPTO_pop_info();
		}
348 349
	if (int_error_hash)
		ret = int_error_hash;
350
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
351 352

	return ret;
353
	}
354

355 356 357
static void int_err_del(void)
	{
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
358
	if (int_error_hash)
359 360 361 362 363 364
		{
		lh_free(int_error_hash);
		int_error_hash = NULL;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
	}
365

366 367 368 369
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
	LHASH *hash;
370

371
	err_fns_check();
B
Bodo Möller 已提交
372
	hash = ERRFN(err_get)(0);
373
	if (!hash)
374
		return NULL;
375

376 377 378
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
379

380 381
	return p;
	}
382

383 384 385 386
static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
	LHASH *hash;
387

388
	err_fns_check();
B
Bodo Möller 已提交
389
	hash = ERRFN(err_get)(1);
390
	if (!hash)
391
		return NULL;
392

393
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
394
	p = (ERR_STRING_DATA *)lh_insert(hash, d);
395
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
396

397 398
	return p;
	}
399

400 401 402 403
static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
	{
	ERR_STRING_DATA *p;
	LHASH *hash;
404

405
	err_fns_check();
B
Bodo Möller 已提交
406
	hash = ERRFN(err_get)(0);
407
	if (!hash)
408
		return NULL;
409

410
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
411
	p = (ERR_STRING_DATA *)lh_delete(hash, d);
412
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
413

414 415
	return p;
	}
416

B
Bodo Möller 已提交
417
static LHASH *int_thread_get(int create)
418
	{
419 420
	LHASH *ret = NULL;

421
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
422 423 424
	if (!int_thread_hash && create)
		{
		CRYPTO_push_info("int_thread_get (err.c)");
425
		int_thread_hash = lh_new(pid_hash, pid_cmp);
B
Bodo Möller 已提交
426 427
		CRYPTO_pop_info();
		}
428
	if (int_thread_hash)
429 430
		{
		int_thread_hash_references++;
431
		ret = int_thread_hash;
432
		}
433
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
434
	return ret;
435
	}
436

437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
static void int_thread_release(LHASH **hash)
	{
	int i;

	if (hash == NULL || *hash == NULL)
		return;

	i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR);

#ifdef REF_PRINT
	fprintf(stderr,"%4d:%s\n",int_thread_hash_references,"ERR");
#endif
	if (i > 0) return;
#ifdef REF_CHECK
	if (i < 0)
		{
		fprintf(stderr,"int_thread_release, bad reference count\n");
		abort(); /* ok */
		}
#endif
	*hash = NULL;
	}

460 461 462 463
static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
	LHASH *hash;
464

465
	err_fns_check();
B
Bodo Möller 已提交
466
	hash = ERRFN(thread_get)(0);
467
	if (!hash)
468
		return NULL;
469

470 471 472
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
	p = (ERR_STATE *)lh_retrieve(hash, d);
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
473

474
	ERRFN(thread_release)(&hash);
475 476
	return p;
	}
477

478 479 480 481
static ERR_STATE *int_thread_set_item(ERR_STATE *d)
	{
	ERR_STATE *p;
	LHASH *hash;
482

483
	err_fns_check();
B
Bodo Möller 已提交
484
	hash = ERRFN(thread_get)(1);
485
	if (!hash)
486
		return NULL;
487

488
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
489
	p = (ERR_STATE *)lh_insert(hash, d);
490
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
491

492
	ERRFN(thread_release)(&hash);
493 494
	return p;
	}
495

496 497 498 499
static void int_thread_del_item(const ERR_STATE *d)
	{
	ERR_STATE *p;
	LHASH *hash;
500

501
	err_fns_check();
B
Bodo Möller 已提交
502
	hash = ERRFN(thread_get)(0);
503
	if (!hash)
504
		return;
505

506 507 508
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
	p = (ERR_STATE *)lh_delete(hash, d);
	/* make sure we don't leak memory */
509 510
	if (int_thread_hash_references == 1
		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
511 512 513 514 515
		{
		lh_free(int_thread_hash);
		int_thread_hash = NULL;
		}
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
516

517
	ERRFN(thread_release)(&hash);
518
	if (p)
519 520
		ERR_STATE_free(p);
	}
521

522 523
static int int_err_get_next_lib(void)
	{
524 525
	int ret;

526
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
527
	ret = int_err_library_number++;
528
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
529 530

	return ret;
531 532 533
	}


534
#ifndef OPENSSL_NO_ERR
535 536 537 538 539 540 541 542 543 544 545 546 547
#define NUM_SYS_STR_REASONS 127
#define LEN_SYS_STR_REASON 32

static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
/* SYS_str_reasons is filled with copies of strerror() results at
 * initialization.
 * 'errno' values up to 127 should cover all usual errors,
 * others will be displayed numerically by ERR_error_string.
 * It is crucial that we have something for each reason code
 * that occurs in ERR_str_reasons, or bogus reason strings
 * will be returned for SYSerr(), which always gets an errno
 * value and never one of those 'standard' reason codes. */

548
static void build_SYS_str_reasons(void)
549
	{
550
	/* OPENSSL_malloc cannot be used here, use static storage instead */
551 552
	static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
	int i;
553 554
	static int init = 1;

B
Bodo Möller 已提交
555 556 557 558 559 560 561 562
	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
	if (!init)
		{
		CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
		return;
		}
	
	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
563
	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
B
Bodo Möller 已提交
564 565 566 567 568
	if (!init)
		{
		CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
		return;
		}
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592

	for (i = 1; i <= NUM_SYS_STR_REASONS; i++)
		{
		ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];

		str->error = (unsigned long)i;
		if (str->string == NULL)
			{
			char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
			char *src = strerror(i);
			if (src != NULL)
				{
				strncpy(*dest, src, sizeof *dest);
				(*dest)[sizeof *dest - 1] = '\0';
				str->string = *dest;
				}
			}
		if (str->string == NULL)
			str->string = "unknown";
		}

	/* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL},
	 * as required by ERR_load_strings. */

593 594
	init = 0;
	
595
	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
596
	}
597 598
#endif

599
#define err_clear_data(p,i) \
600
	do { \
601 602 603
	if (((p)->err_data[i] != NULL) && \
		(p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
		{  \
604
		OPENSSL_free((p)->err_data[i]); \
605 606
		(p)->err_data[i]=NULL; \
		} \
607 608 609 610 611
	(p)->err_data_flags[i]=0; \
	} while(0)

#define err_clear(p,i) \
	do { \
612 613
	(p)->err_flags[i]=0; \
	(p)->err_buffer[i]=0; \
614
	err_clear_data(p,i); \
615 616
	(p)->err_file[i]=NULL; \
	(p)->err_line[i]= -1; \
617
	} while(0)
618

U
Ulf Möller 已提交
619
static void ERR_STATE_free(ERR_STATE *s)
620 621 622
	{
	int i;

623
	if (s == NULL)
B
Ben Laurie 已提交
624 625
	    return;

626 627 628 629
	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
		err_clear_data(s,i);
		}
630
	OPENSSL_free(s);
631 632
	}

U
Ulf Möller 已提交
633
void ERR_load_ERR_strings(void)
634
	{
635
	err_fns_check();
636
#ifndef OPENSSL_NO_ERR
637 638 639 640 641
	err_load_strings(0,ERR_str_libraries);
	err_load_strings(0,ERR_str_reasons);
	err_load_strings(ERR_LIB_SYS,ERR_str_functs);
	build_SYS_str_reasons();
	err_load_strings(ERR_LIB_SYS,SYS_str_reasons);
642 643 644
#endif
	}

645
static void err_load_strings(int lib, ERR_STRING_DATA *str)
646 647 648
	{
	while (str->error)
		{
649 650
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
651
		ERRFN(err_set_item)(str);
652 653 654 655
		str++;
		}
	}

656 657
void ERR_load_strings(int lib, ERR_STRING_DATA *str)
	{
B
typo  
Bodo Möller 已提交
658
	ERR_load_ERR_strings();
659 660 661
	err_load_strings(lib, str);
	}

662 663
void ERR_unload_strings(int lib, ERR_STRING_DATA *str)
	{
664
	while (str->error)
665
		{
666 667
		if (lib)
			str->error|=ERR_PACK(lib,0,0);
668 669 670 671 672
		ERRFN(err_del_item)(str);
		str++;
		}
	}

U
Ulf Möller 已提交
673
void ERR_free_strings(void)
674
	{
675 676
	err_fns_check();
	ERRFN(err_del)();
677 678
	}

679 680
/********************************************************/

U
Ulf Möller 已提交
681 682
void ERR_put_error(int lib, int func, int reason, const char *file,
	     int line)
683 684 685
	{
	ERR_STATE *es;

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
#ifdef _OSD_POSIX
	/* In the BS2000-OSD POSIX subsystem, the compiler generates
	 * path names in the form "*POSIX(/etc/passwd)".
	 * This dirty hack strips them to something sensible.
	 * @@@ We shouldn't modify a const string, though.
	 */
	if (strncmp(file,"*POSIX(", sizeof("*POSIX(")-1) == 0) {
		char *end;

		/* Skip the "*POSIX(" prefix */
		file += sizeof("*POSIX(")-1;
		end = &file[strlen(file)-1];
		if (*end == ')')
			*end = '\0';
		/* Optional: use the basename of the path only. */
		if ((end = strrchr(file, '/')) != NULL)
			file = &end[1];
	}
#endif
705 706 707 708 709
	es=ERR_get_state();

	es->top=(es->top+1)%ERR_NUM_ERRORS;
	if (es->top == es->bottom)
		es->bottom=(es->bottom+1)%ERR_NUM_ERRORS;
710
	es->err_flags[es->top]=0;
711 712 713
	es->err_buffer[es->top]=ERR_PACK(lib,func,reason);
	es->err_file[es->top]=file;
	es->err_line[es->top]=line;
714
	err_clear_data(es,es->top);
715 716
	}

U
Ulf Möller 已提交
717
void ERR_clear_error(void)
718
	{
B
Bodo Möller 已提交
719
	int i;
720 721 722 723 724 725
	ERR_STATE *es;

	es=ERR_get_state();

	for (i=0; i<ERR_NUM_ERRORS; i++)
		{
726
		err_clear(es,i);
727 728 729 730 731
		}
	es->top=es->bottom=0;
	}


U
Ulf Möller 已提交
732
unsigned long ERR_get_error(void)
B
Bodo Möller 已提交
733
	{ return(get_error_values(1,0,NULL,NULL,NULL,NULL)); }
734

U
Ulf Möller 已提交
735 736
unsigned long ERR_get_error_line(const char **file,
	     int *line)
B
Bodo Möller 已提交
737
	{ return(get_error_values(1,0,file,line,NULL,NULL)); }
738

U
Ulf Möller 已提交
739 740
unsigned long ERR_get_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
B
Bodo Möller 已提交
741
	{ return(get_error_values(1,0,file,line,data,flags)); }
742

B
Bodo Möller 已提交
743

U
Ulf Möller 已提交
744
unsigned long ERR_peek_error(void)
B
Bodo Möller 已提交
745
	{ return(get_error_values(0,0,NULL,NULL,NULL,NULL)); }
746

B
Bodo Möller 已提交
747 748
unsigned long ERR_peek_error_line(const char **file, int *line)
	{ return(get_error_values(0,0,file,line,NULL,NULL)); }
749

U
Ulf Möller 已提交
750 751
unsigned long ERR_peek_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
B
Bodo Möller 已提交
752 753
	{ return(get_error_values(0,0,file,line,data,flags)); }

B
Bodo Möller 已提交
754 755 756 757 758 759 760

unsigned long ERR_peek_last_error(void)
	{ return(get_error_values(0,1,NULL,NULL,NULL,NULL)); }

unsigned long ERR_peek_last_error_line(const char **file, int *line)
	{ return(get_error_values(0,1,file,line,NULL,NULL)); }

B
Bodo Möller 已提交
761 762 763
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
	     const char **data, int *flags)
	{ return(get_error_values(0,1,file,line,data,flags)); }
U
Ulf Möller 已提交
764

B
Bodo Möller 已提交
765

B
Bodo Möller 已提交
766
static unsigned long get_error_values(int inc, int top, const char **file, int *line,
U
Ulf Möller 已提交
767
	     const char **data, int *flags)
768 769
	{	
	int i=0;
770
	ERR_STATE *es;
771
	unsigned long ret;
772 773 774

	es=ERR_get_state();

B
Bodo Möller 已提交
775 776 777 778 779 780 781 782 783 784
	if (inc && top)
		{
		if (file) *file = "";
		if (line) *line = 0;
		if (data) *data = "";
		if (flags) *flags = 0;
			
		return ERR_R_INTERNAL_ERROR;
		}

785
	if (es->bottom == es->top) return 0;
B
Bodo Möller 已提交
786
	if (top)
787
		i=es->top;			 /* last error */
B
Bodo Möller 已提交
788 789
	else
		i=(es->bottom+1)%ERR_NUM_ERRORS; /* first error */
790 791 792

	ret=es->err_buffer[i];
	if (inc)
793
		{
794 795
		es->bottom=i;
		es->err_buffer[i]=0;
796
		}
797 798

	if ((file != NULL) && (line != NULL))
799
		{
800 801 802 803 804 805 806 807 808 809
		if (es->err_file[i] == NULL)
			{
			*file="NA";
			if (line != NULL) *line=0;
			}
		else
			{
			*file=es->err_file[i];
			if (line != NULL) *line=es->err_line[i];
			}
810 811
		}

B
Bodo Möller 已提交
812 813
	if (data == NULL)
		{
B
Bodo Möller 已提交
814
		if (inc)
B
Bodo Möller 已提交
815
			{
B
Bodo Möller 已提交
816
			err_clear_data(es, i);
B
Bodo Möller 已提交
817 818 819
			}
		}
	else
820 821 822 823 824 825 826 827 828 829 830 831
		{
		if (es->err_data[i] == NULL)
			{
			*data="";
			if (flags != NULL) *flags=0;
			}
		else
			{
			*data=es->err_data[i];
			if (flags != NULL) *flags=es->err_data_flags[i];
			}
		}
832
	return ret;
833 834
	}

B
Bodo Möller 已提交
835
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
836
	{
B
Bodo Möller 已提交
837
	char lsbuf[64], fsbuf[64], rsbuf[64];
B
Ben Laurie 已提交
838
	const char *ls,*fs,*rs;
839 840 841 842 843 844 845 846 847 848
	unsigned long l,f,r;

	l=ERR_GET_LIB(e);
	f=ERR_GET_FUNC(e);
	r=ERR_GET_REASON(e);

	ls=ERR_lib_error_string(e);
	fs=ERR_func_error_string(e);
	rs=ERR_reason_error_string(e);

B
Bodo Möller 已提交
849 850
	if (ls == NULL) 
		BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
851
	if (fs == NULL)
B
Bodo Möller 已提交
852
		BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
853
	if (rs == NULL)
B
Bodo Möller 已提交
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891
		BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);

	BIO_snprintf(buf, len,"error:%08lX:%s:%s:%s", e, ls?ls:lsbuf, 
		fs?fs:fsbuf, rs?rs:rsbuf);
	if (strlen(buf) == len-1)
		{
		/* output may be truncated; make sure we always have 5 
		 * colon-separated fields, i.e. 4 colons ... */
#define NUM_COLONS 4
		if (len > NUM_COLONS) /* ... if possible */
			{
			int i;
			char *s = buf;
			
			for (i = 0; i < NUM_COLONS; i++)
				{
				char *colon = strchr(s, ':');
				if (colon == NULL || colon > &buf[len-1] - NUM_COLONS + i)
					{
					/* set colon no. i at last possible position
					 * (buf[len-1] is the terminating 0)*/
					colon = &buf[len-1] - NUM_COLONS + i;
					*colon = ':';
					}
				s = colon + 1;
				}
			}
		}
	}

/* BAD for multi-threading: uses a local buffer if ret == NULL */
/* ERR_error_string_n should be used instead for ret != NULL
 * as ERR_error_string cannot know how large the buffer is */
char *ERR_error_string(unsigned long e, char *ret)
	{
	static char buf[256];

	if (ret == NULL) ret=buf;
892
	ERR_error_string_n(e, ret, 256);
893

894
	return ret;
895 896
	}

U
Ulf Möller 已提交
897
LHASH *ERR_get_string_table(void)
898
	{
899
	err_fns_check();
B
Bodo Möller 已提交
900
	return ERRFN(err_get)(0);
901 902
	}

U
Ulf Möller 已提交
903
LHASH *ERR_get_err_state_table(void)
904
	{
905
	err_fns_check();
B
Bodo Möller 已提交
906
	return ERRFN(thread_get)(0);
907 908
	}

909 910 911 912 913 914
void ERR_release_err_state_table(LHASH **hash)
	{
	err_fns_check();
	ERRFN(thread_release)(hash);
	}

U
Ulf Möller 已提交
915
const char *ERR_lib_error_string(unsigned long e)
916
	{
917
	ERR_STRING_DATA d,*p;
918 919
	unsigned long l;

920
	err_fns_check();
921
	l=ERR_GET_LIB(e);
922 923
	d.error=ERR_PACK(l,0,0);
	p=ERRFN(err_get_item)(&d);
924 925 926
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
927
const char *ERR_func_error_string(unsigned long e)
928
	{
929
	ERR_STRING_DATA d,*p;
930 931
	unsigned long l,f;

932
	err_fns_check();
933 934
	l=ERR_GET_LIB(e);
	f=ERR_GET_FUNC(e);
935 936
	d.error=ERR_PACK(l,f,0);
	p=ERRFN(err_get_item)(&d);
937 938 939
	return((p == NULL)?NULL:p->string);
	}

U
Ulf Möller 已提交
940
const char *ERR_reason_error_string(unsigned long e)
941 942 943 944
	{
	ERR_STRING_DATA d,*p=NULL;
	unsigned long l,r;

945
	err_fns_check();
946 947
	l=ERR_GET_LIB(e);
	r=ERR_GET_REASON(e);
948 949
	d.error=ERR_PACK(l,0,r);
	p=ERRFN(err_get_item)(&d);
950
	if (!p)
951
		{
952 953
		d.error=ERR_PACK(0,0,r);
		p=ERRFN(err_get_item)(&d);
954 955 956 957
		}
	return((p == NULL)?NULL:p->string);
	}

958
/* static unsigned long err_hash(ERR_STRING_DATA *a) */
959
static unsigned long err_hash(const void *a_void)
960 961 962
	{
	unsigned long ret,l;

N
Nils Larsch 已提交
963
	l=((const ERR_STRING_DATA *)a_void)->error;
964 965 966 967
	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
	return(ret^ret%19*13);
	}

968
/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
969
static int err_cmp(const void *a_void, const void *b_void)
970
	{
N
Nils Larsch 已提交
971 972
	return((int)(((const ERR_STRING_DATA *)a_void)->error -
			((const ERR_STRING_DATA *)b_void)->error));
973 974
	}

975
/* static unsigned long pid_hash(ERR_STATE *a) */
976
static unsigned long pid_hash(const void *a_void)
977
	{
978
	return((((const ERR_STATE *)a_void)->pid + (unsigned long)((const ERR_STATE *)a_void)->pidptr)*13);
979 980
	}

981
/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
982
static int pid_cmp(const void *a_void, const void *b_void)
983
	{
984 985
	return (((const ERR_STATE *)a_void)->pid != ((const ERR_STATE *)b_void)->pid)
	       || (((const ERR_STATE *)a_void)->pidptr != ((const ERR_STATE *)b_void)->pidptr);
986 987
	}

U
Ulf Möller 已提交
988
void ERR_remove_state(unsigned long pid)
989
	{
990
	ERR_STATE tmp;
991
	void *pidptr;
992

993
	err_fns_check();
994 995 996 997 998 999 1000 1001
	if (pid != 0)
		pidptr = &errno;
	else
		{
		pid = CRYPTO_thread_id();
		pidptr = CRYPTO_thread_idptr();
		}
	
1002
	tmp.pid=pid;
1003
	tmp.pidptr=pidptr;
1004 1005 1006
	/* thread_del_item automatically destroys the LHASH if the number of
	 * items reaches zero. */
	ERRFN(thread_del_item)(&tmp);
1007 1008
	}

U
Ulf Möller 已提交
1009
ERR_STATE *ERR_get_state(void)
1010 1011
	{
	static ERR_STATE fallback;
1012
	ERR_STATE *ret,tmp,*tmpp=NULL;
1013
	int i;
1014
	unsigned long pid;
1015
	void *pidptr;
1016

1017
	err_fns_check();
1018 1019 1020 1021
	pid = CRYPTO_thread_id();
	pidptr = CRYPTO_thread_idptr();
	tmp.pid = pid;
	tmp.pidptr = pidptr;
1022
	ret=ERRFN(thread_get_item)(&tmp);
1023 1024 1025 1026

	/* ret == the error state, if NULL, make a new one */
	if (ret == NULL)
		{
1027
		ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE));
1028 1029
		if (ret == NULL) return(&fallback);
		ret->pid=pid;
1030
		ret->pidptr=pidptr;
1031 1032
		ret->top=0;
		ret->bottom=0;
1033 1034 1035 1036 1037
		for (i=0; i<ERR_NUM_ERRORS; i++)
			{
			ret->err_data[i]=NULL;
			ret->err_data_flags[i]=0;
			}
1038 1039
		tmpp = ERRFN(thread_set_item)(ret);
		/* To check if insertion failed, do a get. */
1040
		if (ERRFN(thread_get_item)(ret) != ret)
1041 1042 1043 1044
			{
			ERR_STATE_free(ret); /* could not insert it */
			return(&fallback);
			}
1045 1046
		/* If a race occured in this function and we came second, tmpp
		 * is the first one that we just replaced. */
1047
		if (tmpp)
1048
			ERR_STATE_free(tmpp);
1049
		}
1050
	return ret;
1051 1052
	}

U
Ulf Möller 已提交
1053
int ERR_get_next_error_library(void)
1054
	{
1055 1056
	err_fns_check();
	return ERRFN(get_next_lib)();
1057 1058
	}

U
Ulf Möller 已提交
1059
void ERR_set_error_data(char *data, int flags)
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
	{
	ERR_STATE *es;
	int i;

	es=ERR_get_state();

	i=es->top;
	if (i == 0)
		i=ERR_NUM_ERRORS-1;

B
Bodo Möller 已提交
1070
	err_clear_data(es,i);
1071
	es->err_data[i]=data;
B
Bodo Möller 已提交
1072
	es->err_data_flags[i]=flags;
1073 1074
	}

U
Ulf Möller 已提交
1075
void ERR_add_error_data(int num, ...)
1076
	{
U
Ulf Möller 已提交
1077
	va_list args;
1078 1079 1080
	int i,n,s;
	char *str,*p,*a;

B
Bodo Möller 已提交
1081
	s=80;
1082
	str=OPENSSL_malloc(s+1);
1083 1084 1085
	if (str == NULL) return;
	str[0]='\0';

U
Ulf Möller 已提交
1086
	va_start(args, num);
1087 1088 1089
	n=0;
	for (i=0; i<num; i++)
		{
U
Ulf Möller 已提交
1090
		a=va_arg(args, char*);
1091 1092
		/* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
		if (a != NULL)
1093
			{
1094 1095
			n+=strlen(a);
			if (n > s)
1096
				{
1097
				s=n+20;
1098
				p=OPENSSL_realloc(str,s+1);
1099 1100
				if (p == NULL)
					{
1101
					OPENSSL_free(str);
1102
					goto err;
1103 1104 1105
					}
				else
					str=p;
1106
				}
N
Nils Larsch 已提交
1107
			BUF_strlcat(str,a,(size_t)s+1);
1108 1109 1110 1111
			}
		}
	ERR_set_error_data(str,ERR_TXT_MALLOCED|ERR_TXT_STRING);

1112
err:
U
Ulf Möller 已提交
1113
	va_end(args);
1114
	}
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137

int ERR_set_mark(void)
	{
	ERR_STATE *es;

	es=ERR_get_state();

	if (es->bottom == es->top) return 0;
	es->err_flags[es->top]|=ERR_FLAG_MARK;
	return 1;
	}

int ERR_pop_to_mark(void)
	{
	ERR_STATE *es;

	es=ERR_get_state();

	while(es->bottom != es->top
		&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0)
		{
		err_clear(es,es->top);
		es->top-=1;
N
Nils Larsch 已提交
1138
		if (es->top == -1) es->top=ERR_NUM_ERRORS-1;
1139 1140 1141 1142 1143 1144
		}
		
	if (es->bottom == es->top) return 0;
	es->err_flags[es->top]&=~ERR_FLAG_MARK;
	return 1;
	}