From 4304b995a3f006e120984eb34edc41662e7f4109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Thu, 16 Oct 2025 19:38:33 +0200 Subject: [PATCH] Improve debug message with context dump (passwords) during auth handshake This message is dump with each call to 'process_pkt_handshake_response' printing the updated context. When the verbosity value for module 'debug_mysql_protocol' is >= 5, the stored and client supplied passwords will be dumped in HEX format, for values < 5, the passwords will be masked. --- include/proxysql_utils.h | 14 +++++++++ lib/MySQL_Protocol.cpp | 64 +++++++++++++++++++--------------------- lib/proxysql_utils.cpp | 30 +++++++++++++++++++ 3 files changed, 74 insertions(+), 34 deletions(-) diff --git a/include/proxysql_utils.h b/include/proxysql_utils.h index df8e13600b..05e271c55d 100644 --- a/include/proxysql_utils.h +++ b/include/proxysql_utils.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -201,6 +202,19 @@ int wexecvp( */ uint64_t get_timestamp_us(); + /** + * @brief Converts a string to its hexadecimal representation. + * @param str The input string to convert. + * @return The hexadecimal representation of the input string. Empty for empty input. + */ +std::string hex(const std::string_view& str); +/** + * @brief Converts a hexadecimal string to its original string representation. + * @param hex The hexadecimal string to convert. + * @return The original string representation of the input hexadecimal string. Empty for empty input. + */ +std::string unhex(const std::string_view& hex); + /** * @brief Helper function to replace all the occurrences in a string of a matching substring in favor * of another string. diff --git a/lib/MySQL_Protocol.cpp b/lib/MySQL_Protocol.cpp index a57c45730f..22b74ecc2a 100644 --- a/lib/MySQL_Protocol.cpp +++ b/lib/MySQL_Protocol.cpp @@ -57,24 +57,6 @@ static const char *plugins[3] = { #include "MySQL_encode.h" -std::string unhex(const std::string& hex) { - if (hex.size() % 2 || hex.size() == 0) { return {}; }; - - string result {}; - - for (size_t i = 0; i < hex.size() - 1; i += 2) { - string hex_char { string { hex[i] } + hex[i+1] }; - uint64_t char_val { 0 }; - - std::istringstream stream { hex_char }; - stream >> std::hex >> char_val; - - result += string { static_cast(char_val) }; - } - - return result; -} - char* get_password(account_details_t& ad, PASSWORD_TYPE::E passtype) { char* ret = nullptr; @@ -2526,22 +2508,6 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned __exit_do_auth: - -#ifdef DEBUG - { - char *tmp_pass= NULL; - if (vars1.password) { - tmp_pass = strdup(vars1.password); - int lpass = strlen(tmp_pass); - for (int i=2; i, capabilities:%u char:%u, use_ssl:%s\n", - (vars1.capabilities & CLIENT_SECURE_CONNECTION ? "new" : "old"), vars1.user, tmp_pass, vars1.db, (*myds)->myconn->options.max_allowed_pkt, vars1.capabilities, vars1.charset, ((*myds)->encrypted ? "yes" : "no")); - free(tmp_pass); - } -#endif assert(sess); assert(sess->client_myds); @@ -2583,6 +2549,36 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned userinfo->set(NULL,NULL,NULL,NULL); // just to call compute_hash() __exit_process_pkt_handshake_response: + +#ifdef DEBUG + { + const auto get_debug_pass = [] (const char* pass, size_t len = 0) -> string { + if (!pass) { return "(null)"; } + + const string_view pass_view { len > 0 ? string_view { pass, len } : string_view { pass } }; + const string hex_pass { hex(pass_view) }; + + if (GloVars.global.gdbg_lvl[PROXY_DEBUG_MYSQL_PROTOCOL].verbosity >= 5) { + return hex_pass; + } else { + return string { get_masked_pass(hex_pass.c_str()).get() }; + } + }; + + const string tmp_pass { get_debug_pass(vars1.password) }; + const string tmp_cpass { get_debug_pass(reinterpret_cast(vars1.pass), vars1.pass_len) }; + + proxy_debug(PROXY_DEBUG_MYSQL_PROTOCOL, 1, + "Handshake in progress session_id=%u user=\"%s\" password=\"%s\" client_pass=\"%s\" scramble=\"%s\"" + " db=\"%s\" auth_method=\"%s\" max_pkt=%u capabilities=%u charset=%u use_ssl=%d auth_in_progress=%d\n", + (*myds)->sess->thread_session_id, vars1.user, tmp_pass.c_str(), tmp_cpass.c_str(), + hex((*myds)->myconn->scramble_buff).c_str(), vars1.db, vars1.auth_plugin, + (*myds)->myconn->options.max_allowed_pkt, vars1.capabilities, vars1.charset, (*myds)->encrypted, + (*myds)->auth_in_progress + ); + } +#endif + free(vars1.pass); if (vars1.password) { free(vars1.password); diff --git a/lib/proxysql_utils.cpp b/lib/proxysql_utils.cpp index b64e50d4cd..7920c24ef1 100644 --- a/lib/proxysql_utils.cpp +++ b/lib/proxysql_utils.cpp @@ -19,6 +19,7 @@ using std::function; using std::string; +using std::string_view; using std::unique_ptr; using std::vector; @@ -122,6 +123,35 @@ uint64_t get_timestamp_us() { return start_timestamp; } +string hex(const string_view& str) { + std::ostringstream hex_stream; + + for (unsigned char c : str) { + hex_stream << std::hex << std::setfill('0') << std::setw(2) << + std::uppercase << static_cast(c); + } + + return hex_stream.str(); +} + +string unhex(const string_view& hex) { + if (hex.size() % 2 || hex.size() == 0) { return {}; }; + + string result {}; + + for (size_t i = 0; i < hex.size() - 1; i += 2) { + string hex_char { string { hex[i] } + hex[i+1] }; + uint64_t char_val { 0 }; + + std::istringstream stream { hex_char }; + stream >> std::hex >> char_val; + + result += string { static_cast(char_val) }; + } + + return result; +} + /** * @brief Verifies if the supplied process 'pid' exists within the supplied 'timeout'. *