#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/atexit.h>
+#include <freeradius-devel/tls/strerror.h>
+#include <freeradius-devel/tls/utils.h>
#include <stdatomic.h>
#include "log.h"
-#include "utils.h"
-
-#if OPENSSL_VERSION_NUMBER < 0x30000000L
-static inline unsigned long ERR_get_error_all(const char **file, int *line,
- const char **func,
- const char **data, int *flags)
-{
- if (func != NULL) *func = "";
-
- return ERR_get_error_line_data(file, line, data, flags);
-}
-#endif
/** Holds the state of a log BIO
*
*/
static _Thread_local fr_tls_log_bio_t *global_log_bio;
-static void _tls_cert_line_push(char const *file, int line, int idx, X509 *cert)
-{
- char subject[1024];
-
- X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject));
- subject[sizeof(subject) - 1] = '\0';
-
- _fr_strerror_printf_push(file, line, "[%i] %s %s", idx, fr_tls_utils_x509_pkey_type(cert), subject);
-}
-
-static void _tls_cert_line_marker_push(char const *file, int line,
- int idx, X509 *cert, bool marker)
-{
- char subject[1024];
-
- X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject));
- subject[sizeof(subject) - 1] = '\0';
-
- _fr_strerror_printf_push(file, line, "%s [%i] %s %s", marker ? ">" : " ",
- idx, fr_tls_utils_x509_pkey_type(cert), subject);
-}
-
-static void _tls_cert_line_marker_no_idx_push(char const *file, int line, X509 *cert)
-{
- char subject[1024];
-
- X509_NAME_oneline(X509_get_subject_name(cert), subject, sizeof(subject));
- subject[sizeof(subject) - 1] = '\0';
-
- _fr_strerror_printf_push(file, line, "%s %s", fr_tls_utils_x509_pkey_type(cert), subject);
-}
-
-DIAG_OFF(DIAG_UNKNOWN_PRAGMAS)
-DIAG_OFF(used-but-marked-unused) /* fix spurious warnings for sk macros */
-/** Print out the current stack of certs to the thread local error buffer
- *
- * @param[in] file File where this function is being called.
- * @param[in] line Line where this function is being called.
- * @param[in] chain The certificate chain.
- * @param[in] cert The leaf certificate.
- */
-void _fr_tls_chain_push(char const *file, int line, STACK_OF(X509) *chain, X509 *cert)
-{
- int i;
-
- for (i = sk_X509_num(chain); i > 0 ; i--) {
- _tls_cert_line_push(file, line, i, sk_X509_value(chain, i - 1));
- }
- if (cert) _tls_cert_line_push(file, line, i, cert);
-}
-
/** Print out the current stack of certs
*
* @param[in] file File where this function is being called.
* Dump to the thread local buffer
*/
fr_strerror_clear();
- _fr_tls_chain_push(file, line, chain, cert);
+ _fr_tls_strerror_push_chain(file, line, chain, cert);
if (request) {
log_request_perror(log_type, L_DBG_LVL_OFF, request, file, line, NULL);
} else {
}
}
-/** Print out the current stack of certs to the thread local error buffer
- *
- * @param[in] file File where this function is being called.
- * @param[in] line Line where this function is being called.
- * @param[in] chain The certificate chain.
- * @param[in] cert The leaf certificate.
- * @param[in] marker The certificate we want to mark.
- */
-void _fr_tls_chain_marker_push(char const *file, int line,
- STACK_OF(X509) *chain, X509 *cert, X509 *marker)
-{
- int i;
-
- for (i = sk_X509_num(chain); i > 0 ; i--) {
- X509 *selected = sk_X509_value(chain, i - 1);
- _tls_cert_line_marker_push(file, line, i, selected, (selected == marker));
- }
- if (cert) _tls_cert_line_marker_push(file, line, i, cert, (cert == marker));
-}
-
/** Print out the current stack of certs
*
* @param[in] file File where this function is being called.
* Dump to the thread local buffer
*/
fr_strerror_clear();
- _fr_tls_chain_marker_push(file, line, chain, cert, marker);
+ _fr_tls_strerror_push_chain_marker(file, line, chain, cert, marker);
if (request) {
log_request_perror(log_type, L_DBG_LVL_OFF, request, file, line, NULL);
} else {
}
}
-/** Print out the current stack of X509 objects (certificates only)
- *
- * @param[in] file File where this function is being called.
- * @param[in] line Line where this function is being called.
- * @param[in] objects A stack of X509 objects
- */
-void _fr_tls_x509_objects_push(char const *file, int line,
- STACK_OF(X509_OBJECT) *objects)
-{
- int i;
-
- for (i = sk_X509_OBJECT_num(objects); i > 0 ; i--) {
- X509_OBJECT *obj = sk_X509_OBJECT_value(objects, i - 1);
-
- switch (X509_OBJECT_get_type(obj)) {
- case X509_LU_X509: /* X509 certificate */
- /*
- * Dump to the thread local buffer
- */
- _tls_cert_line_marker_no_idx_push(file, line, X509_OBJECT_get0_X509(obj));
- break;
-
- case X509_LU_CRL: /* Certificate revocation list */
- continue;
-
- default:
- continue;
- }
- }
-}
-
/** Print out the current stack of X509 objects (certificates only)
*
* @param[in] file File where this function is being called.
{
fr_strerror_clear();
- _fr_tls_x509_objects_push(file, line, objects);
+ _fr_tls_strerror_push_x509_objects(file, line, objects);
if (request) {
log_request_perror(log_type, L_DBG_LVL_OFF, request, file, line, NULL);
} else {
}
}
-DIAG_OFF(format-nonliteral)
-/** Print errors in the TLS thread local error stack
- *
- * Drains the thread local OpenSSL error queue, and prints out the first error
- * storing it in libfreeradius's error buffer.
- *
- * @param[in] msg Error message describing the operation being attempted.
- * @param[in] ap Arguments for msg.
- * @return the number of errors drained from the stack.
- */
-static int tls_strerror_vasprintf(char const *msg, va_list ap)
-{
- unsigned long error;
- char *p = NULL;
- int drained = 0;
- char buffer[256];
-
- int line;
- char const *file;
- char const *func;
- char const *data;
- int flags = 0;
-
- /*
- * Pop the first error, so ERR_peek_error()
- * can be used to determine if there are
- * multiple errors.
- */
- error = ERR_get_error_all(&file, &line, &func, &data, &flags);
- if (!(flags & ERR_TXT_STRING)) data = NULL;
-
- if (msg) {
- /*
- * Print the error we were passed, and
- * OpenSSL's error.
- */
- p = talloc_vasprintf(NULL, msg, ap);
- if (error) {
- ERR_error_string_n(error, buffer, sizeof(buffer));
- _fr_strerror_printf(file, line, "%s: %s%c%s", p, buffer, data ? ':' : '\0', data ? data : "");
- talloc_free(p);
- drained++;
- /*
- * Print the error we were given, irrespective
- * of whether there were any OpenSSL errors.
- */
- } else {
- fr_strerror_printf("%s", p);
- talloc_free(p);
- }
- } else if (error) {
- ERR_error_string_n(error, buffer, sizeof(buffer));
- _fr_strerror_printf(file, line, "%s%c%s", buffer, data ? ':' : '\0', data ? data : "");
- drained++;
- } else {
- return 0;
- }
-
- while ((error = ERR_get_error_all(&file, &line, &func, &data, &flags))) {
- if (!(flags & ERR_TXT_STRING)) data = NULL;
-
- ERR_error_string_n(error, buffer, sizeof(buffer));
-
- _fr_strerror_printf_push(file, line, "%s%c%s", buffer, data ? ':' : '\0', data ? data : "");
- drained++;
- }
-
- return drained;
-}
-DIAG_ON(format-nonliteral)
-
/** Print errors raised by OpenSSL I/O functions
*
* Drains the thread local OpenSSL error queue, and prints out errors
*/
case SSL_ERROR_SSL:
va_start(ap, fmt);
- (void)tls_strerror_vasprintf(fmt, ap);
+ (void)fr_tls_strerror_vprintf(fmt, ap);
va_end(ap);
ROPTIONAL(RPERROR, PERROR, "");
return 0;
}
-/** Wrapper around fr_strerror_printf to log error messages for library functions calling libssl
- *
- * @note Will only drain the first error.
- *
- * @param[in] msg Error message describing the operation being attempted.
- * @param[in] ... Arguments for msg.
- * @return the number of errors drained from the stack.
- */
-int fr_tls_strerror_printf(char const *msg, ...)
-{
- va_list ap;
- int ret;
-
- va_start(ap, msg);
- ret = tls_strerror_vasprintf(msg, ap);
- va_end(ap);
-
- return ret;
-}
/** Print errors in the TLS thread local error stack
*
int ret;
va_start(ap, msg);
- ret = tls_strerror_vasprintf(msg, ap);
+ ret = fr_tls_strerror_vprintf(msg, ap);
va_end(ap);
ROPTIONAL(RPERROR, PERROR, "");
#include "base.h"
-/** Push a representation of a certificate chain onto the thread local error stack
- *
- * @param[in] _chain A stack of X509 certificates representing the chain.
- * @param[in] _leaf The leaf certificate. May be NULL.
- * @param[in] _marker The certificate to emit a marker for.
- */
-#define fr_tls_chain_push(_chain, _leaf) \
- _fr_tls_chain_push( __FILE__, __LINE__, _chain, _leaf)
-void _fr_tls_chain_push(char const *file, int line, STACK_OF(X509) *chain, X509 *cert);
-
/** Write out a certificate chain to the request or global log
*
* @param[in] _request The current request or NULL if you want to write to the global log.
void _fr_tls_chain_log(char const *file, int line,
request_t *request, fr_log_type_t log_type, STACK_OF(X509) *chain, X509 *leaf);
-/** Push a representation of a certificate chain with a marker onto the thread local error stack
- *
- * @param[in] _chain A stack of X509 certificates representing the chain.
- * @param[in] _leaf The leaf certificate. May be NULL.
- * @param[in] _marker The certificate to emit a marker for.
- */
-#define fr_tls_chain_marker_push(_chain, _leaf, _marker) \
- _fr_tls_chain_push( __FILE__, __LINE__, _chain, _leaf, _marker)
-void _fr_tls_chain_marker_push(char const *file, int line,
- STACK_OF(X509) *chain, X509 *cert, X509 *marker);
-
/** Write out a certificate chain with a marker to the request or global log
*
* @param[in] _request The current request or NULL if you want to write to the global log.
request_t *request, fr_log_type_t log_type, STACK_OF(X509) *chain, X509 *leaf,
X509 *marker);
-/** Push a collection of X509 objects into the thread local error stack
- *
- * @param[in] _objects to push onto the thread local error stack
- */
-#define fr_tls_x509_objects_push(_objects) \
- _fr_tls_x509_objects_push( __FILE__, __LINE__, _objects)
-void _fr_tls_x509_objects_push(char const *file, int line,
- STACK_OF(X509_OBJECT) *objects);
-
/** Write out a collection of X509 objects to the request or global log
*
* @param[in] _request The current request or NULL if you want to write to the global log.
int fr_tls_log_io_error(request_t *request, int err, char const *msg, ...)
CC_HINT(format (printf, 3, 4));
-int fr_tls_strerror_printf(char const *msg, ...) CC_HINT(format (printf, 1, 2));
-
int fr_tls_log(request_t *request, char const *msg, ...) CC_HINT(format (printf, 2, 3));
void fr_tls_log_clear(void);