X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Ferr%2Ferr.c;h=91949ba4681b6097b99e8eec19d1719c9a266de8;hp=5abe44e6d57d7b63cf6475a3ef275c93eb080db6;hb=4c8855b975bdd1b4c84cf32a6a4748d40ea4a14c;hpb=d15711efc6c82d5483dcf73ac7fa3ec5deb2c24a diff --git a/crypto/err/err.c b/crypto/err/err.c index 5abe44e6d5..91949ba468 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -56,7 +56,7 @@ * [including the GNU Public Licence.] */ /* ==================================================================== - * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -109,16 +109,21 @@ * */ +#define OPENSSL_NO_FIPS_ERR + #include #include #include +#include "cryptlib.h" #include #include -#include "cryptlib.h" #include #include #include +DECLARE_LHASH_OF(ERR_STRING_DATA); +DECLARE_LHASH_OF(ERR_STATE); + static void err_load_strings(int lib, ERR_STRING_DATA *str); static void ERR_STATE_free(ERR_STATE *s); @@ -140,6 +145,8 @@ static ERR_STRING_DATA ERR_str_libraries[]= {ERR_PACK(ERR_LIB_CONF,0,0) ,"configuration file routines"}, {ERR_PACK(ERR_LIB_CRYPTO,0,0) ,"common libcrypto routines"}, {ERR_PACK(ERR_LIB_EC,0,0) ,"elliptic curve routines"}, +{ERR_PACK(ERR_LIB_ECDSA,0,0) ,"ECDSA routines"}, +{ERR_PACK(ERR_LIB_ECDH,0,0) ,"ECDH routines"}, {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"}, @@ -147,8 +154,12 @@ static ERR_STRING_DATA ERR_str_libraries[]= {ERR_PACK(ERR_LIB_PKCS12,0,0) ,"PKCS12 routines"}, {ERR_PACK(ERR_LIB_RAND,0,0) ,"random number generator"}, {ERR_PACK(ERR_LIB_DSO,0,0) ,"DSO support routines"}, +{ERR_PACK(ERR_LIB_TS,0,0) ,"time stamp routines"}, {ERR_PACK(ERR_LIB_ENGINE,0,0) ,"engine routines"}, {ERR_PACK(ERR_LIB_OCSP,0,0) ,"OCSP routines"}, +{ERR_PACK(ERR_LIB_FIPS,0,0) ,"FIPS routines"}, +{ERR_PACK(ERR_LIB_CMS,0,0) ,"CMS routines"}, +{ERR_PACK(ERR_LIB_HMAC,0,0) ,"HMAC routines"}, {0,NULL}, }; @@ -195,6 +206,8 @@ static ERR_STRING_DATA ERR_str_reasons[]= {ERR_R_DSO_LIB ,"DSO lib"}, {ERR_R_ENGINE_LIB ,"ENGINE lib"}, {ERR_R_OCSP_LIB ,"OCSP lib"}, +{ERR_R_TS_LIB ,"TS lib"}, +{ERR_R_ECDSA_LIB ,"ECDSA lib"}, {ERR_R_NESTED_ASN1_ERROR ,"nested asn1 error"}, {ERR_R_BAD_ASN1_OBJECT_HEADER ,"bad asn1 object header"}, @@ -208,22 +221,25 @@ static ERR_STRING_DATA ERR_str_reasons[]= {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"}, +{ERR_R_DISABLED ,"called a function that was disabled at compile-time"}, {0,NULL}, }; +#endif /* Define the predeclared (but externally opaque) "ERR_FNS" type */ struct st_ERR_FNS { /* Works on the "error_hash" string table */ - LHASH *(*cb_err_get)(int create); + LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create); 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 *); ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *); /* Works on the "thread_hash" error-state table */ - LHASH *(*cb_thread_get)(int create); + LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create); + void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash); 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 *); @@ -232,12 +248,13 @@ struct st_ERR_FNS }; /* Predeclarations of the "err_defaults" functions */ -static LHASH *int_err_get(int create); +static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create); 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 *); static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *); -static LHASH *int_thread_get(int create); +static LHASH_OF(ERR_STATE) *int_thread_get(int create); +static void int_thread_release(LHASH_OF(ERR_STATE) **hash); 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 *); @@ -251,6 +268,7 @@ static const ERR_FNS err_defaults = int_err_set_item, int_err_del_item, int_thread_get, + int_thread_release, int_thread_get_item, int_thread_set_item, int_thread_del_item, @@ -268,8 +286,9 @@ static const ERR_FNS *err_fns = NULL; * "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. */ -static LHASH *int_error_hash = NULL; -static LHASH *int_thread_hash = NULL; +static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; +static LHASH_OF(ERR_STATE) *int_thread_hash = NULL; +static int int_thread_hash_references = 0; static int int_err_library_number= ERR_LIB_USER; /* Internal function that checks whether "err_fns" is set and if not, sets it to @@ -311,28 +330,37 @@ int ERR_set_implementation(const ERR_FNS *fns) /* 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); static unsigned long get_error_values(int inc,int top,const char **file,int *line, const char **data,int *flags); /* The internal functions used in the "err_defaults" implementation */ -static LHASH *int_err_get(int create) +static unsigned long err_string_data_hash(const ERR_STRING_DATA *a) { - LHASH *ret = NULL; + unsigned long ret,l; + + l=a->error; + ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); + return(ret^ret%19*13); + } +static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA) + +static int err_string_data_cmp(const ERR_STRING_DATA *a, + const ERR_STRING_DATA *b) + { + return (int)(a->error - b->error); + } +static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA) + +static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create) + { + LHASH_OF(ERR_STRING_DATA) *ret = NULL; CRYPTO_w_lock(CRYPTO_LOCK_ERR); if (!int_error_hash && create) { CRYPTO_push_info("int_err_get (err.c)"); - int_error_hash = lh_new(err_hash, err_cmp); + int_error_hash = lh_ERR_STRING_DATA_new(); CRYPTO_pop_info(); } if (int_error_hash) @@ -347,7 +375,7 @@ static void int_err_del(void) CRYPTO_w_lock(CRYPTO_LOCK_ERR); if (int_error_hash) { - lh_free(int_error_hash); + lh_ERR_STRING_DATA_free(int_error_hash); int_error_hash = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_ERR); @@ -356,7 +384,7 @@ static void int_err_del(void) static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) { ERR_STRING_DATA *p; - LHASH *hash; + LHASH_OF(ERR_STRING_DATA) *hash; err_fns_check(); hash = ERRFN(err_get)(0); @@ -364,7 +392,7 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) return NULL; CRYPTO_r_lock(CRYPTO_LOCK_ERR); - p = (ERR_STRING_DATA *)lh_retrieve(hash, d); + p = lh_ERR_STRING_DATA_retrieve(hash, d); CRYPTO_r_unlock(CRYPTO_LOCK_ERR); return p; @@ -373,7 +401,7 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) { ERR_STRING_DATA *p; - LHASH *hash; + LHASH_OF(ERR_STRING_DATA) *hash; err_fns_check(); hash = ERRFN(err_get)(1); @@ -381,7 +409,7 @@ static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) return NULL; CRYPTO_w_lock(CRYPTO_LOCK_ERR); - p = (ERR_STRING_DATA *)lh_insert(hash, d); + p = lh_ERR_STRING_DATA_insert(hash, d); CRYPTO_w_unlock(CRYPTO_LOCK_ERR); return p; @@ -390,7 +418,7 @@ static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d) static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) { ERR_STRING_DATA *p; - LHASH *hash; + LHASH_OF(ERR_STRING_DATA) *hash; err_fns_check(); hash = ERRFN(err_get)(0); @@ -398,33 +426,71 @@ static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d) return NULL; CRYPTO_w_lock(CRYPTO_LOCK_ERR); - p = (ERR_STRING_DATA *)lh_delete(hash, d); + p = lh_ERR_STRING_DATA_delete(hash, d); CRYPTO_w_unlock(CRYPTO_LOCK_ERR); return p; } -static LHASH *int_thread_get(int create) +static unsigned long err_state_hash(const ERR_STATE *a) + { + return CRYPTO_THREADID_hash(&a->tid) * 13; + } +static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE) + +static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b) + { + return CRYPTO_THREADID_cmp(&a->tid, &b->tid); + } +static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE) + +static LHASH_OF(ERR_STATE) *int_thread_get(int create) { - LHASH *ret = NULL; + LHASH_OF(ERR_STATE) *ret = NULL; CRYPTO_w_lock(CRYPTO_LOCK_ERR); if (!int_thread_hash && create) { CRYPTO_push_info("int_thread_get (err.c)"); - int_thread_hash = lh_new(pid_hash, pid_cmp); + int_thread_hash = lh_ERR_STATE_new(); CRYPTO_pop_info(); } if (int_thread_hash) + { + int_thread_hash_references++; ret = int_thread_hash; + } CRYPTO_w_unlock(CRYPTO_LOCK_ERR); return ret; } +static void int_thread_release(LHASH_OF(ERR_STATE) **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; + } + static ERR_STATE *int_thread_get_item(const ERR_STATE *d) { ERR_STATE *p; - LHASH *hash; + LHASH_OF(ERR_STATE) *hash; err_fns_check(); hash = ERRFN(thread_get)(0); @@ -432,16 +498,17 @@ static ERR_STATE *int_thread_get_item(const ERR_STATE *d) return NULL; CRYPTO_r_lock(CRYPTO_LOCK_ERR); - p = (ERR_STATE *)lh_retrieve(hash, d); + p = lh_ERR_STATE_retrieve(hash, d); CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + ERRFN(thread_release)(&hash); return p; } static ERR_STATE *int_thread_set_item(ERR_STATE *d) { ERR_STATE *p; - LHASH *hash; + LHASH_OF(ERR_STATE) *hash; err_fns_check(); hash = ERRFN(thread_get)(1); @@ -449,16 +516,17 @@ static ERR_STATE *int_thread_set_item(ERR_STATE *d) return NULL; CRYPTO_w_lock(CRYPTO_LOCK_ERR); - p = (ERR_STATE *)lh_insert(hash, d); + p = lh_ERR_STATE_insert(hash, d); CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + ERRFN(thread_release)(&hash); return p; } static void int_thread_del_item(const ERR_STATE *d) { ERR_STATE *p; - LHASH *hash; + LHASH_OF(ERR_STATE) *hash; err_fns_check(); hash = ERRFN(thread_get)(0); @@ -466,15 +534,17 @@ static void int_thread_del_item(const ERR_STATE *d) return; CRYPTO_w_lock(CRYPTO_LOCK_ERR); - p = (ERR_STATE *)lh_delete(hash, d); + p = lh_ERR_STATE_delete(hash, d); /* make sure we don't leak memory */ - if (int_thread_hash && (lh_num_items(int_thread_hash) == 0)) + if (int_thread_hash_references == 1 + && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0) { - lh_free(int_thread_hash); + lh_ERR_STATE_free(int_thread_hash); int_thread_hash = NULL; } CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + ERRFN(thread_release)(&hash); if (p) ERR_STATE_free(p); } @@ -491,6 +561,7 @@ static int int_err_get_next_lib(void) } +#ifndef OPENSSL_NO_ERR #define NUM_SYS_STR_REASONS 127 #define LEN_SYS_STR_REASON 32 @@ -504,16 +575,27 @@ static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1]; * will be returned for SYSerr(), which always gets an errno * value and never one of those 'standard' reason codes. */ -static void build_SYS_str_reasons() +static void build_SYS_str_reasons(void) { /* OPENSSL_malloc cannot be used here, use static storage instead */ static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON]; int i; static int init = 1; - if (!init) return; - + CRYPTO_r_lock(CRYPTO_LOCK_ERR); + if (!init) + { + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); + return; + } + + CRYPTO_r_unlock(CRYPTO_LOCK_ERR); CRYPTO_w_lock(CRYPTO_LOCK_ERR); + if (!init) + { + CRYPTO_w_unlock(CRYPTO_LOCK_ERR); + return; + } for (i = 1; i <= NUM_SYS_STR_REASONS; i++) { @@ -545,13 +627,24 @@ static void build_SYS_str_reasons() #endif #define err_clear_data(p,i) \ + do { \ if (((p)->err_data[i] != NULL) && \ (p)->err_data_flags[i] & ERR_TXT_MALLOCED) \ { \ OPENSSL_free((p)->err_data[i]); \ (p)->err_data[i]=NULL; \ } \ - (p)->err_data_flags[i]=0; + (p)->err_data_flags[i]=0; \ + } while(0) + +#define err_clear(p,i) \ + do { \ + (p)->err_flags[i]=0; \ + (p)->err_buffer[i]=0; \ + err_clear_data(p,i); \ + (p)->err_file[i]=NULL; \ + (p)->err_line[i]= -1; \ + } while(0) static void ERR_STATE_free(ERR_STATE *s) { @@ -583,7 +676,8 @@ static void err_load_strings(int lib, ERR_STRING_DATA *str) { while (str->error) { - str->error|=ERR_PACK(lib,0,0); + if (lib) + str->error|=ERR_PACK(lib,0,0); ERRFN(err_set_item)(str); str++; } @@ -599,7 +693,8 @@ void ERR_unload_strings(int lib, ERR_STRING_DATA *str) { while (str->error) { - str->error|=ERR_PACK(lib,0,0); + if (lib) + str->error|=ERR_PACK(lib,0,0); ERRFN(err_del_item)(str); str++; } @@ -642,6 +737,7 @@ void ERR_put_error(int lib, int func, int reason, const char *file, es->top=(es->top+1)%ERR_NUM_ERRORS; if (es->top == es->bottom) es->bottom=(es->bottom+1)%ERR_NUM_ERRORS; + es->err_flags[es->top]=0; es->err_buffer[es->top]=ERR_PACK(lib,func,reason); es->err_file[es->top]=file; es->err_line[es->top]=line; @@ -657,10 +753,7 @@ void ERR_clear_error(void) for (i=0; ierr_buffer[i]=0; - err_clear_data(es,i); - es->err_file[i]=NULL; - es->err_line[i]= -1; + err_clear(es,i); } es->top=es->bottom=0; } @@ -831,18 +924,24 @@ char *ERR_error_string(unsigned long e, char *ret) return ret; } -LHASH *ERR_get_string_table(void) +LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void) { err_fns_check(); return ERRFN(err_get)(0); } -LHASH *ERR_get_err_state_table(void) +LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void) { err_fns_check(); return ERRFN(thread_get)(0); } +void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash) + { + err_fns_check(); + ERRFN(thread_release)(hash); + } + const char *ERR_lib_error_string(unsigned long e) { ERR_STRING_DATA d,*p; @@ -886,59 +985,37 @@ const char *ERR_reason_error_string(unsigned long e) return((p == NULL)?NULL:p->string); } -/* static unsigned long err_hash(ERR_STRING_DATA *a) */ -static unsigned long err_hash(const void *a_void) - { - unsigned long ret,l; - - l=((ERR_STRING_DATA *)a_void)->error; - ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l); - return(ret^ret%19*13); - } - -/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */ -static int err_cmp(const void *a_void, const void *b_void) - { - return((int)(((ERR_STRING_DATA *)a_void)->error - - ((ERR_STRING_DATA *)b_void)->error)); - } - -/* static unsigned long pid_hash(ERR_STATE *a) */ -static unsigned long pid_hash(const void *a_void) - { - return(((ERR_STATE *)a_void)->pid*13); - } - -/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */ -static int pid_cmp(const void *a_void, const void *b_void) - { - return((int)((long)((ERR_STATE *)a_void)->pid - - (long)((ERR_STATE *)b_void)->pid)); - } - -void ERR_remove_state(unsigned long pid) +void ERR_remove_thread_state(const CRYPTO_THREADID *id) { ERR_STATE tmp; + if (id) + CRYPTO_THREADID_cpy(&tmp.tid, id); + else + CRYPTO_THREADID_current(&tmp.tid); err_fns_check(); - if (pid == 0) - pid=(unsigned long)CRYPTO_thread_id(); - tmp.pid=pid; /* thread_del_item automatically destroys the LHASH if the number of * items reaches zero. */ ERRFN(thread_del_item)(&tmp); } +#ifndef OPENSSL_NO_DEPRECATED +void ERR_remove_state(unsigned long pid) + { + ERR_remove_thread_state(NULL); + } +#endif + ERR_STATE *ERR_get_state(void) { static ERR_STATE fallback; ERR_STATE *ret,tmp,*tmpp=NULL; int i; - unsigned long pid; + CRYPTO_THREADID tid; err_fns_check(); - pid=(unsigned long)CRYPTO_thread_id(); - tmp.pid=pid; + CRYPTO_THREADID_current(&tid); + CRYPTO_THREADID_cpy(&tmp.tid, &tid); ret=ERRFN(thread_get_item)(&tmp); /* ret == the error state, if NULL, make a new one */ @@ -946,7 +1023,7 @@ ERR_STATE *ERR_get_state(void) { ret=(ERR_STATE *)OPENSSL_malloc(sizeof(ERR_STATE)); if (ret == NULL) return(&fallback); - ret->pid=pid; + CRYPTO_THREADID_cpy(&ret->tid, &tid); ret->top=0; ret->bottom=0; for (i=0; ibottom == 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; + if (es->top == -1) es->top=ERR_NUM_ERRORS-1; + } + + if (es->bottom == es->top) return 0; + es->err_flags[es->top]&=~ERR_FLAG_MARK; + return 1; }