1 /* 2 * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (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 #define OSSL_FORCE_ERR_STATE 11 12 #include <stdio.h> 13 #include "internal/cryptlib.h" 14 #include <openssl/crypto.h> 15 #include <openssl/buffer.h> 16 #include <openssl/err.h> 17 #include "err_local.h" 18 19 #define ERR_PRINT_BUF_SIZE 4096 20 void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u), 21 void *u) 22 { 23 CRYPTO_THREAD_ID tid = CRYPTO_THREAD_get_current_id(); 24 unsigned long l; 25 const char *file, *data, *func; 26 int line, flags; 27 28 while ((l = ERR_get_error_all(&file, &line, &func, &data, &flags)) != 0) { 29 char buf[ERR_PRINT_BUF_SIZE] = ""; 30 char *hex = NULL; 31 int offset; 32 33 if ((flags & ERR_TXT_STRING) == 0) 34 data = ""; 35 36 hex = ossl_buf2hexstr_sep((const unsigned char *)&tid, sizeof(tid), '\0'); 37 BIO_snprintf(buf, sizeof(buf), "%s:", hex == NULL ? "<null>" : hex); 38 offset = strlen(buf); 39 ossl_err_string_int(l, func, buf + offset, sizeof(buf) - offset); 40 offset += strlen(buf + offset); 41 BIO_snprintf(buf + offset, sizeof(buf) - offset, ":%s:%d:%s\n", 42 file, line, data); 43 OPENSSL_free(hex); 44 if (cb(buf, strlen(buf), u) <= 0) 45 break; /* abort outputting the error report */ 46 } 47 } 48 49 /* auxiliary function for incrementally reporting texts via the error queue */ 50 static void put_error(int lib, const char *func, int reason, 51 const char *file, int line) 52 { 53 ERR_new(); 54 ERR_set_debug(file, line, func); 55 ERR_set_error(lib, reason, NULL /* no data here, so fmt is NULL */); 56 } 57 58 #define TYPICAL_MAX_OUTPUT_BEFORE_DATA 100 59 #define MAX_DATA_LEN (ERR_PRINT_BUF_SIZE - TYPICAL_MAX_OUTPUT_BEFORE_DATA) 60 void ERR_add_error_txt(const char *separator, const char *txt) 61 { 62 const char *file = NULL; 63 int line; 64 const char *func = NULL; 65 const char *data = NULL; 66 int flags; 67 unsigned long err = ERR_peek_last_error(); 68 69 if (separator == NULL) 70 separator = ""; 71 if (err == 0) 72 put_error(ERR_LIB_NONE, NULL, 0, "", 0); 73 74 do { 75 size_t available_len, data_len; 76 const char *curr = txt, *next = txt; 77 const char *leading_separator = separator; 78 int trailing_separator = 0; 79 char *tmp; 80 81 ERR_peek_last_error_all(&file, &line, &func, &data, &flags); 82 if ((flags & ERR_TXT_STRING) == 0) { 83 data = ""; 84 leading_separator = ""; 85 } 86 data_len = strlen(data); 87 88 /* workaround for limit of ERR_print_errors_cb() */ 89 if (data_len >= MAX_DATA_LEN 90 || strlen(separator) >= (size_t)(MAX_DATA_LEN - data_len)) 91 available_len = 0; 92 else 93 available_len = MAX_DATA_LEN - data_len - strlen(separator) - 1; 94 /* MAX_DATA_LEN > available_len >= 0 */ 95 96 if (*separator == '\0') { 97 const size_t len_next = strlen(next); 98 99 if (len_next <= available_len) { 100 next += len_next; 101 curr = NULL; /* no need to split */ 102 } else { 103 next += available_len; 104 curr = next; /* will split at this point */ 105 } 106 } else { 107 while (*next != '\0' && (size_t)(next - txt) <= available_len) { 108 curr = next; 109 next = strstr(curr, separator); 110 if (next != NULL) { 111 next += strlen(separator); 112 trailing_separator = *next == '\0'; 113 } else { 114 next = curr + strlen(curr); 115 } 116 } 117 if ((size_t)(next - txt) <= available_len) 118 curr = NULL; /* the above loop implies *next == '\0' */ 119 } 120 if (curr != NULL) { 121 /* split error msg at curr since error data would get too long */ 122 if (curr != txt) { 123 tmp = OPENSSL_strndup(txt, curr - txt); 124 if (tmp == NULL) 125 return; 126 ERR_add_error_data(2, separator, tmp); 127 OPENSSL_free(tmp); 128 } 129 put_error(ERR_GET_LIB(err), func, err, file, line); 130 txt = curr; 131 } else { 132 if (trailing_separator) { 133 tmp = OPENSSL_strndup(txt, next - strlen(separator) - txt); 134 if (tmp == NULL) 135 return; 136 /* output txt without the trailing separator */ 137 ERR_add_error_data(2, leading_separator, tmp); 138 OPENSSL_free(tmp); 139 } else { 140 ERR_add_error_data(2, leading_separator, txt); 141 } 142 txt = next; /* finished */ 143 } 144 } while (*txt != '\0'); 145 } 146 147 void ERR_add_error_mem_bio(const char *separator, BIO *bio) 148 { 149 if (bio != NULL) { 150 char *str; 151 long len = BIO_get_mem_data(bio, &str); 152 153 if (len > 0) { 154 if (str[len - 1] != '\0') { 155 if (BIO_write(bio, "", 1) <= 0) 156 return; 157 158 len = BIO_get_mem_data(bio, &str); 159 } 160 if (len > 1) 161 ERR_add_error_txt(separator, str); 162 } 163 } 164 } 165 166 static int print_bio(const char *str, size_t len, void *bp) 167 { 168 return BIO_write((BIO *)bp, str, len); 169 } 170 171 void ERR_print_errors(BIO *bp) 172 { 173 ERR_print_errors_cb(print_bio, bp); 174 } 175 176 #ifndef OPENSSL_NO_STDIO 177 void ERR_print_errors_fp(FILE *fp) 178 { 179 BIO *bio = BIO_new_fp(fp, BIO_NOCLOSE); 180 if (bio == NULL) 181 return; 182 183 ERR_print_errors_cb(print_bio, bio); 184 BIO_free(bio); 185 } 186 #endif 187