[331] | 1 | /*
|
---|
| 2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
| 5 | * this file except in compliance with the License. You can obtain a copy
|
---|
| 6 | * in the file LICENSE in the source distribution or at
|
---|
| 7 | * https://www.openssl.org/source/license.html
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 | #include <stdio.h>
|
---|
| 11 | #include <stdarg.h>
|
---|
| 12 | #include <string.h>
|
---|
| 13 | #include <internal/cryptlib_int.h>
|
---|
| 14 | #include <internal/err.h>
|
---|
| 15 | #include <internal/err_int.h>
|
---|
| 16 | #include <openssl/lhash.h>
|
---|
| 17 | #include <openssl/crypto.h>
|
---|
| 18 | #include <openssl/buffer.h>
|
---|
| 19 | #include <openssl/bio.h>
|
---|
| 20 | #include <openssl/opensslconf.h>
|
---|
| 21 | #include <internal/thread_once.h>
|
---|
| 22 |
|
---|
| 23 | static void err_load_strings(int lib, ERR_STRING_DATA *str);
|
---|
| 24 |
|
---|
| 25 | static void ERR_STATE_free(ERR_STATE *s);
|
---|
| 26 | #ifndef OPENSSL_NO_ERR
|
---|
| 27 | static ERR_STRING_DATA ERR_str_libraries[] = {
|
---|
| 28 | {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"},
|
---|
| 29 | {ERR_PACK(ERR_LIB_SYS, 0, 0), "system library"},
|
---|
| 30 | {ERR_PACK(ERR_LIB_BN, 0, 0), "bignum routines"},
|
---|
| 31 | {ERR_PACK(ERR_LIB_RSA, 0, 0), "rsa routines"},
|
---|
| 32 | {ERR_PACK(ERR_LIB_DH, 0, 0), "Diffie-Hellman routines"},
|
---|
| 33 | {ERR_PACK(ERR_LIB_EVP, 0, 0), "digital envelope routines"},
|
---|
| 34 | {ERR_PACK(ERR_LIB_BUF, 0, 0), "memory buffer routines"},
|
---|
| 35 | {ERR_PACK(ERR_LIB_OBJ, 0, 0), "object identifier routines"},
|
---|
| 36 | {ERR_PACK(ERR_LIB_PEM, 0, 0), "PEM routines"},
|
---|
| 37 | {ERR_PACK(ERR_LIB_DSA, 0, 0), "dsa routines"},
|
---|
| 38 | {ERR_PACK(ERR_LIB_X509, 0, 0), "x509 certificate routines"},
|
---|
| 39 | {ERR_PACK(ERR_LIB_ASN1, 0, 0), "asn1 encoding routines"},
|
---|
| 40 | {ERR_PACK(ERR_LIB_CONF, 0, 0), "configuration file routines"},
|
---|
| 41 | {ERR_PACK(ERR_LIB_CRYPTO, 0, 0), "common libcrypto routines"},
|
---|
| 42 | {ERR_PACK(ERR_LIB_EC, 0, 0), "elliptic curve routines"},
|
---|
| 43 | {ERR_PACK(ERR_LIB_ECDSA, 0, 0), "ECDSA routines"},
|
---|
| 44 | {ERR_PACK(ERR_LIB_ECDH, 0, 0), "ECDH routines"},
|
---|
| 45 | {ERR_PACK(ERR_LIB_SSL, 0, 0), "SSL routines"},
|
---|
| 46 | {ERR_PACK(ERR_LIB_BIO, 0, 0), "BIO routines"},
|
---|
| 47 | {ERR_PACK(ERR_LIB_PKCS7, 0, 0), "PKCS7 routines"},
|
---|
| 48 | {ERR_PACK(ERR_LIB_X509V3, 0, 0), "X509 V3 routines"},
|
---|
| 49 | {ERR_PACK(ERR_LIB_PKCS12, 0, 0), "PKCS12 routines"},
|
---|
| 50 | {ERR_PACK(ERR_LIB_RAND, 0, 0), "random number generator"},
|
---|
| 51 | {ERR_PACK(ERR_LIB_DSO, 0, 0), "DSO support routines"},
|
---|
| 52 | {ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"},
|
---|
| 53 | {ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"},
|
---|
| 54 | {ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"},
|
---|
| 55 | {ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"},
|
---|
| 56 | {ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
|
---|
| 57 | {ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
|
---|
| 58 | {ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
|
---|
| 59 | {ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
|
---|
| 60 | {ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
|
---|
| 61 | {ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
|
---|
| 62 | {0, NULL},
|
---|
| 63 | };
|
---|
| 64 |
|
---|
| 65 | static ERR_STRING_DATA ERR_str_functs[] = {
|
---|
| 66 | {ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"},
|
---|
| 67 | {ERR_PACK(0, SYS_F_CONNECT, 0), "connect"},
|
---|
| 68 | {ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"},
|
---|
| 69 | {ERR_PACK(0, SYS_F_SOCKET, 0), "socket"},
|
---|
| 70 | {ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"},
|
---|
| 71 | {ERR_PACK(0, SYS_F_BIND, 0), "bind"},
|
---|
| 72 | {ERR_PACK(0, SYS_F_LISTEN, 0), "listen"},
|
---|
| 73 | {ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"},
|
---|
| 74 | # ifdef OPENSSL_SYS_WINDOWS
|
---|
| 75 | {ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"},
|
---|
| 76 | # endif
|
---|
| 77 | {ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"},
|
---|
| 78 | {ERR_PACK(0, SYS_F_FREAD, 0), "fread"},
|
---|
| 79 | {ERR_PACK(0, SYS_F_GETADDRINFO, 0), "getaddrinfo"},
|
---|
| 80 | {ERR_PACK(0, SYS_F_GETNAMEINFO, 0), "getnameinfo"},
|
---|
| 81 | {ERR_PACK(0, SYS_F_SETSOCKOPT, 0), "setsockopt"},
|
---|
| 82 | {ERR_PACK(0, SYS_F_GETSOCKOPT, 0), "getsockopt"},
|
---|
| 83 | {ERR_PACK(0, SYS_F_GETSOCKNAME, 0), "getsockname"},
|
---|
| 84 | {ERR_PACK(0, SYS_F_GETHOSTBYNAME, 0), "gethostbyname"},
|
---|
| 85 | {0, NULL},
|
---|
| 86 | };
|
---|
| 87 |
|
---|
| 88 | static ERR_STRING_DATA ERR_str_reasons[] = {
|
---|
| 89 | {ERR_R_SYS_LIB, "system lib"},
|
---|
| 90 | {ERR_R_BN_LIB, "BN lib"},
|
---|
| 91 | {ERR_R_RSA_LIB, "RSA lib"},
|
---|
| 92 | {ERR_R_DH_LIB, "DH lib"},
|
---|
| 93 | {ERR_R_EVP_LIB, "EVP lib"},
|
---|
| 94 | {ERR_R_BUF_LIB, "BUF lib"},
|
---|
| 95 | {ERR_R_OBJ_LIB, "OBJ lib"},
|
---|
| 96 | {ERR_R_PEM_LIB, "PEM lib"},
|
---|
| 97 | {ERR_R_DSA_LIB, "DSA lib"},
|
---|
| 98 | {ERR_R_X509_LIB, "X509 lib"},
|
---|
| 99 | {ERR_R_ASN1_LIB, "ASN1 lib"},
|
---|
| 100 | {ERR_R_EC_LIB, "EC lib"},
|
---|
| 101 | {ERR_R_BIO_LIB, "BIO lib"},
|
---|
| 102 | {ERR_R_PKCS7_LIB, "PKCS7 lib"},
|
---|
| 103 | {ERR_R_X509V3_LIB, "X509V3 lib"},
|
---|
| 104 | {ERR_R_ENGINE_LIB, "ENGINE lib"},
|
---|
| 105 | {ERR_R_ECDSA_LIB, "ECDSA lib"},
|
---|
| 106 |
|
---|
| 107 | {ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
|
---|
| 108 | {ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},
|
---|
| 109 |
|
---|
| 110 | {ERR_R_FATAL, "fatal"},
|
---|
| 111 | {ERR_R_MALLOC_FAILURE, "malloc failure"},
|
---|
| 112 | {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
|
---|
| 113 | "called a function you should not call"},
|
---|
| 114 | {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
|
---|
| 115 | {ERR_R_INTERNAL_ERROR, "internal error"},
|
---|
| 116 | {ERR_R_DISABLED, "called a function that was disabled at compile-time"},
|
---|
| 117 | {ERR_R_INIT_FAIL, "init fail"},
|
---|
| 118 |
|
---|
| 119 | {0, NULL},
|
---|
| 120 | };
|
---|
| 121 | #endif
|
---|
| 122 |
|
---|
| 123 | static CRYPTO_ONCE err_init = CRYPTO_ONCE_STATIC_INIT;
|
---|
| 124 | static CRYPTO_THREAD_LOCAL err_thread_local;
|
---|
| 125 |
|
---|
| 126 | static CRYPTO_ONCE err_string_init = CRYPTO_ONCE_STATIC_INIT;
|
---|
| 127 | static CRYPTO_RWLOCK *err_string_lock;
|
---|
| 128 |
|
---|
| 129 | static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
|
---|
| 130 |
|
---|
| 131 | /*
|
---|
| 132 | * The internal state
|
---|
| 133 | */
|
---|
| 134 |
|
---|
| 135 | static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
|
---|
| 136 | static int int_err_library_number = ERR_LIB_USER;
|
---|
| 137 |
|
---|
| 138 | static unsigned long get_error_values(int inc, int top, const char **file,
|
---|
| 139 | int *line, const char **data,
|
---|
| 140 | int *flags);
|
---|
| 141 |
|
---|
| 142 | static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
|
---|
| 143 | {
|
---|
| 144 | unsigned long ret, l;
|
---|
| 145 |
|
---|
| 146 | l = a->error;
|
---|
| 147 | ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l);
|
---|
| 148 | return (ret ^ ret % 19 * 13);
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | static int err_string_data_cmp(const ERR_STRING_DATA *a,
|
---|
| 152 | const ERR_STRING_DATA *b)
|
---|
| 153 | {
|
---|
| 154 | return (int)(a->error - b->error);
|
---|
| 155 | }
|
---|
| 156 |
|
---|
| 157 | static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
|
---|
| 158 | {
|
---|
| 159 | ERR_STRING_DATA *p = NULL;
|
---|
| 160 |
|
---|
| 161 | CRYPTO_THREAD_read_lock(err_string_lock);
|
---|
| 162 | if (int_error_hash != NULL)
|
---|
| 163 | p = lh_ERR_STRING_DATA_retrieve(int_error_hash, d);
|
---|
| 164 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 165 |
|
---|
| 166 | return p;
|
---|
| 167 | }
|
---|
| 168 |
|
---|
| 169 | #ifndef OPENSSL_NO_ERR
|
---|
| 170 | # define NUM_SYS_STR_REASONS 127
|
---|
| 171 | # define LEN_SYS_STR_REASON 32
|
---|
| 172 |
|
---|
| 173 | static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
|
---|
| 174 | /*
|
---|
| 175 | * SYS_str_reasons is filled with copies of strerror() results at
|
---|
| 176 | * initialization. 'errno' values up to 127 should cover all usual errors,
|
---|
| 177 | * others will be displayed numerically by ERR_error_string. It is crucial
|
---|
| 178 | * that we have something for each reason code that occurs in
|
---|
| 179 | * ERR_str_reasons, or bogus reason strings will be returned for SYSerr(),
|
---|
| 180 | * which always gets an errno value and never one of those 'standard' reason
|
---|
| 181 | * codes.
|
---|
| 182 | */
|
---|
| 183 |
|
---|
| 184 | static void build_SYS_str_reasons(void)
|
---|
| 185 | {
|
---|
| 186 | /* OPENSSL_malloc cannot be used here, use static storage instead */
|
---|
| 187 | static char strerror_tab[NUM_SYS_STR_REASONS][LEN_SYS_STR_REASON];
|
---|
| 188 | static int init = 1;
|
---|
| 189 | int i;
|
---|
| 190 |
|
---|
| 191 | CRYPTO_THREAD_write_lock(err_string_lock);
|
---|
| 192 | if (!init) {
|
---|
| 193 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 194 | return;
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
|
---|
| 198 | ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
|
---|
| 199 |
|
---|
| 200 | str->error = (unsigned long)i;
|
---|
| 201 | if (str->string == NULL) {
|
---|
| 202 | char (*dest)[LEN_SYS_STR_REASON] = &(strerror_tab[i - 1]);
|
---|
| 203 | if (openssl_strerror_r(i, *dest, sizeof(*dest)))
|
---|
| 204 | str->string = *dest;
|
---|
| 205 | }
|
---|
| 206 | if (str->string == NULL)
|
---|
| 207 | str->string = "unknown";
|
---|
| 208 | }
|
---|
| 209 |
|
---|
| 210 | /*
|
---|
| 211 | * Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as
|
---|
| 212 | * required by ERR_load_strings.
|
---|
| 213 | */
|
---|
| 214 |
|
---|
| 215 | init = 0;
|
---|
| 216 |
|
---|
| 217 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 218 | }
|
---|
| 219 | #endif
|
---|
| 220 |
|
---|
| 221 | #define err_clear_data(p,i) \
|
---|
| 222 | do { \
|
---|
| 223 | if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) \
|
---|
| 224 | { \
|
---|
| 225 | OPENSSL_free((p)->err_data[i]); \
|
---|
| 226 | (p)->err_data[i]=NULL; \
|
---|
| 227 | } \
|
---|
| 228 | (p)->err_data_flags[i]=0; \
|
---|
| 229 | } while(0)
|
---|
| 230 |
|
---|
| 231 | #define err_clear(p,i) \
|
---|
| 232 | do { \
|
---|
| 233 | (p)->err_flags[i]=0; \
|
---|
| 234 | (p)->err_buffer[i]=0; \
|
---|
| 235 | err_clear_data(p,i); \
|
---|
| 236 | (p)->err_file[i]=NULL; \
|
---|
| 237 | (p)->err_line[i]= -1; \
|
---|
| 238 | } while(0)
|
---|
| 239 |
|
---|
| 240 | static void ERR_STATE_free(ERR_STATE *s)
|
---|
| 241 | {
|
---|
| 242 | int i;
|
---|
| 243 |
|
---|
| 244 | if (s == NULL)
|
---|
| 245 | return;
|
---|
| 246 |
|
---|
| 247 | for (i = 0; i < ERR_NUM_ERRORS; i++) {
|
---|
| 248 | err_clear_data(s, i);
|
---|
| 249 | }
|
---|
| 250 | OPENSSL_free(s);
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 | DEFINE_RUN_ONCE_STATIC(do_err_strings_init)
|
---|
| 254 | {
|
---|
| 255 | OPENSSL_init_crypto(0, NULL);
|
---|
| 256 | err_string_lock = CRYPTO_THREAD_lock_new();
|
---|
| 257 | return err_string_lock != NULL;
|
---|
| 258 | }
|
---|
| 259 |
|
---|
| 260 | void err_cleanup(void)
|
---|
| 261 | {
|
---|
| 262 | CRYPTO_THREAD_lock_free(err_string_lock);
|
---|
| 263 | err_string_lock = NULL;
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | int ERR_load_ERR_strings(void)
|
---|
| 267 | {
|
---|
| 268 | #ifndef OPENSSL_NO_ERR
|
---|
| 269 | if (!RUN_ONCE(&err_string_init, do_err_strings_init))
|
---|
| 270 | return 0;
|
---|
| 271 |
|
---|
| 272 | err_load_strings(0, ERR_str_libraries);
|
---|
| 273 | err_load_strings(0, ERR_str_reasons);
|
---|
| 274 | err_load_strings(ERR_LIB_SYS, ERR_str_functs);
|
---|
| 275 | build_SYS_str_reasons();
|
---|
| 276 | err_load_strings(ERR_LIB_SYS, SYS_str_reasons);
|
---|
| 277 | #endif
|
---|
| 278 | return 1;
|
---|
| 279 | }
|
---|
| 280 |
|
---|
| 281 | static void err_load_strings(int lib, ERR_STRING_DATA *str)
|
---|
| 282 | {
|
---|
| 283 | CRYPTO_THREAD_write_lock(err_string_lock);
|
---|
| 284 | if (int_error_hash == NULL)
|
---|
| 285 | int_error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash,
|
---|
| 286 | err_string_data_cmp);
|
---|
| 287 | if (int_error_hash != NULL) {
|
---|
| 288 | for (; str->error; str++) {
|
---|
| 289 | if (lib)
|
---|
| 290 | str->error |= ERR_PACK(lib, 0, 0);
|
---|
| 291 | (void)lh_ERR_STRING_DATA_insert(int_error_hash, str);
|
---|
| 292 | }
|
---|
| 293 | }
|
---|
| 294 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 295 | }
|
---|
| 296 |
|
---|
| 297 | int ERR_load_strings(int lib, ERR_STRING_DATA *str)
|
---|
| 298 | {
|
---|
| 299 | if (ERR_load_ERR_strings() == 0)
|
---|
| 300 | return 0;
|
---|
| 301 | err_load_strings(lib, str);
|
---|
| 302 | return 1;
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 | int ERR_unload_strings(int lib, ERR_STRING_DATA *str)
|
---|
| 306 | {
|
---|
| 307 | if (!RUN_ONCE(&err_string_init, do_err_strings_init))
|
---|
| 308 | return 0;
|
---|
| 309 |
|
---|
| 310 | CRYPTO_THREAD_write_lock(err_string_lock);
|
---|
| 311 | if (int_error_hash != NULL) {
|
---|
| 312 | for (; str->error; str++) {
|
---|
| 313 | if (lib)
|
---|
| 314 | str->error |= ERR_PACK(lib, 0, 0);
|
---|
| 315 | (void)lh_ERR_STRING_DATA_delete(int_error_hash, str);
|
---|
| 316 | }
|
---|
| 317 | }
|
---|
| 318 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 319 |
|
---|
| 320 | return 1;
|
---|
| 321 | }
|
---|
| 322 |
|
---|
| 323 | void err_free_strings_int(void)
|
---|
| 324 | {
|
---|
| 325 | if (!RUN_ONCE(&err_string_init, do_err_strings_init))
|
---|
| 326 | return;
|
---|
| 327 |
|
---|
| 328 | CRYPTO_THREAD_write_lock(err_string_lock);
|
---|
| 329 | lh_ERR_STRING_DATA_free(int_error_hash);
|
---|
| 330 | int_error_hash = NULL;
|
---|
| 331 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 332 | }
|
---|
| 333 |
|
---|
| 334 | /********************************************************/
|
---|
| 335 |
|
---|
| 336 | void ERR_put_error(int lib, int func, int reason, const char *file, int line)
|
---|
| 337 | {
|
---|
| 338 | ERR_STATE *es;
|
---|
| 339 |
|
---|
| 340 | #ifdef _OSD_POSIX
|
---|
| 341 | /*
|
---|
| 342 | * In the BS2000-OSD POSIX subsystem, the compiler generates path names
|
---|
| 343 | * in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
|
---|
| 344 | * something sensible. @@@ We shouldn't modify a const string, though.
|
---|
| 345 | */
|
---|
| 346 | if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
|
---|
| 347 | char *end;
|
---|
| 348 |
|
---|
| 349 | /* Skip the "*POSIX(" prefix */
|
---|
| 350 | file += sizeof("*POSIX(") - 1;
|
---|
| 351 | end = &file[strlen(file) - 1];
|
---|
| 352 | if (*end == ')')
|
---|
| 353 | *end = '\0';
|
---|
| 354 | /* Optional: use the basename of the path only. */
|
---|
| 355 | if ((end = strrchr(file, '/')) != NULL)
|
---|
| 356 | file = &end[1];
|
---|
| 357 | }
|
---|
| 358 | #endif
|
---|
| 359 | es = ERR_get_state();
|
---|
| 360 |
|
---|
| 361 | es->top = (es->top + 1) % ERR_NUM_ERRORS;
|
---|
| 362 | if (es->top == es->bottom)
|
---|
| 363 | es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
|
---|
| 364 | es->err_flags[es->top] = 0;
|
---|
| 365 | es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
|
---|
| 366 | es->err_file[es->top] = file;
|
---|
| 367 | es->err_line[es->top] = line;
|
---|
| 368 | err_clear_data(es, es->top);
|
---|
| 369 | }
|
---|
| 370 |
|
---|
| 371 | void ERR_clear_error(void)
|
---|
| 372 | {
|
---|
| 373 | int i;
|
---|
| 374 | ERR_STATE *es;
|
---|
| 375 |
|
---|
| 376 | es = ERR_get_state();
|
---|
| 377 |
|
---|
| 378 | for (i = 0; i < ERR_NUM_ERRORS; i++) {
|
---|
| 379 | err_clear(es, i);
|
---|
| 380 | }
|
---|
| 381 | es->top = es->bottom = 0;
|
---|
| 382 | }
|
---|
| 383 |
|
---|
| 384 | unsigned long ERR_get_error(void)
|
---|
| 385 | {
|
---|
| 386 | return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | unsigned long ERR_get_error_line(const char **file, int *line)
|
---|
| 390 | {
|
---|
| 391 | return (get_error_values(1, 0, file, line, NULL, NULL));
|
---|
| 392 | }
|
---|
| 393 |
|
---|
| 394 | unsigned long ERR_get_error_line_data(const char **file, int *line,
|
---|
| 395 | const char **data, int *flags)
|
---|
| 396 | {
|
---|
| 397 | return (get_error_values(1, 0, file, line, data, flags));
|
---|
| 398 | }
|
---|
| 399 |
|
---|
| 400 | unsigned long ERR_peek_error(void)
|
---|
| 401 | {
|
---|
| 402 | return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
|
---|
| 403 | }
|
---|
| 404 |
|
---|
| 405 | unsigned long ERR_peek_error_line(const char **file, int *line)
|
---|
| 406 | {
|
---|
| 407 | return (get_error_values(0, 0, file, line, NULL, NULL));
|
---|
| 408 | }
|
---|
| 409 |
|
---|
| 410 | unsigned long ERR_peek_error_line_data(const char **file, int *line,
|
---|
| 411 | const char **data, int *flags)
|
---|
| 412 | {
|
---|
| 413 | return (get_error_values(0, 0, file, line, data, flags));
|
---|
| 414 | }
|
---|
| 415 |
|
---|
| 416 | unsigned long ERR_peek_last_error(void)
|
---|
| 417 | {
|
---|
| 418 | return (get_error_values(0, 1, NULL, NULL, NULL, NULL));
|
---|
| 419 | }
|
---|
| 420 |
|
---|
| 421 | unsigned long ERR_peek_last_error_line(const char **file, int *line)
|
---|
| 422 | {
|
---|
| 423 | return (get_error_values(0, 1, file, line, NULL, NULL));
|
---|
| 424 | }
|
---|
| 425 |
|
---|
| 426 | unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
|
---|
| 427 | const char **data, int *flags)
|
---|
| 428 | {
|
---|
| 429 | return (get_error_values(0, 1, file, line, data, flags));
|
---|
| 430 | }
|
---|
| 431 |
|
---|
| 432 | static unsigned long get_error_values(int inc, int top, const char **file,
|
---|
| 433 | int *line, const char **data,
|
---|
| 434 | int *flags)
|
---|
| 435 | {
|
---|
| 436 | int i = 0;
|
---|
| 437 | ERR_STATE *es;
|
---|
| 438 | unsigned long ret;
|
---|
| 439 |
|
---|
| 440 | es = ERR_get_state();
|
---|
| 441 |
|
---|
| 442 | if (inc && top) {
|
---|
| 443 | if (file)
|
---|
| 444 | *file = "";
|
---|
| 445 | if (line)
|
---|
| 446 | *line = 0;
|
---|
| 447 | if (data)
|
---|
| 448 | *data = "";
|
---|
| 449 | if (flags)
|
---|
| 450 | *flags = 0;
|
---|
| 451 |
|
---|
| 452 | return ERR_R_INTERNAL_ERROR;
|
---|
| 453 | }
|
---|
| 454 |
|
---|
| 455 | if (es->bottom == es->top)
|
---|
| 456 | return 0;
|
---|
| 457 | if (top)
|
---|
| 458 | i = es->top; /* last error */
|
---|
| 459 | else
|
---|
| 460 | i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
|
---|
| 461 |
|
---|
| 462 | ret = es->err_buffer[i];
|
---|
| 463 | if (inc) {
|
---|
| 464 | es->bottom = i;
|
---|
| 465 | es->err_buffer[i] = 0;
|
---|
| 466 | }
|
---|
| 467 |
|
---|
| 468 | if ((file != NULL) && (line != NULL)) {
|
---|
| 469 | if (es->err_file[i] == NULL) {
|
---|
| 470 | *file = "NA";
|
---|
| 471 | if (line != NULL)
|
---|
| 472 | *line = 0;
|
---|
| 473 | } else {
|
---|
| 474 | *file = es->err_file[i];
|
---|
| 475 | if (line != NULL)
|
---|
| 476 | *line = es->err_line[i];
|
---|
| 477 | }
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | if (data == NULL) {
|
---|
| 481 | if (inc) {
|
---|
| 482 | err_clear_data(es, i);
|
---|
| 483 | }
|
---|
| 484 | } else {
|
---|
| 485 | if (es->err_data[i] == NULL) {
|
---|
| 486 | *data = "";
|
---|
| 487 | if (flags != NULL)
|
---|
| 488 | *flags = 0;
|
---|
| 489 | } else {
|
---|
| 490 | *data = es->err_data[i];
|
---|
| 491 | if (flags != NULL)
|
---|
| 492 | *flags = es->err_data_flags[i];
|
---|
| 493 | }
|
---|
| 494 | }
|
---|
| 495 | return ret;
|
---|
| 496 | }
|
---|
| 497 |
|
---|
| 498 | void ERR_error_string_n(unsigned long e, char *buf, size_t len)
|
---|
| 499 | {
|
---|
| 500 | char lsbuf[64], fsbuf[64], rsbuf[64];
|
---|
| 501 | const char *ls, *fs, *rs;
|
---|
| 502 | unsigned long l, f, r;
|
---|
| 503 |
|
---|
| 504 | if (len == 0)
|
---|
| 505 | return;
|
---|
| 506 |
|
---|
| 507 | l = ERR_GET_LIB(e);
|
---|
| 508 | f = ERR_GET_FUNC(e);
|
---|
| 509 | r = ERR_GET_REASON(e);
|
---|
| 510 |
|
---|
| 511 | ls = ERR_lib_error_string(e);
|
---|
| 512 | fs = ERR_func_error_string(e);
|
---|
| 513 | rs = ERR_reason_error_string(e);
|
---|
| 514 |
|
---|
| 515 | if (ls == NULL)
|
---|
| 516 | BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
|
---|
| 517 | if (fs == NULL)
|
---|
| 518 | BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
|
---|
| 519 | if (rs == NULL)
|
---|
| 520 | BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
|
---|
| 521 |
|
---|
| 522 | BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls ? ls : lsbuf,
|
---|
| 523 | fs ? fs : fsbuf, rs ? rs : rsbuf);
|
---|
| 524 | if (strlen(buf) == len - 1) {
|
---|
| 525 | /*
|
---|
| 526 | * output may be truncated; make sure we always have 5
|
---|
| 527 | * colon-separated fields, i.e. 4 colons ...
|
---|
| 528 | */
|
---|
| 529 | #define NUM_COLONS 4
|
---|
| 530 | if (len > NUM_COLONS) { /* ... if possible */
|
---|
| 531 | int i;
|
---|
| 532 | char *s = buf;
|
---|
| 533 |
|
---|
| 534 | for (i = 0; i < NUM_COLONS; i++) {
|
---|
| 535 | char *colon = strchr(s, ':');
|
---|
| 536 | if (colon == NULL || colon > &buf[len - 1] - NUM_COLONS + i) {
|
---|
| 537 | /*
|
---|
| 538 | * set colon no. i at last possible position (buf[len-1]
|
---|
| 539 | * is the terminating 0)
|
---|
| 540 | */
|
---|
| 541 | colon = &buf[len - 1] - NUM_COLONS + i;
|
---|
| 542 | *colon = ':';
|
---|
| 543 | }
|
---|
| 544 | s = colon + 1;
|
---|
| 545 | }
|
---|
| 546 | }
|
---|
| 547 | }
|
---|
| 548 | }
|
---|
| 549 |
|
---|
| 550 | /*
|
---|
| 551 | * ERR_error_string_n should be used instead for ret != NULL as
|
---|
| 552 | * ERR_error_string cannot know how large the buffer is
|
---|
| 553 | */
|
---|
| 554 | char *ERR_error_string(unsigned long e, char *ret)
|
---|
| 555 | {
|
---|
| 556 | static char buf[256];
|
---|
| 557 |
|
---|
| 558 | if (ret == NULL)
|
---|
| 559 | ret = buf;
|
---|
| 560 | ERR_error_string_n(e, ret, 256);
|
---|
| 561 |
|
---|
| 562 | return ret;
|
---|
| 563 | }
|
---|
| 564 |
|
---|
| 565 | const char *ERR_lib_error_string(unsigned long e)
|
---|
| 566 | {
|
---|
| 567 | ERR_STRING_DATA d, *p;
|
---|
| 568 | unsigned long l;
|
---|
| 569 |
|
---|
| 570 | if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
|
---|
| 571 | return NULL;
|
---|
| 572 | }
|
---|
| 573 |
|
---|
| 574 | l = ERR_GET_LIB(e);
|
---|
| 575 | d.error = ERR_PACK(l, 0, 0);
|
---|
| 576 | p = int_err_get_item(&d);
|
---|
| 577 | return ((p == NULL) ? NULL : p->string);
|
---|
| 578 | }
|
---|
| 579 |
|
---|
| 580 | const char *ERR_func_error_string(unsigned long e)
|
---|
| 581 | {
|
---|
| 582 | ERR_STRING_DATA d, *p;
|
---|
| 583 | unsigned long l, f;
|
---|
| 584 |
|
---|
| 585 | if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
|
---|
| 586 | return NULL;
|
---|
| 587 | }
|
---|
| 588 |
|
---|
| 589 | l = ERR_GET_LIB(e);
|
---|
| 590 | f = ERR_GET_FUNC(e);
|
---|
| 591 | d.error = ERR_PACK(l, f, 0);
|
---|
| 592 | p = int_err_get_item(&d);
|
---|
| 593 | return ((p == NULL) ? NULL : p->string);
|
---|
| 594 | }
|
---|
| 595 |
|
---|
| 596 | const char *ERR_reason_error_string(unsigned long e)
|
---|
| 597 | {
|
---|
| 598 | ERR_STRING_DATA d, *p = NULL;
|
---|
| 599 | unsigned long l, r;
|
---|
| 600 |
|
---|
| 601 | if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
|
---|
| 602 | return NULL;
|
---|
| 603 | }
|
---|
| 604 |
|
---|
| 605 | l = ERR_GET_LIB(e);
|
---|
| 606 | r = ERR_GET_REASON(e);
|
---|
| 607 | d.error = ERR_PACK(l, 0, r);
|
---|
| 608 | p = int_err_get_item(&d);
|
---|
| 609 | if (!p) {
|
---|
| 610 | d.error = ERR_PACK(0, 0, r);
|
---|
| 611 | p = int_err_get_item(&d);
|
---|
| 612 | }
|
---|
| 613 | return ((p == NULL) ? NULL : p->string);
|
---|
| 614 | }
|
---|
| 615 |
|
---|
| 616 | void err_delete_thread_state(void)
|
---|
| 617 | {
|
---|
| 618 | ERR_STATE *state = ERR_get_state();
|
---|
| 619 | if (state == NULL)
|
---|
| 620 | return;
|
---|
| 621 |
|
---|
| 622 | CRYPTO_THREAD_set_local(&err_thread_local, NULL);
|
---|
| 623 | ERR_STATE_free(state);
|
---|
| 624 | }
|
---|
| 625 |
|
---|
| 626 | #if OPENSSL_API_COMPAT < 0x10100000L
|
---|
| 627 | void ERR_remove_thread_state(void *dummy)
|
---|
| 628 | {
|
---|
| 629 | }
|
---|
| 630 | #endif
|
---|
| 631 |
|
---|
| 632 | #if OPENSSL_API_COMPAT < 0x10000000L
|
---|
| 633 | void ERR_remove_state(unsigned long pid)
|
---|
| 634 | {
|
---|
| 635 | }
|
---|
| 636 | #endif
|
---|
| 637 |
|
---|
| 638 | DEFINE_RUN_ONCE_STATIC(err_do_init)
|
---|
| 639 | {
|
---|
| 640 | return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
|
---|
| 641 | }
|
---|
| 642 |
|
---|
| 643 | ERR_STATE *ERR_get_state(void)
|
---|
| 644 | {
|
---|
| 645 | ERR_STATE *state = NULL;
|
---|
| 646 |
|
---|
| 647 | if (!RUN_ONCE(&err_init, err_do_init))
|
---|
| 648 | return NULL;
|
---|
| 649 |
|
---|
| 650 | state = CRYPTO_THREAD_get_local(&err_thread_local);
|
---|
| 651 |
|
---|
| 652 | if (state == NULL) {
|
---|
| 653 | state = OPENSSL_zalloc(sizeof(*state));
|
---|
| 654 | if (state == NULL)
|
---|
| 655 | return NULL;
|
---|
| 656 |
|
---|
| 657 | if (!CRYPTO_THREAD_set_local(&err_thread_local, state)) {
|
---|
| 658 | ERR_STATE_free(state);
|
---|
| 659 | return NULL;
|
---|
| 660 | }
|
---|
| 661 |
|
---|
| 662 | /* Ignore failures from these */
|
---|
| 663 | OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
---|
| 664 | ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE);
|
---|
| 665 | }
|
---|
| 666 |
|
---|
| 667 | return state;
|
---|
| 668 | }
|
---|
| 669 |
|
---|
| 670 | int ERR_get_next_error_library(void)
|
---|
| 671 | {
|
---|
| 672 | int ret;
|
---|
| 673 |
|
---|
| 674 | if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
|
---|
| 675 | return 0;
|
---|
| 676 | }
|
---|
| 677 |
|
---|
| 678 | CRYPTO_THREAD_write_lock(err_string_lock);
|
---|
| 679 | ret = int_err_library_number++;
|
---|
| 680 | CRYPTO_THREAD_unlock(err_string_lock);
|
---|
| 681 | return ret;
|
---|
| 682 | }
|
---|
| 683 |
|
---|
| 684 | void ERR_set_error_data(char *data, int flags)
|
---|
| 685 | {
|
---|
| 686 | ERR_STATE *es;
|
---|
| 687 | int i;
|
---|
| 688 |
|
---|
| 689 | es = ERR_get_state();
|
---|
| 690 |
|
---|
| 691 | i = es->top;
|
---|
| 692 | if (i == 0)
|
---|
| 693 | i = ERR_NUM_ERRORS - 1;
|
---|
| 694 |
|
---|
| 695 | err_clear_data(es, i);
|
---|
| 696 | es->err_data[i] = data;
|
---|
| 697 | es->err_data_flags[i] = flags;
|
---|
| 698 | }
|
---|
| 699 |
|
---|
| 700 | void ERR_add_error_data(int num, ...)
|
---|
| 701 | {
|
---|
| 702 | va_list args;
|
---|
| 703 | va_start(args, num);
|
---|
| 704 | ERR_add_error_vdata(num, args);
|
---|
| 705 | va_end(args);
|
---|
| 706 | }
|
---|
| 707 |
|
---|
| 708 | void ERR_add_error_vdata(int num, va_list args)
|
---|
| 709 | {
|
---|
| 710 | int i, n, s;
|
---|
| 711 | char *str, *p, *a;
|
---|
| 712 |
|
---|
| 713 | s = 80;
|
---|
| 714 | str = OPENSSL_malloc(s + 1);
|
---|
| 715 | if (str == NULL)
|
---|
| 716 | return;
|
---|
| 717 | str[0] = '\0';
|
---|
| 718 |
|
---|
| 719 | n = 0;
|
---|
| 720 | for (i = 0; i < num; i++) {
|
---|
| 721 | a = va_arg(args, char *);
|
---|
| 722 | /* ignore NULLs, thanks to Bob Beck <beck@obtuse.com> */
|
---|
| 723 | if (a != NULL) {
|
---|
| 724 | n += strlen(a);
|
---|
| 725 | if (n > s) {
|
---|
| 726 | s = n + 20;
|
---|
| 727 | p = OPENSSL_realloc(str, s + 1);
|
---|
| 728 | if (p == NULL) {
|
---|
| 729 | OPENSSL_free(str);
|
---|
| 730 | return;
|
---|
| 731 | }
|
---|
| 732 | str = p;
|
---|
| 733 | }
|
---|
| 734 | OPENSSL_strlcat(str, a, (size_t)s + 1);
|
---|
| 735 | }
|
---|
| 736 | }
|
---|
| 737 | ERR_set_error_data(str, ERR_TXT_MALLOCED | ERR_TXT_STRING);
|
---|
| 738 | }
|
---|
| 739 |
|
---|
| 740 | int ERR_set_mark(void)
|
---|
| 741 | {
|
---|
| 742 | ERR_STATE *es;
|
---|
| 743 |
|
---|
| 744 | es = ERR_get_state();
|
---|
| 745 |
|
---|
| 746 | if (es->bottom == es->top)
|
---|
| 747 | return 0;
|
---|
| 748 | es->err_flags[es->top] |= ERR_FLAG_MARK;
|
---|
| 749 | return 1;
|
---|
| 750 | }
|
---|
| 751 |
|
---|
| 752 | int ERR_pop_to_mark(void)
|
---|
| 753 | {
|
---|
| 754 | ERR_STATE *es;
|
---|
| 755 |
|
---|
| 756 | es = ERR_get_state();
|
---|
| 757 |
|
---|
| 758 | while (es->bottom != es->top
|
---|
| 759 | && (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
|
---|
| 760 | err_clear(es, es->top);
|
---|
| 761 | es->top -= 1;
|
---|
| 762 | if (es->top == -1)
|
---|
| 763 | es->top = ERR_NUM_ERRORS - 1;
|
---|
| 764 | }
|
---|
| 765 |
|
---|
| 766 | if (es->bottom == es->top)
|
---|
| 767 | return 0;
|
---|
| 768 | es->err_flags[es->top] &= ~ERR_FLAG_MARK;
|
---|
| 769 | return 1;
|
---|
| 770 | }
|
---|