From 956fba242ac0a4bcfe3db103d4d1f41545c924fb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 7 Apr 2024 16:15:34 +0200 Subject: [PATCH] add callbacks for debug messages This is useful for tracking down connection issues Signed-off-by: Felix Fietkau --- ustream-internal.h | 1 + ustream-mbedtls.c | 33 ++++++++++++++++++ ustream-mbedtls.h | 2 ++ ustream-openssl.c | 83 +++++++++++++++++++++++++++++++++++++++++----- ustream-openssl.h | 11 ++++-- ustream-ssl.c | 1 + ustream-ssl.h | 5 ++- 7 files changed, 124 insertions(+), 12 deletions(-) diff --git a/ustream-internal.h b/ustream-internal.h index e80abf8..f8f28e1 100644 --- a/ustream-internal.h +++ b/ustream-internal.h @@ -40,6 +40,7 @@ int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char *file); int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char *file); int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers); int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, bool require); +void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level, ustream_ssl_debug_cb cb, void *cb_priv); void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx); enum ssl_conn_status __ustream_ssl_connect(struct ustream_ssl *us); int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len); diff --git a/ustream-mbedtls.c b/ustream-mbedtls.c index 13785ce..b733ea1 100644 --- a/ustream-mbedtls.c +++ b/ustream-mbedtls.c @@ -26,6 +26,30 @@ #include "ustream-ssl.h" #include "ustream-internal.h" #include +#include + +static void debug_cb(void *ctx_p, int level, + const char *file, int line, + const char *str) +{ + struct ustream_ssl_ctx *ctx = ctx_p; + const char *fstr; + char buf[512]; + int len; + + if (!ctx->debug_cb) + return; + + while ((fstr = strstr(file + 1, "library/")) != NULL) + file = fstr; + + len = snprintf(buf, sizeof(buf), "%s:%04d: %s", file, line, str); + if (len >= (int)sizeof(buf)) + len = (int)sizeof(buf) - 1; + if (buf[len - 1] == '\n') + buf[len - 1] = 0; + ctx->debug_cb(ctx->debug_cb_priv, level, buf); +} static int s_ustream_read(void *ctx, unsigned char *buf, size_t len) { @@ -433,6 +457,15 @@ __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) return ret; } +__hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level, + ustream_ssl_debug_cb cb, void *cb_priv) +{ + ctx->debug_cb = cb; + ctx->debug_cb_priv = cb_priv; + mbedtls_ssl_conf_dbg(&ctx->conf, debug_cb, ctx); + mbedtls_debug_set_threshold(level); +} + __hidden void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx) { mbedtls_ssl_context *ssl; diff --git a/ustream-mbedtls.h b/ustream-mbedtls.h index 7e7c699..ff907f6 100644 --- a/ustream-mbedtls.h +++ b/ustream-mbedtls.h @@ -39,6 +39,8 @@ struct ustream_ssl_ctx { #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif + ustream_ssl_debug_cb debug_cb; + void *debug_cb_priv; bool server; int *ciphersuites; }; diff --git a/ustream-openssl.c b/ustream-openssl.c index 7a991e9..3d576be 100644 --- a/ustream-openssl.c +++ b/ustream-openssl.c @@ -106,6 +106,7 @@ __hidden struct ustream_ssl_ctx * __ustream_ssl_context_new(bool server) { + struct ustream_ssl_ctx *ctx; const void *m; SSL_CTX *c; @@ -134,6 +135,9 @@ __ustream_ssl_context_new(bool server) if (!c) return NULL; + ctx = calloc(1, sizeof(*ctx)); + ctx->ssl = c; + #if defined(HAVE_WOLFSSL) if (server) SSL_CTX_set_verify(c, SSL_VERIFY_NONE, NULL); @@ -169,14 +173,14 @@ __ustream_ssl_context_new(bool server) } SSL_CTX_set_quiet_shutdown(c, 1); - return (void *) c; + return ctx; } __hidden int __ustream_ssl_add_ca_crt_file(struct ustream_ssl_ctx *ctx, const char *file) { int ret; - ret = SSL_CTX_load_verify_locations((void *) ctx, file, NULL); + ret = SSL_CTX_load_verify_locations(ctx->ssl, file, NULL); if (ret < 1) return -1; @@ -187,9 +191,9 @@ __hidden int __ustream_ssl_set_crt_file(struct ustream_ssl_ctx *ctx, const char { int ret; - ret = SSL_CTX_use_certificate_chain_file((void *) ctx, file); + ret = SSL_CTX_use_certificate_chain_file(ctx->ssl, file); if (ret < 1) - ret = SSL_CTX_use_certificate_file((void *) ctx, file, SSL_FILETYPE_ASN1); + ret = SSL_CTX_use_certificate_file(ctx->ssl, file, SSL_FILETYPE_ASN1); if (ret < 1) return -1; @@ -201,9 +205,9 @@ __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char { int ret; - ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_PEM); + ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_PEM); if (ret < 1) - ret = SSL_CTX_use_PrivateKey_file((void *) ctx, file, SSL_FILETYPE_ASN1); + ret = SSL_CTX_use_PrivateKey_file(ctx->ssl, file, SSL_FILETYPE_ASN1); if (ret < 1) return -1; @@ -213,7 +217,7 @@ __hidden int __ustream_ssl_set_key_file(struct ustream_ssl_ctx *ctx, const char __hidden int __ustream_ssl_set_ciphers(struct ustream_ssl_ctx *ctx, const char *ciphers) { - int ret = SSL_CTX_set_cipher_list((void *) ctx, ciphers); + int ret = SSL_CTX_set_cipher_list(ctx->ssl, ciphers); if (ret == 0) return -1; @@ -228,14 +232,17 @@ __hidden int __ustream_ssl_set_require_validation(struct ustream_ssl_ctx *ctx, b if (!require) mode = SSL_VERIFY_NONE; - SSL_CTX_set_verify((void *) ctx, mode, NULL); + SSL_CTX_set_verify(ctx->ssl, mode, NULL); return 0; } __hidden void __ustream_ssl_context_free(struct ustream_ssl_ctx *ctx) { - SSL_CTX_free((void *) ctx); + SSL_CTX_free(ctx->ssl); + if (ctx->debug_bio) + BIO_free(ctx->debug_bio); + free(ctx); } void __ustream_ssl_session_free(void *ssl) @@ -420,3 +427,61 @@ __hidden int __ustream_ssl_read(struct ustream_ssl *us, char *buf, int len) return ret; } + +#ifndef WOLFSSL_SSL_H +static long +debug_cb(BIO *bio, int cmd, const char *argp, size_t len, int argi, long argl, + int ret, size_t *processed) +{ + struct ustream_ssl_ctx *ctx = (void *)BIO_get_callback_arg(bio); + char buf[256]; + char *str, *sep; + ssize_t cur_len; + + if (cmd != (BIO_CB_WRITE|BIO_CB_RETURN)) + goto out; + + while (1) { + cur_len = BIO_get_mem_data(bio, (void *)&str); + if (!cur_len) + break; + + sep = memchr(str, '\n', cur_len); + if (!sep) + break; + + cur_len = sep + 1 - str; + if (cur_len >= (ssize_t)sizeof(buf)) + cur_len = sizeof(buf) - 1; + + cur_len = BIO_read(bio, buf, cur_len); + if (cur_len <= 1) + break; + + cur_len--; + buf[cur_len] = 0; + if (ctx->debug_cb) + ctx->debug_cb(ctx->debug_cb_priv, 1, buf); + } + +out: + return ret; +} +#endif + +__hidden void __ustream_ssl_set_debug(struct ustream_ssl_ctx *ctx, int level, + ustream_ssl_debug_cb cb, void *cb_priv) +{ +#ifndef WOLFSSL_SSL_H + if (!ctx->debug_bio) + ctx->debug_bio = BIO_new(BIO_s_mem()); + + ctx->debug_cb = cb; + ctx->debug_cb_priv = cb_priv; + SSL_CTX_set_msg_callback(ctx->ssl, SSL_trace); + SSL_CTX_set_msg_callback_arg(ctx->ssl, ctx->debug_bio); + + BIO_set_callback_ex(ctx->debug_bio, debug_cb); + BIO_set_callback_arg(ctx->debug_bio, (void *)ctx); +#endif +} diff --git a/ustream-openssl.h b/ustream-openssl.h index 90acc86..f547aa6 100644 --- a/ustream-openssl.h +++ b/ustream-openssl.h @@ -29,6 +29,13 @@ #include +struct ustream_ssl_ctx { + SSL_CTX *ssl; + BIO *debug_bio; + ustream_ssl_debug_cb debug_cb; + void *debug_cb_priv; +}; + void __ustream_ssl_session_free(void *ssl); struct bio_ctx { @@ -36,9 +43,9 @@ struct bio_ctx { struct ustream *stream; }; -static inline void *__ustream_ssl_session_new(void *ctx) +static inline void *__ustream_ssl_session_new(struct ustream_ssl_ctx *ctx) { - return SSL_new(ctx); + return SSL_new(ctx->ssl); } static inline char *__ustream_ssl_strerror(int error, char *buffer, int len) diff --git a/ustream-ssl.c b/ustream-ssl.c index cd69f9e..c4e7971 100644 --- a/ustream-ssl.c +++ b/ustream-ssl.c @@ -230,6 +230,7 @@ const struct ustream_ssl_ops ustream_ssl_ops = { .context_add_ca_crt_file = __ustream_ssl_add_ca_crt_file, .context_set_ciphers = __ustream_ssl_set_ciphers, .context_set_require_validation = __ustream_ssl_set_require_validation, + .context_set_debug = __ustream_ssl_set_debug, .context_free = __ustream_ssl_context_free, .init = _ustream_ssl_init, .set_peer_cn = _ustream_ssl_set_peer_cn, diff --git a/ustream-ssl.h b/ustream-ssl.h index 87c0ae6..b1115c6 100644 --- a/ustream-ssl.h +++ b/ustream-ssl.h @@ -47,8 +47,9 @@ struct ustream_ssl { struct ustream_ssl_ctx; -struct ustream_ssl_ops { +typedef void (*ustream_ssl_debug_cb)(void *priv, int level, const char *msg); +struct ustream_ssl_ops { struct ustream_ssl_ctx *(*context_new)(bool server); int (*context_set_crt_file)(struct ustream_ssl_ctx *ctx, const char *file); int (*context_set_key_file)(struct ustream_ssl_ctx *ctx, const char *file); @@ -59,6 +60,7 @@ struct ustream_ssl_ops { int (*set_peer_cn)(struct ustream_ssl *conn, const char *name); int (*context_set_ciphers)(struct ustream_ssl_ctx *ctx, const char *ciphers); + void (*context_set_debug)(struct ustream_ssl_ctx *ctx, int level, ustream_ssl_debug_cb cb, void *cb_priv); int (*context_set_require_validation)(struct ustream_ssl_ctx *ctx, bool require); }; @@ -69,6 +71,7 @@ extern const struct ustream_ssl_ops ustream_ssl_ops; #define ustream_ssl_context_set_key_file ustream_ssl_ops.context_set_key_file #define ustream_ssl_context_add_ca_crt_file ustream_ssl_ops.context_add_ca_crt_file #define ustream_ssl_context_set_ciphers ustream_ssl_ops.context_set_ciphers +#define ustream_ssl_context_set_debug ustream_ssl_ops.context_set_debug #define ustream_ssl_context_set_require_validation ustream_ssl_ops.context_set_require_validation #define ustream_ssl_context_free ustream_ssl_ops.context_free #define ustream_ssl_init ustream_ssl_ops.init -- 2.30.2