/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* https://www.openssl.org/source/license.html
*/
+/* TODO: When ERR_STATE becomes opaque, this musts be removed */
+#define OSSL_FORCE_ERR_STATE
+
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
-#include "internal/cryptlib_int.h"
+#include "crypto/cryptlib.h"
#include "internal/err.h"
-#include "internal/err_int.h"
+#include "crypto/err.h"
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/opensslconf.h>
#include "internal/thread_once.h"
-#include "internal/ctype.h"
-#include "internal/constant_time_locl.h"
+#include "crypto/ctype.h"
+#include "internal/constant_time.h"
#include "e_os.h"
+#include "err_local.h"
+
+/* Forward declaration in case it's not published because of configuration */
+ERR_STATE *ERR_get_state(void);
static int err_load_strings(const ERR_STRING_DATA *str);
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
{ERR_PACK(ERR_LIB_ESS, 0, 0), "ESS routines"},
{ERR_PACK(ERR_LIB_PROV, 0, 0), "Provider routines"},
+ {ERR_PACK(ERR_LIB_OSSL_SERIALIZER, 0, 0), "SERIALIZER routines"},
+ {ERR_PACK(ERR_LIB_HTTP, 0, 0), "HTTP routines"},
{0, NULL},
};
{ERR_R_DISABLED, "called a function that was disabled at compile-time"},
{ERR_R_INIT_FAIL, "init fail"},
{ERR_R_OPERATION_FAIL, "operation fail"},
+ {ERR_R_INVALID_PROVIDER_FUNCTIONS, "invalid provider functions"},
+ {ERR_R_INTERRUPTED_OR_CANCELLED, "interrupted or cancelled"},
{0, NULL},
};
static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
static int int_err_library_number = ERR_LIB_USER;
-static unsigned long get_error_values(int inc, int top, const char **file,
- int *line, const char **data,
+typedef enum ERR_GET_ACTION_e {
+ EV_POP, EV_PEEK, EV_PEEK_LAST
+} ERR_GET_ACTION;
+
+static unsigned long get_error_values(ERR_GET_ACTION g,
+ const char **file, int *line,
+ const char **func, const char **data,
int *flags);
static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
}
#endif
-#define err_get_slot(p) \
- do { \
- (p)->top = ((p)->top + 1) % ERR_NUM_ERRORS; \
- if ((p)->top == (p)->bottom) \
- (p)->bottom = ((p)->bottom + 1) % ERR_NUM_ERRORS; \
- } while (0)
-
-#define err_clear_data(p, i, deall) \
- do { \
- if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) { \
- if (deall) { \
- OPENSSL_free((p)->err_data[i]); \
- (p)->err_data[i] = NULL; \
- (p)->err_data_size[i] = 0; \
- (p)->err_data_flags[i] = 0; \
- } else if ((p)->err_data[i] != NULL) { \
- (p)->err_data[i][0] = '\0'; \
- } \
- } else { \
- (p)->err_data[i] = NULL; \
- (p)->err_data_size[i] = 0; \
- (p)->err_data_flags[i] = 0; \
- } \
- } while (0)
-
-#define err_clear(p, i, deall) \
- do { \
- err_clear_data((p), (i), (deall)); \
- (p)->err_flags[i] = 0; \
- (p)->err_buffer[i] = 0; \
- (p)->err_file[i] = NULL; \
- (p)->err_line[i] = -1; \
- } while (0)
-
static void ERR_STATE_free(ERR_STATE *s)
{
int i;
/********************************************************/
-void ERR_put_func_error(int lib, const char *func, int reason,
- const char *file, int line)
-{
- ERR_put_error(lib, 0, reason, file, line);
- ERR_add_error_data(2, "calling function ", func);
-}
-
-void ERR_put_error(int lib, int func, int reason, const char *file, int line)
-{
- ERR_STATE *es;
-
-#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
- es = ERR_get_state();
- if (es == NULL)
- return;
-
- err_get_slot(es);
- err_clear(es, 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;
-}
-
void ERR_clear_error(void)
{
int i;
ERR_STATE *es;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return;
unsigned long ERR_get_error(void)
{
- return get_error_values(1, 0, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_POP, NULL, NULL, NULL, NULL, NULL);
}
unsigned long ERR_get_error_line(const char **file, int *line)
{
- return get_error_values(1, 0, file, line, NULL, NULL);
+ return get_error_values(EV_POP, file, line, NULL, NULL, NULL);
}
+unsigned long ERR_get_error_func(const char **func)
+{
+ return get_error_values(EV_POP, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_get_error_data(const char **data, int *flags)
+{
+ return get_error_values(EV_POP, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_get_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_POP, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
- return get_error_values(1, 0, file, line, data, flags);
+ return get_error_values(EV_POP, file, line, NULL, data, flags);
}
+#endif
unsigned long ERR_peek_error(void)
{
- return get_error_values(0, 0, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_PEEK, NULL, NULL, NULL, NULL, NULL);
}
unsigned long ERR_peek_error_line(const char **file, int *line)
{
- return get_error_values(0, 0, file, line, NULL, NULL);
+ return get_error_values(EV_PEEK, file, line, NULL, NULL, NULL);
}
+unsigned long ERR_peek_error_func(const char **func)
+{
+ return get_error_values(EV_PEEK, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_peek_error_data(const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
unsigned long ERR_peek_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
- return get_error_values(0, 0, file, line, data, flags);
+ return get_error_values(EV_PEEK, file, line, NULL, data, flags);
}
+#endif
unsigned long ERR_peek_last_error(void)
{
- return get_error_values(0, 1, NULL, NULL, NULL, NULL);
+ return get_error_values(EV_PEEK_LAST, NULL, 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);
+ return get_error_values(EV_PEEK_LAST, file, line, NULL, NULL, NULL);
}
+unsigned long ERR_peek_last_error_func(const char **func)
+{
+ return get_error_values(EV_PEEK_LAST, NULL, NULL, func, NULL, NULL);
+}
+
+unsigned long ERR_peek_last_error_data(const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK_LAST, NULL, NULL, NULL, data, flags);
+}
+
+unsigned long ERR_peek_last_error_all(const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
+{
+ return get_error_values(EV_PEEK_LAST, file, line, func, data, flags);
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
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);
+ return get_error_values(EV_PEEK_LAST, file, line, NULL, data, flags);
}
+#endif
-static unsigned long get_error_values(int inc, int top, const char **file,
- int *line, const char **data,
- int *flags)
+static unsigned long get_error_values(ERR_GET_ACTION g,
+ const char **file, int *line,
+ const char **func,
+ const char **data, int *flags)
{
int i = 0;
ERR_STATE *es;
unsigned long ret;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return 0;
- if (inc && top) {
- if (file)
- *file = "";
- if (line)
- *line = 0;
- if (data)
- *data = "";
- if (flags)
- *flags = 0;
-
- return ERR_R_INTERNAL_ERROR;
- }
-
+ /*
+ * Clear anything that should have been cleared earlier. We do this
+ * here because this doesn't have constant-time issues.
+ */
while (es->bottom != es->top) {
if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
err_clear(es, es->top, 0);
break;
}
+ /* If everything has been cleared, the stack is empty. */
if (es->bottom == es->top)
return 0;
- if (top)
- i = es->top; /* last error */
+ /* Which error, the top of stack (latest one) or the first one? */
+ if (g == EV_PEEK_LAST)
+ i = es->top;
else
- i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+ i = (es->bottom + 1) % ERR_NUM_ERRORS;
ret = es->err_buffer[i];
- if (inc) {
+ if (g == EV_POP) {
es->bottom = i;
es->err_buffer[i] = 0;
}
- if (file != NULL && line != NULL) {
- if (es->err_file[i] == NULL) {
- *file = "NA";
- *line = 0;
- } else {
- *file = es->err_file[i];
- *line = es->err_line[i];
- }
+ if (file != NULL) {
+ *file = es->err_file[i];
+ if (*file == NULL)
+ *file = "";
}
-
+ if (line != NULL)
+ *line = es->err_line[i];
+ if (func != NULL) {
+ *func = es->err_func[i];
+ if (*func == NULL)
+ *func = "";
+ }
+ if (flags != NULL)
+ *flags = es->err_data_flags[i];
if (data == NULL) {
- if (inc) {
+ if (g == EV_POP) {
err_clear_data(es, i, 0);
}
} else {
- if (es->err_data[i] == NULL) {
+ *data = es->err_data[i];
+ if (*data == NULL) {
*data = "";
if (flags != NULL)
*flags = 0;
- } else {
- *data = es->err_data[i];
- if (flags != NULL)
- *flags = es->err_data_flags[i];
}
}
return ret;
return ((p == NULL) ? NULL : p->string);
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
const char *ERR_func_error_string(unsigned long e)
{
- if (!RUN_ONCE(&err_string_init, do_err_strings_init))
- return NULL;
- return ERR_GET_LIB(e) == ERR_LIB_SYS ? "system library" : NULL;
+ return NULL;
}
+#endif
const char *ERR_reason_error_string(unsigned long e)
{
r = ERR_GET_REASON(e);
d.error = ERR_PACK(l, 0, r);
p = int_err_get_item(&d);
- if (!p) {
+ if (p == NULL) {
d.error = ERR_PACK(0, 0, r);
p = int_err_get_item(&d);
}
ERR_STATE_free(state);
}
-#if !OPENSSL_API_1_1_0
+#ifndef OPENSSL_NO_DEPRECATED_1_1_0
void ERR_remove_thread_state(void *dummy)
{
}
#endif
-#if !OPENSSL_API_1_0_0
+#ifndef OPENSSL_NO_DEPRECATED_1_0_0
void ERR_remove_state(unsigned long pid)
{
}
return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
}
-ERR_STATE *ERR_get_state(void)
+ERR_STATE *err_get_state_int(void)
{
ERR_STATE *state;
int saveerrno = get_last_sys_error();
return state;
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ERR_STATE *ERR_get_state(void)
+{
+ return err_get_state_int();
+}
+#endif
+
+
/*
* err_shelve_state returns the current thread local error state
* and freezes the error module until err_unshelve_state is called.
int deallocate)
{
ERR_STATE *es;
- int i;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return 0;
- i = es->top;
-
err_clear_data(es, es->top, deallocate);
- es->err_data[i] = data;
- es->err_data_size[i] = size;
- es->err_data_flags[i] = flags;
+ err_set_data(es, es->top, data, size, flags);
return 1;
}
ERR_STATE *es;
/* Get the current error data; if an allocated string get it. */
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return;
i = es->top;
}
len = strlen(str);
- for (len = 0; --num >= 0; ) {
+ while (--num >= 0) {
arg = va_arg(args, char *);
if (arg == NULL)
arg = "<NULL>";
len += strlen(arg);
- if (len > size) {
+ if (len >= size) {
char *p;
size = len + 20;
- p = OPENSSL_realloc(str, size + 1);
+ p = OPENSSL_realloc(str, size);
if (p == NULL) {
OPENSSL_free(str);
return;
}
str = p;
}
- OPENSSL_strlcat(str, arg, (size_t)size + 1);
+ OPENSSL_strlcat(str, arg, (size_t)size);
}
if (!err_set_error_data_int(str, size, flags, 0))
OPENSSL_free(str);
{
ERR_STATE *es;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return 0;
{
ERR_STATE *es;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return 0;
ERR_STATE *es;
int top;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return 0;
ERR_STATE *es;
int top;
- es = ERR_get_state();
+ es = err_get_state_int();
if (es == NULL)
return;