155714Skris/* crypto/err/err.c */ 255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 355714Skris * All rights reserved. 455714Skris * 555714Skris * This package is an SSL implementation written 655714Skris * by Eric Young (eay@cryptsoft.com). 755714Skris * The implementation was written so as to conform with Netscapes SSL. 8280304Sjkim * 955714Skris * This library is free for commercial and non-commercial use as long as 1055714Skris * the following conditions are aheared to. The following conditions 1155714Skris * apply to all code found in this distribution, be it the RC4, RSA, 1255714Skris * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1355714Skris * included with this distribution is covered by the same copyright terms 1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15280304Sjkim * 1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in 1755714Skris * the code are not to be removed. 1855714Skris * If this package is used in a product, Eric Young should be given attribution 1955714Skris * as the author of the parts of the library used. 2055714Skris * This can be in the form of a textual message at program startup or 2155714Skris * in documentation (online or textual) provided with the package. 22280304Sjkim * 2355714Skris * Redistribution and use in source and binary forms, with or without 2455714Skris * modification, are permitted provided that the following conditions 2555714Skris * are met: 2655714Skris * 1. Redistributions of source code must retain the copyright 2755714Skris * notice, this list of conditions and the following disclaimer. 2855714Skris * 2. Redistributions in binary form must reproduce the above copyright 2955714Skris * notice, this list of conditions and the following disclaimer in the 3055714Skris * documentation and/or other materials provided with the distribution. 3155714Skris * 3. All advertising materials mentioning features or use of this software 3255714Skris * must display the following acknowledgement: 3355714Skris * "This product includes cryptographic software written by 3455714Skris * Eric Young (eay@cryptsoft.com)" 3555714Skris * The word 'cryptographic' can be left out if the rouines from the library 3655714Skris * being used are not cryptographic related :-). 37280304Sjkim * 4. If you include any Windows specific code (or a derivative thereof) from 3855714Skris * the apps directory (application code) you must include an acknowledgement: 3955714Skris * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40280304Sjkim * 4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5155714Skris * SUCH DAMAGE. 52280304Sjkim * 5355714Skris * The licence and distribution terms for any publically available version or 5455714Skris * derivative of this code cannot be changed. i.e. this code cannot simply be 5555714Skris * copied and put under another distribution licence 5655714Skris * [including the GNU Public Licence.] 5755714Skris */ 5859191Skris/* ==================================================================== 59238405Sjkim * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. 6059191Skris * 6159191Skris * Redistribution and use in source and binary forms, with or without 6259191Skris * modification, are permitted provided that the following conditions 6359191Skris * are met: 6459191Skris * 6559191Skris * 1. Redistributions of source code must retain the above copyright 66280304Sjkim * notice, this list of conditions and the following disclaimer. 6759191Skris * 6859191Skris * 2. Redistributions in binary form must reproduce the above copyright 6959191Skris * notice, this list of conditions and the following disclaimer in 7059191Skris * the documentation and/or other materials provided with the 7159191Skris * distribution. 7259191Skris * 7359191Skris * 3. All advertising materials mentioning features or use of this 7459191Skris * software must display the following acknowledgment: 7559191Skris * "This product includes software developed by the OpenSSL Project 7659191Skris * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 7759191Skris * 7859191Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 7959191Skris * endorse or promote products derived from this software without 8059191Skris * prior written permission. For written permission, please contact 8159191Skris * openssl-core@openssl.org. 8259191Skris * 8359191Skris * 5. Products derived from this software may not be called "OpenSSL" 8459191Skris * nor may "OpenSSL" appear in their names without prior written 8559191Skris * permission of the OpenSSL Project. 8659191Skris * 8759191Skris * 6. Redistributions of any form whatsoever must retain the following 8859191Skris * acknowledgment: 8959191Skris * "This product includes software developed by the OpenSSL Project 9059191Skris * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 9159191Skris * 9259191Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 9359191Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9459191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 9559191Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 9659191Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 9759191Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 9859191Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 9959191Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 10059191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 10159191Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10259191Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 10359191Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 10459191Skris * ==================================================================== 10559191Skris * 10659191Skris * This product includes cryptographic software written by Eric Young 10759191Skris * (eay@cryptsoft.com). This product includes software written by Tim 10859191Skris * Hudson (tjh@cryptsoft.com). 10959191Skris * 11059191Skris */ 11155714Skris 11255714Skris#include <stdio.h> 11355714Skris#include <stdarg.h> 11459191Skris#include <string.h> 115160814Ssimon#include "cryptlib.h" 11655714Skris#include <openssl/lhash.h> 11755714Skris#include <openssl/crypto.h> 11855714Skris#include <openssl/buffer.h> 11968651Skris#include <openssl/bio.h> 12055714Skris#include <openssl/err.h> 12155714Skris 122238405SjkimDECLARE_LHASH_OF(ERR_STRING_DATA); 123238405SjkimDECLARE_LHASH_OF(ERR_STATE); 12455714Skris 125238405Sjkimstatic void err_load_strings(int lib, ERR_STRING_DATA *str); 126238405Sjkim 127238405Sjkimstatic void ERR_STATE_free(ERR_STATE *s); 128238405Sjkim#ifndef OPENSSL_NO_ERR 129280304Sjkimstatic ERR_STRING_DATA ERR_str_libraries[] = { 130280304Sjkim {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"}, 131280304Sjkim {ERR_PACK(ERR_LIB_SYS, 0, 0), "system library"}, 132280304Sjkim {ERR_PACK(ERR_LIB_BN, 0, 0), "bignum routines"}, 133280304Sjkim {ERR_PACK(ERR_LIB_RSA, 0, 0), "rsa routines"}, 134280304Sjkim {ERR_PACK(ERR_LIB_DH, 0, 0), "Diffie-Hellman routines"}, 135280304Sjkim {ERR_PACK(ERR_LIB_EVP, 0, 0), "digital envelope routines"}, 136280304Sjkim {ERR_PACK(ERR_LIB_BUF, 0, 0), "memory buffer routines"}, 137280304Sjkim {ERR_PACK(ERR_LIB_OBJ, 0, 0), "object identifier routines"}, 138280304Sjkim {ERR_PACK(ERR_LIB_PEM, 0, 0), "PEM routines"}, 139280304Sjkim {ERR_PACK(ERR_LIB_DSA, 0, 0), "dsa routines"}, 140280304Sjkim {ERR_PACK(ERR_LIB_X509, 0, 0), "x509 certificate routines"}, 141280304Sjkim {ERR_PACK(ERR_LIB_ASN1, 0, 0), "asn1 encoding routines"}, 142280304Sjkim {ERR_PACK(ERR_LIB_CONF, 0, 0), "configuration file routines"}, 143280304Sjkim {ERR_PACK(ERR_LIB_CRYPTO, 0, 0), "common libcrypto routines"}, 144280304Sjkim {ERR_PACK(ERR_LIB_EC, 0, 0), "elliptic curve routines"}, 145280304Sjkim {ERR_PACK(ERR_LIB_SSL, 0, 0), "SSL routines"}, 146280304Sjkim {ERR_PACK(ERR_LIB_BIO, 0, 0), "BIO routines"}, 147280304Sjkim {ERR_PACK(ERR_LIB_PKCS7, 0, 0), "PKCS7 routines"}, 148280304Sjkim {ERR_PACK(ERR_LIB_X509V3, 0, 0), "X509 V3 routines"}, 149280304Sjkim {ERR_PACK(ERR_LIB_PKCS12, 0, 0), "PKCS12 routines"}, 150280304Sjkim {ERR_PACK(ERR_LIB_RAND, 0, 0), "random number generator"}, 151280304Sjkim {ERR_PACK(ERR_LIB_DSO, 0, 0), "DSO support routines"}, 152280304Sjkim {ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"}, 153280304Sjkim {ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"}, 154280304Sjkim {ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"}, 155280304Sjkim {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"}, 156280304Sjkim {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"}, 157280304Sjkim {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"}, 158280304Sjkim {0, NULL}, 159280304Sjkim}; 160238405Sjkim 161280304Sjkimstatic ERR_STRING_DATA ERR_str_functs[] = { 162280304Sjkim {ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"}, 163280304Sjkim {ERR_PACK(0, SYS_F_CONNECT, 0), "connect"}, 164280304Sjkim {ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"}, 165280304Sjkim {ERR_PACK(0, SYS_F_SOCKET, 0), "socket"}, 166280304Sjkim {ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"}, 167280304Sjkim {ERR_PACK(0, SYS_F_BIND, 0), "bind"}, 168280304Sjkim {ERR_PACK(0, SYS_F_LISTEN, 0), "listen"}, 169280304Sjkim {ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"}, 170280304Sjkim# ifdef OPENSSL_SYS_WINDOWS 171280304Sjkim {ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"}, 172280304Sjkim# endif 173280304Sjkim {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"}, 174280304Sjkim {ERR_PACK(0, SYS_F_FREAD, 0), "fread"}, 175280304Sjkim {0, NULL}, 176280304Sjkim}; 177238405Sjkim 178280304Sjkimstatic ERR_STRING_DATA ERR_str_reasons[] = { 179280304Sjkim {ERR_R_SYS_LIB, "system lib"}, 180280304Sjkim {ERR_R_BN_LIB, "BN lib"}, 181280304Sjkim {ERR_R_RSA_LIB, "RSA lib"}, 182280304Sjkim {ERR_R_DH_LIB, "DH lib"}, 183280304Sjkim {ERR_R_EVP_LIB, "EVP lib"}, 184280304Sjkim {ERR_R_BUF_LIB, "BUF lib"}, 185280304Sjkim {ERR_R_OBJ_LIB, "OBJ lib"}, 186280304Sjkim {ERR_R_PEM_LIB, "PEM lib"}, 187280304Sjkim {ERR_R_DSA_LIB, "DSA lib"}, 188280304Sjkim {ERR_R_X509_LIB, "X509 lib"}, 189280304Sjkim {ERR_R_ASN1_LIB, "ASN1 lib"}, 190280304Sjkim {ERR_R_CONF_LIB, "CONF lib"}, 191280304Sjkim {ERR_R_CRYPTO_LIB, "CRYPTO lib"}, 192280304Sjkim {ERR_R_EC_LIB, "EC lib"}, 193280304Sjkim {ERR_R_SSL_LIB, "SSL lib"}, 194280304Sjkim {ERR_R_BIO_LIB, "BIO lib"}, 195280304Sjkim {ERR_R_PKCS7_LIB, "PKCS7 lib"}, 196280304Sjkim {ERR_R_X509V3_LIB, "X509V3 lib"}, 197280304Sjkim {ERR_R_PKCS12_LIB, "PKCS12 lib"}, 198280304Sjkim {ERR_R_RAND_LIB, "RAND lib"}, 199280304Sjkim {ERR_R_DSO_LIB, "DSO lib"}, 200280304Sjkim {ERR_R_ENGINE_LIB, "ENGINE lib"}, 201280304Sjkim {ERR_R_OCSP_LIB, "OCSP lib"}, 202280304Sjkim {ERR_R_TS_LIB, "TS lib"}, 203238405Sjkim 204280304Sjkim {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"}, 205280304Sjkim {ERR_R_BAD_ASN1_OBJECT_HEADER, "bad asn1 object header"}, 206280304Sjkim {ERR_R_BAD_GET_ASN1_OBJECT_CALL, "bad get asn1 object call"}, 207280304Sjkim {ERR_R_EXPECTING_AN_ASN1_SEQUENCE, "expecting an asn1 sequence"}, 208280304Sjkim {ERR_R_ASN1_LENGTH_MISMATCH, "asn1 length mismatch"}, 209280304Sjkim {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"}, 210238405Sjkim 211280304Sjkim {ERR_R_FATAL, "fatal"}, 212280304Sjkim {ERR_R_MALLOC_FAILURE, "malloc failure"}, 213280304Sjkim {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, 214280304Sjkim "called a function you should not call"}, 215280304Sjkim {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"}, 216280304Sjkim {ERR_R_INTERNAL_ERROR, "internal error"}, 217280304Sjkim {ERR_R_DISABLED, "called a function that was disabled at compile-time"}, 218238405Sjkim 219280304Sjkim {0, NULL}, 220280304Sjkim}; 221238405Sjkim#endif 222238405Sjkim 223238405Sjkim/* Define the predeclared (but externally opaque) "ERR_FNS" type */ 224280304Sjkimstruct st_ERR_FNS { 225280304Sjkim /* Works on the "error_hash" string table */ 226280304Sjkim LHASH_OF(ERR_STRING_DATA) *(*cb_err_get) (int create); 227280304Sjkim void (*cb_err_del) (void); 228280304Sjkim ERR_STRING_DATA *(*cb_err_get_item) (const ERR_STRING_DATA *); 229280304Sjkim ERR_STRING_DATA *(*cb_err_set_item) (ERR_STRING_DATA *); 230280304Sjkim ERR_STRING_DATA *(*cb_err_del_item) (ERR_STRING_DATA *); 231280304Sjkim /* Works on the "thread_hash" error-state table */ 232280304Sjkim LHASH_OF(ERR_STATE) *(*cb_thread_get) (int create); 233280304Sjkim void (*cb_thread_release) (LHASH_OF(ERR_STATE) **hash); 234280304Sjkim ERR_STATE *(*cb_thread_get_item) (const ERR_STATE *); 235280304Sjkim ERR_STATE *(*cb_thread_set_item) (ERR_STATE *); 236280304Sjkim void (*cb_thread_del_item) (const ERR_STATE *); 237280304Sjkim /* Returns the next available error "library" numbers */ 238280304Sjkim int (*cb_get_next_lib) (void); 239280304Sjkim}; 240238405Sjkim 241238405Sjkim/* Predeclarations of the "err_defaults" functions */ 242238405Sjkimstatic LHASH_OF(ERR_STRING_DATA) *int_err_get(int create); 243238405Sjkimstatic void int_err_del(void); 244238405Sjkimstatic ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); 245238405Sjkimstatic ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *); 246238405Sjkimstatic ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *); 247238405Sjkimstatic LHASH_OF(ERR_STATE) *int_thread_get(int create); 248238405Sjkimstatic void int_thread_release(LHASH_OF(ERR_STATE) **hash); 249238405Sjkimstatic ERR_STATE *int_thread_get_item(const ERR_STATE *); 250238405Sjkimstatic ERR_STATE *int_thread_set_item(ERR_STATE *); 251238405Sjkimstatic void int_thread_del_item(const ERR_STATE *); 252238405Sjkimstatic int int_err_get_next_lib(void); 253238405Sjkim/* The static ERR_FNS table using these defaults functions */ 254280304Sjkimstatic const ERR_FNS err_defaults = { 255280304Sjkim int_err_get, 256280304Sjkim int_err_del, 257280304Sjkim int_err_get_item, 258280304Sjkim int_err_set_item, 259280304Sjkim int_err_del_item, 260280304Sjkim int_thread_get, 261280304Sjkim int_thread_release, 262280304Sjkim int_thread_get_item, 263280304Sjkim int_thread_set_item, 264280304Sjkim int_thread_del_item, 265280304Sjkim int_err_get_next_lib 266280304Sjkim}; 267238405Sjkim 268238405Sjkim/* The replacable table of ERR_FNS functions we use at run-time */ 269238405Sjkimstatic const ERR_FNS *err_fns = NULL; 270238405Sjkim 271238405Sjkim/* Eg. rather than using "err_get()", use "ERRFN(err_get)()". */ 272238405Sjkim#define ERRFN(a) err_fns->cb_##a 273238405Sjkim 274280304Sjkim/* 275280304Sjkim * The internal state used by "err_defaults" - as such, the setting, reading, 276238405Sjkim * creating, and deleting of this data should only be permitted via the 277280304Sjkim * "err_defaults" functions. This way, a linked module can completely defer 278280304Sjkim * all ERR state operation (together with requisite locking) to the 279280304Sjkim * implementations and state in the loading application. 280280304Sjkim */ 281238405Sjkimstatic LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; 282238405Sjkimstatic LHASH_OF(ERR_STATE) *int_thread_hash = NULL; 283238405Sjkimstatic int int_thread_hash_references = 0; 284280304Sjkimstatic int int_err_library_number = ERR_LIB_USER; 285238405Sjkim 286280304Sjkim/* 287280304Sjkim * Internal function that checks whether "err_fns" is set and if not, sets it 288280304Sjkim * to the defaults. 289280304Sjkim */ 290238405Sjkimstatic void err_fns_check(void) 291280304Sjkim{ 292280304Sjkim if (err_fns) 293280304Sjkim return; 294238405Sjkim 295280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 296280304Sjkim if (!err_fns) 297280304Sjkim err_fns = &err_defaults; 298280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 299280304Sjkim} 300280304Sjkim 301238405Sjkim/* API functions to get or set the underlying ERR functions. */ 302238405Sjkim 303238405Sjkimconst ERR_FNS *ERR_get_implementation(void) 304280304Sjkim{ 305280304Sjkim err_fns_check(); 306280304Sjkim return err_fns; 307280304Sjkim} 308238405Sjkim 309238405Sjkimint ERR_set_implementation(const ERR_FNS *fns) 310280304Sjkim{ 311280304Sjkim int ret = 0; 312238405Sjkim 313280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 314280304Sjkim /* 315280304Sjkim * It's too late if 'err_fns' is non-NULL. BTW: not much point setting an 316280304Sjkim * error is there?! 317280304Sjkim */ 318280304Sjkim if (!err_fns) { 319280304Sjkim err_fns = fns; 320280304Sjkim ret = 1; 321280304Sjkim } 322280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 323280304Sjkim return ret; 324280304Sjkim} 325238405Sjkim 326280304Sjkim/* 327280304Sjkim * These are the callbacks provided to "lh_new()" when creating the LHASH 328280304Sjkim * tables internal to the "err_defaults" implementation. 329280304Sjkim */ 330238405Sjkim 331280304Sjkimstatic unsigned long get_error_values(int inc, int top, const char **file, 332280304Sjkim int *line, const char **data, 333280304Sjkim int *flags); 334238405Sjkim 335238405Sjkim/* The internal functions used in the "err_defaults" implementation */ 336238405Sjkim 337238405Sjkimstatic unsigned long err_string_data_hash(const ERR_STRING_DATA *a) 338280304Sjkim{ 339280304Sjkim unsigned long ret, l; 340238405Sjkim 341280304Sjkim l = a->error; 342280304Sjkim ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l); 343280304Sjkim return (ret ^ ret % 19 * 13); 344280304Sjkim} 345280304Sjkim 346238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA) 347238405Sjkim 348238405Sjkimstatic int err_string_data_cmp(const ERR_STRING_DATA *a, 349280304Sjkim const ERR_STRING_DATA *b) 350280304Sjkim{ 351280304Sjkim return (int)(a->error - b->error); 352280304Sjkim} 353280304Sjkim 354238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA) 355238405Sjkim 356238405Sjkimstatic LHASH_OF(ERR_STRING_DATA) *int_err_get(int create) 357280304Sjkim{ 358280304Sjkim LHASH_OF(ERR_STRING_DATA) *ret = NULL; 359238405Sjkim 360280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 361280304Sjkim if (!int_error_hash && create) { 362280304Sjkim CRYPTO_push_info("int_err_get (err.c)"); 363280304Sjkim int_error_hash = lh_ERR_STRING_DATA_new(); 364280304Sjkim CRYPTO_pop_info(); 365280304Sjkim } 366280304Sjkim if (int_error_hash) 367280304Sjkim ret = int_error_hash; 368280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 369238405Sjkim 370280304Sjkim return ret; 371280304Sjkim} 372238405Sjkim 373238405Sjkimstatic void int_err_del(void) 374280304Sjkim{ 375280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 376280304Sjkim if (int_error_hash) { 377280304Sjkim lh_ERR_STRING_DATA_free(int_error_hash); 378280304Sjkim int_error_hash = NULL; 379280304Sjkim } 380280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 381280304Sjkim} 382238405Sjkim 383238405Sjkimstatic ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) 384280304Sjkim{ 385280304Sjkim ERR_STRING_DATA *p; 386280304Sjkim LHASH_OF(ERR_STRING_DATA) *hash; 387238405Sjkim 388280304Sjkim err_fns_check(); 389280304Sjkim hash = ERRFN(err_get) (0); 390280304Sjkim if (!hash) 391280304Sjkim return NULL; 392238405Sjkim 393280304Sjkim CRYPTO_r_lock(CRYPTO_LOCK_ERR); 394280304Sjkim p = lh_ERR_STRING_DATA_retrieve(hash, d); 395280304Sjkim CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 396238405Sjkim 397280304Sjkim return p; 398280304Sjkim} 399238405Sjkim 400238405Sjkimstatic ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) 401280304Sjkim{ 402280304Sjkim ERR_STRING_DATA *p; 403280304Sjkim LHASH_OF(ERR_STRING_DATA) *hash; 404238405Sjkim 405280304Sjkim err_fns_check(); 406280304Sjkim hash = ERRFN(err_get) (1); 407280304Sjkim if (!hash) 408280304Sjkim return NULL; 409238405Sjkim 410280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 411280304Sjkim p = lh_ERR_STRING_DATA_insert(hash, d); 412280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 413238405Sjkim 414280304Sjkim return p; 415280304Sjkim} 416238405Sjkim 417238405Sjkimstatic ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) 418280304Sjkim{ 419280304Sjkim ERR_STRING_DATA *p; 420280304Sjkim LHASH_OF(ERR_STRING_DATA) *hash; 421238405Sjkim 422280304Sjkim err_fns_check(); 423280304Sjkim hash = ERRFN(err_get) (0); 424280304Sjkim if (!hash) 425280304Sjkim return NULL; 426238405Sjkim 427280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 428280304Sjkim p = lh_ERR_STRING_DATA_delete(hash, d); 429280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 430238405Sjkim 431280304Sjkim return p; 432280304Sjkim} 433238405Sjkim 434238405Sjkimstatic unsigned long err_state_hash(const ERR_STATE *a) 435280304Sjkim{ 436280304Sjkim return CRYPTO_THREADID_hash(&a->tid) * 13; 437280304Sjkim} 438280304Sjkim 439238405Sjkimstatic IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE) 440238405Sjkim 441238405Sjkimstatic int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) 442280304Sjkim{ 443280304Sjkim return CRYPTO_THREADID_cmp(&a->tid, &b->tid); 444280304Sjkim} 445280304Sjkim 446238405Sjkimstatic IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE) 447238405Sjkim 448238405Sjkimstatic LHASH_OF(ERR_STATE) *int_thread_get(int create) 449280304Sjkim{ 450280304Sjkim LHASH_OF(ERR_STATE) *ret = NULL; 451238405Sjkim 452280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 453280304Sjkim if (!int_thread_hash && create) { 454280304Sjkim CRYPTO_push_info("int_thread_get (err.c)"); 455280304Sjkim int_thread_hash = lh_ERR_STATE_new(); 456280304Sjkim CRYPTO_pop_info(); 457280304Sjkim } 458280304Sjkim if (int_thread_hash) { 459280304Sjkim int_thread_hash_references++; 460280304Sjkim ret = int_thread_hash; 461280304Sjkim } 462280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 463280304Sjkim return ret; 464280304Sjkim} 465238405Sjkim 466238405Sjkimstatic void int_thread_release(LHASH_OF(ERR_STATE) **hash) 467280304Sjkim{ 468280304Sjkim int i; 469238405Sjkim 470280304Sjkim if (hash == NULL || *hash == NULL) 471280304Sjkim return; 472238405Sjkim 473280304Sjkim i = CRYPTO_add(&int_thread_hash_references, -1, CRYPTO_LOCK_ERR); 474238405Sjkim 475238405Sjkim#ifdef REF_PRINT 476280304Sjkim fprintf(stderr, "%4d:%s\n", int_thread_hash_references, "ERR"); 477238405Sjkim#endif 478280304Sjkim if (i > 0) 479280304Sjkim return; 480238405Sjkim#ifdef REF_CHECK 481280304Sjkim if (i < 0) { 482280304Sjkim fprintf(stderr, "int_thread_release, bad reference count\n"); 483280304Sjkim abort(); /* ok */ 484280304Sjkim } 485238405Sjkim#endif 486280304Sjkim *hash = NULL; 487280304Sjkim} 488238405Sjkim 489238405Sjkimstatic ERR_STATE *int_thread_get_item(const ERR_STATE *d) 490280304Sjkim{ 491280304Sjkim ERR_STATE *p; 492280304Sjkim LHASH_OF(ERR_STATE) *hash; 493238405Sjkim 494280304Sjkim err_fns_check(); 495280304Sjkim hash = ERRFN(thread_get) (0); 496280304Sjkim if (!hash) 497280304Sjkim return NULL; 498238405Sjkim 499280304Sjkim CRYPTO_r_lock(CRYPTO_LOCK_ERR); 500280304Sjkim p = lh_ERR_STATE_retrieve(hash, d); 501280304Sjkim CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 502238405Sjkim 503280304Sjkim ERRFN(thread_release) (&hash); 504280304Sjkim return p; 505280304Sjkim} 506238405Sjkim 507238405Sjkimstatic ERR_STATE *int_thread_set_item(ERR_STATE *d) 508280304Sjkim{ 509280304Sjkim ERR_STATE *p; 510280304Sjkim LHASH_OF(ERR_STATE) *hash; 511238405Sjkim 512280304Sjkim err_fns_check(); 513280304Sjkim hash = ERRFN(thread_get) (1); 514280304Sjkim if (!hash) 515280304Sjkim return NULL; 516238405Sjkim 517280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 518280304Sjkim p = lh_ERR_STATE_insert(hash, d); 519280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 520238405Sjkim 521280304Sjkim ERRFN(thread_release) (&hash); 522280304Sjkim return p; 523280304Sjkim} 524238405Sjkim 525238405Sjkimstatic void int_thread_del_item(const ERR_STATE *d) 526280304Sjkim{ 527280304Sjkim ERR_STATE *p; 528280304Sjkim LHASH_OF(ERR_STATE) *hash; 529238405Sjkim 530280304Sjkim err_fns_check(); 531280304Sjkim hash = ERRFN(thread_get) (0); 532280304Sjkim if (!hash) 533280304Sjkim return; 534238405Sjkim 535280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 536280304Sjkim p = lh_ERR_STATE_delete(hash, d); 537280304Sjkim /* make sure we don't leak memory */ 538280304Sjkim if (int_thread_hash_references == 1 539280304Sjkim && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0) { 540280304Sjkim lh_ERR_STATE_free(int_thread_hash); 541280304Sjkim int_thread_hash = NULL; 542280304Sjkim } 543280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 544238405Sjkim 545280304Sjkim ERRFN(thread_release) (&hash); 546280304Sjkim if (p) 547280304Sjkim ERR_STATE_free(p); 548280304Sjkim} 549238405Sjkim 550238405Sjkimstatic int int_err_get_next_lib(void) 551280304Sjkim{ 552280304Sjkim int ret; 553238405Sjkim 554280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 555280304Sjkim ret = int_err_library_number++; 556280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 557238405Sjkim 558280304Sjkim return ret; 559280304Sjkim} 560238405Sjkim 561238405Sjkim#ifndef OPENSSL_NO_ERR 562280304Sjkim# define NUM_SYS_STR_REASONS 127 563280304Sjkim# define LEN_SYS_STR_REASON 32 564238405Sjkim 565238405Sjkimstatic ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1]; 566280304Sjkim/* 567280304Sjkim * SYS_str_reasons is filled with copies of strerror() results at 568280304Sjkim * initialization. 'errno' values up to 127 should cover all usual errors, 569280304Sjkim * others will be displayed numerically by ERR_error_string. It is crucial 570280304Sjkim * that we have something for each reason code that occurs in 571280304Sjkim * ERR_str_reasons, or bogus reason strings will be returned for SYSerr(), 572280304Sjkim * which always gets an errno value and never one of those 'standard' reason 573280304Sjkim * codes. 574280304Sjkim */ 575238405Sjkim 576238405Sjkimstatic void build_SYS_str_reasons(void) 577280304Sjkim{ 578280304Sjkim /* OPENSSL_malloc cannot be used here, use static storage instead */ 579280304Sjkim static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON]; 580280304Sjkim int i; 581280304Sjkim static int init = 1; 582238405Sjkim 583280304Sjkim CRYPTO_r_lock(CRYPTO_LOCK_ERR); 584280304Sjkim if (!init) { 585280304Sjkim CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 586280304Sjkim return; 587280304Sjkim } 588238405Sjkim 589280304Sjkim CRYPTO_r_unlock(CRYPTO_LOCK_ERR); 590280304Sjkim CRYPTO_w_lock(CRYPTO_LOCK_ERR); 591280304Sjkim if (!init) { 592280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 593280304Sjkim return; 594280304Sjkim } 595238405Sjkim 596280304Sjkim for (i = 1; i <= NUM_SYS_STR_REASONS; i++) { 597280304Sjkim ERR_STRING_DATA *str = &SYS_str_reasons[i - 1]; 598238405Sjkim 599280304Sjkim str->error = (unsigned long)i; 600280304Sjkim if (str->string == NULL) { 601280304Sjkim char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]); 602280304Sjkim char *src = strerror(i); 603280304Sjkim if (src != NULL) { 604280304Sjkim strncpy(*dest, src, sizeof *dest); 605280304Sjkim (*dest)[sizeof *dest - 1] = '\0'; 606280304Sjkim str->string = *dest; 607280304Sjkim } 608280304Sjkim } 609280304Sjkim if (str->string == NULL) 610280304Sjkim str->string = "unknown"; 611280304Sjkim } 612238405Sjkim 613280304Sjkim /* 614280304Sjkim * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as 615280304Sjkim * required by ERR_load_strings. 616280304Sjkim */ 617280304Sjkim 618280304Sjkim init = 0; 619280304Sjkim 620280304Sjkim CRYPTO_w_unlock(CRYPTO_LOCK_ERR); 621280304Sjkim} 622238405Sjkim#endif 623238405Sjkim 62455714Skris#define err_clear_data(p,i) \ 625280304Sjkim do { \ 626280304Sjkim if (((p)->err_data[i] != NULL) && \ 627280304Sjkim (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ 628280304Sjkim { \ 629280304Sjkim OPENSSL_free((p)->err_data[i]); \ 630280304Sjkim (p)->err_data[i]=NULL; \ 631280304Sjkim } \ 632280304Sjkim (p)->err_data_flags[i]=0; \ 633280304Sjkim } while(0) 63455714Skris 635160814Ssimon#define err_clear(p,i) \ 636280304Sjkim do { \ 637280304Sjkim (p)->err_flags[i]=0; \ 638280304Sjkim (p)->err_buffer[i]=0; \ 639280304Sjkim err_clear_data(p,i); \ 640280304Sjkim (p)->err_file[i]=NULL; \ 641280304Sjkim (p)->err_line[i]= -1; \ 642280304Sjkim } while(0) 643160814Ssimon 644238405Sjkimstatic void ERR_STATE_free(ERR_STATE *s) 645280304Sjkim{ 646280304Sjkim int i; 647238405Sjkim 648280304Sjkim if (s == NULL) 649280304Sjkim return; 650238405Sjkim 651280304Sjkim for (i = 0; i < ERR_NUM_ERRORS; i++) { 652280304Sjkim err_clear_data(s, i); 653280304Sjkim } 654280304Sjkim OPENSSL_free(s); 655280304Sjkim} 656238405Sjkim 657238405Sjkimvoid ERR_load_ERR_strings(void) 658280304Sjkim{ 659280304Sjkim err_fns_check(); 660238405Sjkim#ifndef OPENSSL_NO_ERR 661280304Sjkim err_load_strings(0, ERR_str_libraries); 662280304Sjkim err_load_strings(0, ERR_str_reasons); 663280304Sjkim err_load_strings(ERR_LIB_SYS, ERR_str_functs); 664280304Sjkim build_SYS_str_reasons(); 665280304Sjkim err_load_strings(ERR_LIB_SYS, SYS_str_reasons); 666238405Sjkim#endif 667280304Sjkim} 668238405Sjkim 669238405Sjkimstatic void err_load_strings(int lib, ERR_STRING_DATA *str) 670280304Sjkim{ 671280304Sjkim while (str->error) { 672280304Sjkim if (lib) 673280304Sjkim str->error |= ERR_PACK(lib, 0, 0); 674280304Sjkim ERRFN(err_set_item) (str); 675280304Sjkim str++; 676280304Sjkim } 677280304Sjkim} 678238405Sjkim 679238405Sjkimvoid ERR_load_strings(int lib, ERR_STRING_DATA *str) 680280304Sjkim{ 681280304Sjkim ERR_load_ERR_strings(); 682280304Sjkim err_load_strings(lib, str); 683280304Sjkim} 684238405Sjkim 685238405Sjkimvoid ERR_unload_strings(int lib, ERR_STRING_DATA *str) 686280304Sjkim{ 687280304Sjkim while (str->error) { 688280304Sjkim if (lib) 689280304Sjkim str->error |= ERR_PACK(lib, 0, 0); 690280304Sjkim ERRFN(err_del_item) (str); 691280304Sjkim str++; 692280304Sjkim } 693280304Sjkim} 694238405Sjkim 695238405Sjkimvoid ERR_free_strings(void) 696280304Sjkim{ 697280304Sjkim err_fns_check(); 698280304Sjkim ERRFN(err_del) (); 699280304Sjkim} 700238405Sjkim 701238405Sjkim/********************************************************/ 702238405Sjkim 703280304Sjkimvoid ERR_put_error(int lib, int func, int reason, const char *file, int line) 704280304Sjkim{ 705280304Sjkim ERR_STATE *es; 70655714Skris 70755714Skris#ifdef _OSD_POSIX 708280304Sjkim /* 709280304Sjkim * In the BS2000-OSD POSIX subsystem, the compiler generates path names 710280304Sjkim * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to 711280304Sjkim * something sensible. @@@ We shouldn't modify a const string, though. 712280304Sjkim */ 713280304Sjkim if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) { 714280304Sjkim char *end; 71555714Skris 716280304Sjkim /* Skip the "*POSIX(" prefix */ 717280304Sjkim file += sizeof("*POSIX(") - 1; 718280304Sjkim end = &file[strlen(file) - 1]; 719280304Sjkim if (*end == ')') 720280304Sjkim *end = '\0'; 721280304Sjkim /* Optional: use the basename of the path only. */ 722280304Sjkim if ((end = strrchr(file, '/')) != NULL) 723280304Sjkim file = &end[1]; 724280304Sjkim } 72555714Skris#endif 726280304Sjkim es = ERR_get_state(); 72755714Skris 728280304Sjkim es->top = (es->top + 1) % ERR_NUM_ERRORS; 729280304Sjkim if (es->top == es->bottom) 730280304Sjkim es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS; 731280304Sjkim es->err_flags[es->top] = 0; 732280304Sjkim es->err_buffer[es->top] = ERR_PACK(lib, func, reason); 733280304Sjkim es->err_file[es->top] = file; 734280304Sjkim es->err_line[es->top] = line; 735280304Sjkim err_clear_data(es, es->top); 736280304Sjkim} 73755714Skris 73855714Skrisvoid ERR_clear_error(void) 739280304Sjkim{ 740280304Sjkim int i; 741280304Sjkim ERR_STATE *es; 74255714Skris 743280304Sjkim es = ERR_get_state(); 74455714Skris 745280304Sjkim for (i = 0; i < ERR_NUM_ERRORS; i++) { 746280304Sjkim err_clear(es, i); 747280304Sjkim } 748280304Sjkim es->top = es->bottom = 0; 749280304Sjkim} 75055714Skris 75155714Skrisunsigned long ERR_get_error(void) 752280304Sjkim{ 753280304Sjkim return (get_error_values(1, 0, NULL, NULL, NULL, NULL)); 754280304Sjkim} 75555714Skris 756280304Sjkimunsigned long ERR_get_error_line(const char **file, int *line) 757280304Sjkim{ 758280304Sjkim return (get_error_values(1, 0, file, line, NULL, NULL)); 759280304Sjkim} 76055714Skris 76155714Skrisunsigned long ERR_get_error_line_data(const char **file, int *line, 762280304Sjkim const char **data, int *flags) 763280304Sjkim{ 764280304Sjkim return (get_error_values(1, 0, file, line, data, flags)); 765280304Sjkim} 76655714Skris 76755714Skrisunsigned long ERR_peek_error(void) 768280304Sjkim{ 769280304Sjkim return (get_error_values(0, 0, NULL, NULL, NULL, NULL)); 770280304Sjkim} 77155714Skris 772109998Smarkmunsigned long ERR_peek_error_line(const char **file, int *line) 773280304Sjkim{ 774280304Sjkim return (get_error_values(0, 0, file, line, NULL, NULL)); 775280304Sjkim} 77655714Skris 77755714Skrisunsigned long ERR_peek_error_line_data(const char **file, int *line, 778280304Sjkim const char **data, int *flags) 779280304Sjkim{ 780280304Sjkim return (get_error_values(0, 0, file, line, data, flags)); 781280304Sjkim} 78255714Skris 783109998Smarkmunsigned long ERR_peek_last_error(void) 784280304Sjkim{ 785280304Sjkim return (get_error_values(0, 1, NULL, NULL, NULL, NULL)); 786280304Sjkim} 787109998Smarkm 788109998Smarkmunsigned long ERR_peek_last_error_line(const char **file, int *line) 789280304Sjkim{ 790280304Sjkim return (get_error_values(0, 1, file, line, NULL, NULL)); 791280304Sjkim} 792109998Smarkm 793109998Smarkmunsigned long ERR_peek_last_error_line_data(const char **file, int *line, 794280304Sjkim const char **data, int *flags) 795280304Sjkim{ 796280304Sjkim return (get_error_values(0, 1, file, line, data, flags)); 797280304Sjkim} 798109998Smarkm 799280304Sjkimstatic unsigned long get_error_values(int inc, int top, const char **file, 800280304Sjkim int *line, const char **data, 801280304Sjkim int *flags) 802280304Sjkim{ 803280304Sjkim int i = 0; 804280304Sjkim ERR_STATE *es; 805280304Sjkim unsigned long ret; 806109998Smarkm 807280304Sjkim es = ERR_get_state(); 80855714Skris 809280304Sjkim if (inc && top) { 810280304Sjkim if (file) 811280304Sjkim *file = ""; 812280304Sjkim if (line) 813280304Sjkim *line = 0; 814280304Sjkim if (data) 815280304Sjkim *data = ""; 816280304Sjkim if (flags) 817280304Sjkim *flags = 0; 81855714Skris 819280304Sjkim return ERR_R_INTERNAL_ERROR; 820280304Sjkim } 82155714Skris 822280304Sjkim if (es->bottom == es->top) 823280304Sjkim return 0; 824280304Sjkim if (top) 825280304Sjkim i = es->top; /* last error */ 826280304Sjkim else 827280304Sjkim i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */ 828109998Smarkm 829280304Sjkim ret = es->err_buffer[i]; 830280304Sjkim if (inc) { 831280304Sjkim es->bottom = i; 832280304Sjkim es->err_buffer[i] = 0; 833280304Sjkim } 83455714Skris 835280304Sjkim if ((file != NULL) && (line != NULL)) { 836280304Sjkim if (es->err_file[i] == NULL) { 837280304Sjkim *file = "NA"; 838280304Sjkim if (line != NULL) 839280304Sjkim *line = 0; 840280304Sjkim } else { 841280304Sjkim *file = es->err_file[i]; 842280304Sjkim if (line != NULL) 843280304Sjkim *line = es->err_line[i]; 844280304Sjkim } 845280304Sjkim } 84655714Skris 847280304Sjkim if (data == NULL) { 848280304Sjkim if (inc) { 849280304Sjkim err_clear_data(es, i); 850280304Sjkim } 851280304Sjkim } else { 852280304Sjkim if (es->err_data[i] == NULL) { 853280304Sjkim *data = ""; 854280304Sjkim if (flags != NULL) 855280304Sjkim *flags = 0; 856280304Sjkim } else { 857280304Sjkim *data = es->err_data[i]; 858280304Sjkim if (flags != NULL) 859280304Sjkim *flags = es->err_data_flags[i]; 860280304Sjkim } 861280304Sjkim } 862280304Sjkim return ret; 863280304Sjkim} 86455714Skris 865238405Sjkimvoid ERR_error_string_n(unsigned long e, char *buf, size_t len) 866280304Sjkim{ 867280304Sjkim char lsbuf[64], fsbuf[64], rsbuf[64]; 868280304Sjkim const char *ls, *fs, *rs; 869280304Sjkim unsigned long l, f, r; 870238405Sjkim 871280304Sjkim l = ERR_GET_LIB(e); 872280304Sjkim f = ERR_GET_FUNC(e); 873280304Sjkim r = ERR_GET_REASON(e); 874238405Sjkim 875280304Sjkim ls = ERR_lib_error_string(e); 876280304Sjkim fs = ERR_func_error_string(e); 877280304Sjkim rs = ERR_reason_error_string(e); 878238405Sjkim 879280304Sjkim if (ls == NULL) 880280304Sjkim BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l); 881280304Sjkim if (fs == NULL) 882280304Sjkim BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f); 883280304Sjkim if (rs == NULL) 884280304Sjkim BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r); 885238405Sjkim 886280304Sjkim BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls ? ls : lsbuf, 887280304Sjkim fs ? fs : fsbuf, rs ? rs : rsbuf); 888280304Sjkim if (strlen(buf) == len - 1) { 889280304Sjkim /* 890280304Sjkim * output may be truncated; make sure we always have 5 891280304Sjkim * colon-separated fields, i.e. 4 colons ... 892280304Sjkim */ 893238405Sjkim#define NUM_COLONS 4 894280304Sjkim if (len > NUM_COLONS) { /* ... if possible */ 895280304Sjkim int i; 896280304Sjkim char *s = buf; 897238405Sjkim 898280304Sjkim for (i = 0; i < NUM_COLONS; i++) { 899280304Sjkim char *colon = strchr(s, ':'); 900280304Sjkim if (colon == NULL || colon > &buf[len - 1] - NUM_COLONS + i) { 901280304Sjkim /* 902280304Sjkim * set colon no. i at last possible position (buf[len-1] 903280304Sjkim * is the terminating 0) 904280304Sjkim */ 905280304Sjkim colon = &buf[len - 1] - NUM_COLONS + i; 906280304Sjkim *colon = ':'; 907280304Sjkim } 908280304Sjkim s = colon + 1; 909280304Sjkim } 910280304Sjkim } 911280304Sjkim } 912280304Sjkim} 913280304Sjkim 914238405Sjkim/* BAD for multi-threading: uses a local buffer if ret == NULL */ 915280304Sjkim/* 916280304Sjkim * ERR_error_string_n should be used instead for ret != NULL as 917280304Sjkim * ERR_error_string cannot know how large the buffer is 918280304Sjkim */ 919238405Sjkimchar *ERR_error_string(unsigned long e, char *ret) 920280304Sjkim{ 921280304Sjkim static char buf[256]; 922238405Sjkim 923280304Sjkim if (ret == NULL) 924280304Sjkim ret = buf; 925280304Sjkim ERR_error_string_n(e, ret, 256); 926238405Sjkim 927280304Sjkim return ret; 928280304Sjkim} 929238405Sjkim 930238405SjkimLHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void) 931280304Sjkim{ 932280304Sjkim err_fns_check(); 933280304Sjkim return ERRFN(err_get) (0); 934280304Sjkim} 935238405Sjkim 936238405SjkimLHASH_OF(ERR_STATE) *ERR_get_err_state_table(void) 937280304Sjkim{ 938280304Sjkim err_fns_check(); 939280304Sjkim return ERRFN(thread_get) (0); 940280304Sjkim} 941238405Sjkim 942238405Sjkimvoid ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash) 943280304Sjkim{ 944280304Sjkim err_fns_check(); 945280304Sjkim ERRFN(thread_release) (hash); 946280304Sjkim} 947238405Sjkim 948238405Sjkimconst char *ERR_lib_error_string(unsigned long e) 949280304Sjkim{ 950280304Sjkim ERR_STRING_DATA d, *p; 951280304Sjkim unsigned long l; 952238405Sjkim 953280304Sjkim err_fns_check(); 954280304Sjkim l = ERR_GET_LIB(e); 955280304Sjkim d.error = ERR_PACK(l, 0, 0); 956280304Sjkim p = ERRFN(err_get_item) (&d); 957280304Sjkim return ((p == NULL) ? NULL : p->string); 958280304Sjkim} 959238405Sjkim 960238405Sjkimconst char *ERR_func_error_string(unsigned long e) 961280304Sjkim{ 962280304Sjkim ERR_STRING_DATA d, *p; 963280304Sjkim unsigned long l, f; 964238405Sjkim 965280304Sjkim err_fns_check(); 966280304Sjkim l = ERR_GET_LIB(e); 967280304Sjkim f = ERR_GET_FUNC(e); 968280304Sjkim d.error = ERR_PACK(l, f, 0); 969280304Sjkim p = ERRFN(err_get_item) (&d); 970280304Sjkim return ((p == NULL) ? NULL : p->string); 971280304Sjkim} 972238405Sjkim 973238405Sjkimconst char *ERR_reason_error_string(unsigned long e) 974280304Sjkim{ 975280304Sjkim ERR_STRING_DATA d, *p = NULL; 976280304Sjkim unsigned long l, r; 977238405Sjkim 978280304Sjkim err_fns_check(); 979280304Sjkim l = ERR_GET_LIB(e); 980280304Sjkim r = ERR_GET_REASON(e); 981280304Sjkim d.error = ERR_PACK(l, 0, r); 982280304Sjkim p = ERRFN(err_get_item) (&d); 983280304Sjkim if (!p) { 984280304Sjkim d.error = ERR_PACK(0, 0, r); 985280304Sjkim p = ERRFN(err_get_item) (&d); 986280304Sjkim } 987280304Sjkim return ((p == NULL) ? NULL : p->string); 988280304Sjkim} 989238405Sjkim 990238405Sjkimvoid ERR_remove_thread_state(const CRYPTO_THREADID *id) 991280304Sjkim{ 992280304Sjkim ERR_STATE tmp; 993238405Sjkim 994280304Sjkim if (id) 995280304Sjkim CRYPTO_THREADID_cpy(&tmp.tid, id); 996280304Sjkim else 997280304Sjkim CRYPTO_THREADID_current(&tmp.tid); 998280304Sjkim err_fns_check(); 999280304Sjkim /* 1000280304Sjkim * thread_del_item automatically destroys the LHASH if the number of 1001280304Sjkim * items reaches zero. 1002280304Sjkim */ 1003280304Sjkim ERRFN(thread_del_item) (&tmp); 1004280304Sjkim} 1005238405Sjkim 1006238405Sjkim#ifndef OPENSSL_NO_DEPRECATED 1007238405Sjkimvoid ERR_remove_state(unsigned long pid) 1008280304Sjkim{ 1009280304Sjkim ERR_remove_thread_state(NULL); 1010280304Sjkim} 1011238405Sjkim#endif 1012238405Sjkim 1013238405SjkimERR_STATE *ERR_get_state(void) 1014280304Sjkim{ 1015280304Sjkim static ERR_STATE fallback; 1016280304Sjkim ERR_STATE *ret, tmp, *tmpp = NULL; 1017280304Sjkim int i; 1018280304Sjkim CRYPTO_THREADID tid; 1019238405Sjkim 1020280304Sjkim err_fns_check(); 1021280304Sjkim CRYPTO_THREADID_current(&tid); 1022280304Sjkim CRYPTO_THREADID_cpy(&tmp.tid, &tid); 1023280304Sjkim ret = ERRFN(thread_get_item) (&tmp); 1024238405Sjkim 1025280304Sjkim /* ret == the error state, if NULL, make a new one */ 1026280304Sjkim if (ret == NULL) { 1027280304Sjkim ret = (ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); 1028280304Sjkim if (ret == NULL) 1029280304Sjkim return (&fallback); 1030280304Sjkim CRYPTO_THREADID_cpy(&ret->tid, &tid); 1031280304Sjkim ret->top = 0; 1032280304Sjkim ret->bottom = 0; 1033280304Sjkim for (i = 0; i < ERR_NUM_ERRORS; i++) { 1034280304Sjkim ret->err_data[i] = NULL; 1035280304Sjkim ret->err_data_flags[i] = 0; 1036280304Sjkim } 1037280304Sjkim tmpp = ERRFN(thread_set_item) (ret); 1038280304Sjkim /* To check if insertion failed, do a get. */ 1039280304Sjkim if (ERRFN(thread_get_item) (ret) != ret) { 1040280304Sjkim ERR_STATE_free(ret); /* could not insert it */ 1041280304Sjkim return (&fallback); 1042280304Sjkim } 1043280304Sjkim /* 1044280304Sjkim * If a race occured in this function and we came second, tmpp is the 1045280304Sjkim * first one that we just replaced. 1046280304Sjkim */ 1047280304Sjkim if (tmpp) 1048280304Sjkim ERR_STATE_free(tmpp); 1049280304Sjkim } 1050280304Sjkim return ret; 1051280304Sjkim} 1052238405Sjkim 1053238405Sjkimint ERR_get_next_error_library(void) 1054280304Sjkim{ 1055280304Sjkim err_fns_check(); 1056280304Sjkim return ERRFN(get_next_lib) (); 1057280304Sjkim} 1058238405Sjkim 105955714Skrisvoid ERR_set_error_data(char *data, int flags) 1060280304Sjkim{ 1061280304Sjkim ERR_STATE *es; 1062280304Sjkim int i; 106355714Skris 1064280304Sjkim es = ERR_get_state(); 106555714Skris 1066280304Sjkim i = es->top; 1067280304Sjkim if (i == 0) 1068280304Sjkim i = ERR_NUM_ERRORS - 1; 106955714Skris 1070280304Sjkim err_clear_data(es, i); 1071280304Sjkim es->err_data[i] = data; 1072280304Sjkim es->err_data_flags[i] = flags; 1073280304Sjkim} 107455714Skris 107555714Skrisvoid ERR_add_error_data(int num, ...) 1076280304Sjkim{ 1077280304Sjkim va_list args; 1078280304Sjkim va_start(args, num); 1079280304Sjkim ERR_add_error_vdata(num, args); 1080280304Sjkim va_end(args); 1081280304Sjkim} 1082238405Sjkim 1083238405Sjkimvoid ERR_add_error_vdata(int num, va_list args) 1084280304Sjkim{ 1085280304Sjkim int i, n, s; 1086280304Sjkim char *str, *p, *a; 108755714Skris 1088280304Sjkim s = 80; 1089280304Sjkim str = OPENSSL_malloc(s + 1); 1090280304Sjkim if (str == NULL) 1091280304Sjkim return; 1092280304Sjkim str[0] = '\0'; 109355714Skris 1094280304Sjkim n = 0; 1095280304Sjkim for (i = 0; i < num; i++) { 1096280304Sjkim a = va_arg(args, char *); 1097280304Sjkim /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */ 1098280304Sjkim if (a != NULL) { 1099280304Sjkim n += strlen(a); 1100280304Sjkim if (n > s) { 1101280304Sjkim s = n + 20; 1102280304Sjkim p = OPENSSL_realloc(str, s + 1); 1103280304Sjkim if (p == NULL) { 1104280304Sjkim OPENSSL_free(str); 1105280304Sjkim return; 1106280304Sjkim } else 1107280304Sjkim str = p; 1108280304Sjkim } 1109280304Sjkim BUF_strlcat(str, a, (size_t)s + 1); 1110280304Sjkim } 1111280304Sjkim } 1112280304Sjkim ERR_set_error_data(str, ERR_TXT_MALLOCED | ERR_TXT_STRING); 1113280304Sjkim} 1114160814Ssimon 1115160814Ssimonint ERR_set_mark(void) 1116280304Sjkim{ 1117280304Sjkim ERR_STATE *es; 1118160814Ssimon 1119280304Sjkim es = ERR_get_state(); 1120160814Ssimon 1121280304Sjkim if (es->bottom == es->top) 1122280304Sjkim return 0; 1123280304Sjkim es->err_flags[es->top] |= ERR_FLAG_MARK; 1124280304Sjkim return 1; 1125280304Sjkim} 1126160814Ssimon 1127160814Ssimonint ERR_pop_to_mark(void) 1128280304Sjkim{ 1129280304Sjkim ERR_STATE *es; 1130160814Ssimon 1131280304Sjkim es = ERR_get_state(); 1132160814Ssimon 1133280304Sjkim while (es->bottom != es->top 1134280304Sjkim && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) { 1135280304Sjkim err_clear(es, es->top); 1136280304Sjkim es->top -= 1; 1137280304Sjkim if (es->top == -1) 1138280304Sjkim es->top = ERR_NUM_ERRORS - 1; 1139280304Sjkim } 1140280304Sjkim 1141280304Sjkim if (es->bottom == es->top) 1142280304Sjkim return 0; 1143280304Sjkim es->err_flags[es->top] &= ~ERR_FLAG_MARK; 1144280304Sjkim return 1; 1145280304Sjkim} 1146