From ea8211618e5db66d4e8ff66513263a264beecaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Jaramago=20Fern=C3=A1ndez?= Date: Thu, 8 May 2025 14:16:52 +0200 Subject: [PATCH] Extract auth testing utils from 'test_auth_methods-t.cpp' --- test/tap/tap/utils_auth.h | 603 +++++++++++++++++++++++ test/tap/tests/test_auth_methods-t.cpp | 652 ++----------------------- 2 files changed, 646 insertions(+), 609 deletions(-) create mode 100644 test/tap/tap/utils_auth.h diff --git a/test/tap/tap/utils_auth.h b/test/tap/tap/utils_auth.h new file mode 100644 index 000000000..36c45d3af --- /dev/null +++ b/test/tap/tap/utils_auth.h @@ -0,0 +1,603 @@ +#ifndef UTILS_AUTH_H +#define UTILS_AUTH_H + +#include +#include + +#include "proxysql_utils.h" +#include "mysql.h" + +#include "utils.h" +#include "tap.h" + +using std::pair; +using std::string; +using std::vector; + +#define MYSQL_QUERY_T__(mysql, query) \ + do { \ + if (mysql_query_t(mysql, query)) { \ + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); \ + return { EXIT_FAILURE, vector {} }; \ + } \ + } while(0) + +#define MYSQL_QUERY_T_(mysql, query) \ + do { \ + if (mysql_query_t(mysql, query)) { \ + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); \ + return { EXIT_FAILURE, user_def_t {} }; \ + } \ + } while(0) + +mf_unique_ptr MF_CHAR_(const char* s) { + return mf_unique_ptr { s ? strdup(s) : nullptr }; +} + +struct user_def_t { + string name {}; + mf_unique_ptr prim_pass { nullptr }; + mf_unique_ptr addl_pass { nullptr }; + string auth {}; + string def_db {}; + uint32_t def_hg { 0 }; + bool rand_pass {}; + + user_def_t() {} + user_def_t(const string& name_) : name(name_) {} + + user_def_t( + const string& name_, + mf_unique_ptr prim_pass_, + mf_unique_ptr addl_pass_, + const string& auth_, + const uint32_t def_hg_ = 0, + const string def_db_ = {}, + bool rand_pass_ = false + ) : + name(name_), + prim_pass(std::move(prim_pass_)), + addl_pass(std::move(addl_pass_)), + auth(auth_), + def_hg(def_hg_), + def_db(def_db_), + rand_pass(rand_pass_) + {} + + user_def_t(const user_def_t& other) : + name(other.name), + auth(other.auth), + rand_pass(other.rand_pass), + def_hg(other.def_hg), + def_db(other.def_db) + { + if (other.prim_pass) { + this->prim_pass = mf_unique_ptr(strdup(other.prim_pass.get())); + } else { + this->prim_pass = nullptr; + } + if (other.addl_pass) { + this->addl_pass = mf_unique_ptr(strdup(other.addl_pass.get())); + } else { + this->addl_pass = nullptr; + } + } + + void operator=(const user_def_t& other) { + this->name = other.name; + this->auth = other.auth; + this->rand_pass = other.rand_pass; + this->def_hg = other.def_hg; + this->def_db = other.def_db; + + if (other.prim_pass) { + this->prim_pass = mf_unique_ptr(strdup(other.prim_pass.get())); + } else { + this->prim_pass = nullptr; + } + if (other.addl_pass) { + this->addl_pass = mf_unique_ptr(strdup(other.addl_pass.get())); + } else { + this->addl_pass = nullptr; + } + } + + user_def_t(user_def_t&& other) : + name(other.name), + auth(other.auth), + rand_pass(other.rand_pass), + prim_pass(std::move(other.prim_pass)), + addl_pass(std::move(other.addl_pass)), + def_hg(other.def_hg), + def_db(other.def_db) + {} + + void operator=(user_def_t&& other) { + this->name = other.name; + this->auth = other.auth; + this->rand_pass = other.rand_pass; + this->prim_pass = std::move(other.prim_pass); + this->addl_pass = std::move(other.addl_pass); + this->def_hg = other.def_hg; + this->def_db = other.def_db; + } +}; + +struct user_creds_t { + user_def_t user_def; + mf_unique_ptr hashed_prim_pass_bin { nullptr }; + mf_unique_ptr hashed_addl_pass_bin { nullptr }; + + user_creds_t(const user_creds_t&) = delete; + user_creds_t(user_creds_t&&) noexcept(false) = default; + + void operator=(user_creds_t&& other) { + this->user_def = std::move(other.user_def); + this->hashed_prim_pass_bin = std::move(other.hashed_prim_pass_bin); + this->hashed_addl_pass_bin = std::move(other.hashed_addl_pass_bin); + } +}; + +bool is_empty_pass(const char* pass) { + return pass == nullptr || (pass && strlen(pass) == 0); +} + +std::string unhex(const std::string& hex) { + if (hex.size() % 2) { 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; +} + +std::string hex(const std::string& 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(); +} + +/** + * @brief TODO: Limitation ProxySQL doesn't allow a clear-text pass to start with '*'. See #1762. + * @param pass Password to check. + * @return 'true' if password is an invalid clear-text pass for ProxySQL. + */ +bool chk_inv_pass(const char* pass) { + if (is_empty_pass(pass)) { + return true; + } else { + if (strlen(pass)) { + return pass[0] == '*'; + } else { + return false; + } + } +} + +pair create_mysql_user_exp_creds(MYSQL* mysql, const user_def_t& user_def) { + const char* addl_pass { user_def.addl_pass.get() }; + const char* prim_pass { user_def.prim_pass.get() }; + + if (addl_pass && strlen(addl_pass)) { + const string CREATE_USER { + "CREATE USER '" + user_def.name + "'@'%' IDENTIFIED WITH" + " '" + user_def.auth + "' BY '" + user_def.addl_pass.get() + "'" + }; + const string GRANT_USER_PRIVS { "GRANT ALL on *.* to '" + user_def.name + "'@'%'" }; + + MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); + MYSQL_QUERY_T_(mysql, GRANT_USER_PRIVS.c_str()); + + if (prim_pass && strlen(prim_pass)) { + const string ALTER_USER_RETAIN { + "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED BY '" + prim_pass + "'" + " RETAIN CURRENT PASSWORD" + }; + MYSQL_QUERY_T_(mysql, ALTER_USER_RETAIN.c_str()); + } else { + const string ALTER_USER_NO_RETAIN { + "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED BY ''" + }; + // When new password is empty; retaining the previous one isn't possible + MYSQL_QUERY_T_(mysql, ALTER_USER_NO_RETAIN.c_str()); + } + } else { + string CREATE_USER { "CREATE USER '" + user_def.name + "'@'%'" }; + string GRANT_USER_PRIVS { "GRANT ALL on *.* to '" + user_def.name + "'@'%'" }; + + if (prim_pass) { + CREATE_USER += " IDENTIFIED WITH '" + user_def.auth + "' BY '" + prim_pass + "'"; + } + + MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); + MYSQL_QUERY_T_(mysql, GRANT_USER_PRIVS.c_str()); + } + + // If user has a 'default_schema' create the target schema and grant perms + if (!user_def.def_db.empty()) { + const string& u_db { user_def.def_db }; + const string& u_name { user_def.name }; + MYSQL_QUERY_T_(mysql, ("CREATE DATABASE IF NOT EXISTS " + u_db).c_str()); + MYSQL_QUERY_T_(mysql, ("GRANT ALL ON " + u_db + ".* TO '" + u_name + "'@'%'").c_str()); + } + + return { EXIT_SUCCESS, user_def }; +} + + +pair create_mysql_user_rnd_creds(MYSQL* mysql, const user_def_t& user_def) { + const string CREATE_USER { + "CREATE USER '" + user_def.name + "'@'%' IDENTIFIED WITH" + " '" + user_def.auth + "' BY RANDOM PASSWORD" + }; + const string DROP_USER { "DROP USER IF EXISTS '" + user_def.name + "'"}; + + mf_unique_ptr addl_text_pass { nullptr }; + + { + // NOTE: Required due to potential pass recreation + MYSQL_QUERY_T_(mysql, DROP_USER.c_str()); + MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); + + MYSQL_RES* myres = mysql_store_result(mysql); + MYSQL_ROW myrow = mysql_fetch_row(myres); + + if (myrow && myrow[2]) { + addl_text_pass = mf_unique_ptr(strdup(myrow[2])); + } + + mysql_free_result(myres); + } + + const string ALTER_USER { + "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED WITH" + " '" + user_def.auth + "' BY RANDOM PASSWORD RETAIN CURRENT PASSWORD" + }; + + mf_unique_ptr prim_text_pass {}; + + { + MYSQL_QUERY_T_(mysql, ALTER_USER.c_str()); + + MYSQL_RES* myres = mysql_store_result(mysql); + MYSQL_ROW myrow = mysql_fetch_row(myres); + + if (myrow && myrow[2]) { + prim_text_pass = mf_unique_ptr(strdup(myrow[2])); + } + + mysql_free_result(myres); + } + + return { + EXIT_SUCCESS, + user_def_t { + user_def.name, + std::move(prim_text_pass), + std::move(addl_text_pass), + user_def.auth, + user_def.def_hg, + user_def.def_db, + user_def.rand_pass + } + }; +} + + +pair create_mysql_user(MYSQL* mysql, const user_def_t& user_def) { + if (user_def.rand_pass) { + pair rnd_user_def {}; + + while ( + rnd_user_def.first == EXIT_SUCCESS && + (chk_inv_pass(rnd_user_def.second.prim_pass.get()) + || chk_inv_pass(rnd_user_def.second.addl_pass.get())) + ) { + rnd_user_def = create_mysql_user_rnd_creds(mysql, user_def); + } + + return rnd_user_def; + } else { + return create_mysql_user_exp_creds(mysql, user_def); + } +} + +/** + * @brief Extract the auth strings (prim/addl) pass from an existing user. + * @param mysql Opened MySQL conn in which to perform the queries. + * @param user_def User definition; used to match by username. + * @return A pair of kind `{err_code, user_creds}`. + */ +pair ext_user_auth_strs(MYSQL* mysql, const user_def_t& user_def) { + const char* addl_pass { user_def.addl_pass.get() }; + const char* prim_pass { user_def.prim_pass.get() }; + + pair p_creds_res { EXIT_SUCCESS, user_creds_t {} }; + + const string ext_auths_query { + "SELECT HEX(authentication_string),json_value(user_attributes, '$.additional_password') " + "FROM mysql.user WHERE user='" + user_def.name + "'" + }; + + if (mysql_query_t(mysql, ext_auths_query.c_str())) { + fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); + return { EXIT_FAILURE, user_creds_t {} }; + } + + MYSQL_RES* myres = mysql_store_result(mysql); + MYSQL_ROW myrow = mysql_fetch_row(myres); + + if (myrow && myrow[0]) { + const char* p_addl_pass { myrow[1] }; + + if (p_addl_pass) { + p_creds_res = { + EXIT_SUCCESS, + user_creds_t { + user_def, + mf_unique_ptr { strdup(myrow[0]) }, + mf_unique_ptr { strdup(p_addl_pass) } + } + }; + } else { + // MySQL wont allow that 'aditional' pass for a backend user; we don't verify user attributes + // right now when loading to runtime; but we wont allow user to connect with empty + // 'additional' passwords either; + if (addl_pass && strlen(addl_pass) == 0) { + p_creds_res = { + EXIT_SUCCESS, + user_creds_t { + user_def, + mf_unique_ptr { strdup(myrow[0]) }, + mf_unique_ptr { strdup("") }, + } + }; + } else { + p_creds_res = { + EXIT_SUCCESS, + user_creds_t { + user_def, + mf_unique_ptr { strdup(myrow[0]) }, + mf_unique_ptr { nullptr }, + } + }; + } + } + } else { + diag("Empty result; no auth_string found for user user:'%s'", user_def.name.c_str()); + } + + mysql_free_result(myres); + + return p_creds_res; +} + +pair create_backend_user(MYSQL* mysql, const user_def_t& user_def) { + const pair c_user_def { create_mysql_user(mysql, user_def) }; + + if (c_user_def.first == EXIT_SUCCESS) { + pair p_creds_res { ext_user_auth_strs(mysql, c_user_def.second) }; + + return p_creds_res; + } else { + return { EXIT_FAILURE, user_creds_t {} }; + } +} + +/** + * @brief Configure the backend MySQL 8 users for frontend-backend connection creation. + * @param mysql Already opened MySQL connection. + * @param backend_users The users to be created in the MySQL server. + * @return A pair of kind `{err_code, user_creds}`. + */ +pair> config_mysql_backend_users( + MYSQL* mysql, const vector& users_defs +) { + for (const auto& u : users_defs) { + MYSQL_QUERY_T__(mysql, ("DROP USER IF EXISTS '" + u.name + "'").c_str()); + } + + vector f_users_creds {}; + + for (const auto& user_def : users_defs) { + pair creds_res { create_backend_user(mysql, user_def) }; + + if (creds_res.first == EXIT_SUCCESS) { + f_users_creds.push_back(std::move(creds_res.second)); + } else { + return { EXIT_FAILURE, vector {} }; + } + } + + return { EXIT_SUCCESS, std::move(f_users_creds) }; +} + +struct test_conf_t { + /* @brief Default auth method announced by ProxySQL */ + string def_auth; + /* @brief Auth method requested by client */ + string req_auth; + /* @brief Wether to use hashed or 'clear_text' passwords. Implies a reload of 'mysql_users'. */ + bool hashed_pass; + /* @brief Wether to attempt auth under SSL conn or not. */ + bool use_ssl; + /* @brief Wether to attempt auth with compression enabled or not. */ + bool use_comp; +}; + +string to_string(const test_conf_t& conf) { + return "{ " + "\"req_auth\":'" + conf.req_auth + "', " + "\"def_auth\":'" + conf.def_auth + "', " + "\"hashed_pass\":'" + std::to_string(conf.hashed_pass) + "', " + "\"use_ssl\":'" + std::to_string(conf.use_ssl) + "'" + " }"; +} + +/** + * @brief Gen all combinations of tests configs. + * @param def_auths Defaults auths to set for ProxySQL. + * @param req_auths Auth methods for client to request. + * @param hash_pass If passwords should be hashed or not. + * @param use_ssl If connection is started with SSL or not. + * @return Vector with the combinations. + */ +vector get_auth_conf_combs( + const vector& def_auths, + const vector& req_auths, + const vector& hash_pass, + const vector& use_ssl, + const vector& use_comp +) { + vector confs {}; + + for (const auto& def_auth : def_auths) { + for (const auto& req_auth : req_auths) { + for (const auto& hashed : hash_pass) { + for (const auto& ssl : use_ssl) { + for (const auto& comp : use_comp) { + confs.push_back({def_auth, req_auth, hashed, ssl, comp}); + } + } + } + } + } + + return confs; +} + +struct PASS_TYPE { + enum E { + UNKNOWN = 0, + PRIMARY, + ADDITIONAL, + }; +}; + +string to_string(const PASS_TYPE::E type) { + if (type == PASS_TYPE::PRIMARY) { + return "PRIM"; + } else if (type == PASS_TYPE::ADDITIONAL) { + return "ADDL"; + } else { + return "UNKN"; + } +} + +/** + * @brief Info from user defs (user_def_t), extracted for building 'test_creds_t'. + */ +struct creds_info_t { + PASS_TYPE::E type; + string auth; +}; + +/** + * @brief Info about user creds used in a particular test case. + * @details Multiple 'test_creds_t' are used while testing a single 'test_conf_t'. + */ +struct test_creds_t { + string name {}; + mf_unique_ptr pass { nullptr }; + creds_info_t info {}; + + test_creds_t(const string& name_, mf_unique_ptr pass_) : name(name_), pass(std::move(pass_)) {} + test_creds_t(const string& name_, mf_unique_ptr pass_, const creds_info_t& info_) : + name(name_), pass(std::move(pass_)), info(info_) {} + test_creds_t(const test_creds_t& other) : name(other.name), info(other.info) { + this->pass = other.pass ? MF_CHAR_(other.pass.get()) : nullptr; + } +}; + +string to_string(const test_creds_t& creds) { + return "{ " + "\"name\":'" + creds.name + "', " + "\"pass\":'" + (creds.pass ? creds.pass.get() : "NULL") + "', " + "\"type\":'" + to_string(creds.info.type) + "'" + " }"; +} + +int config_proxysql_users(MYSQL* admin, const test_conf_t& test_conf, const vector& users) { + for (const auto& u : users) { + MYSQL_QUERY_T(admin, ("DELETE FROM mysql_users WHERE username='" + u.user_def.name + "'").c_str()); + } + + // Ensure cleanup of previously cached clear_text 'caching_sha2' passwords + MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); + MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); + + for (const auto& u : users) { + const string def_hg { _TO_S(u.user_def.def_hg) }; + string attrs {}; + + // A user may not have an additional_password configured + if (u.user_def.addl_pass) { + string addl_pass {}; + + // NOTE: If the primary pass is empty, addl pass must be empty **by spec** + if (is_empty_pass(u.user_def.prim_pass.get())) { + addl_pass = {}; + } else if (test_conf.hashed_pass) { + const char* c_addl_pass { u.hashed_addl_pass_bin.get() }; + + if (c_addl_pass) { + addl_pass = c_addl_pass; + } + } else { + addl_pass = u.user_def.addl_pass.get(); + } + + const string hex_addl_pass { hex(addl_pass) }; + attrs = "{\"additional_password\": \"" + hex_addl_pass + "\"}"; + } + + string insert_query {}; + + if (u.user_def.prim_pass) { + const string prim_pass { + test_conf.hashed_pass && strlen(u.hashed_prim_pass_bin.get()) > 0 ? + "UNHEX('" + string { u.hashed_prim_pass_bin.get() } + "')" : + "'" + string { u.user_def.prim_pass.get() } + "'" + }; + + if (u.user_def.addl_pass) { + insert_query = { + "INSERT INTO mysql_users (username,password,default_hostgroup,attributes) " + "VALUES ('" + u.user_def.name + "'," + prim_pass + "," + def_hg + ",'" + attrs + "')" + }; + } else { + insert_query = { + "INSERT INTO mysql_users (username,password,default_hostgroup) " + "VALUES ('" + u.user_def.name + "'," + prim_pass + "," + def_hg + ")" + }; + } + } else { + insert_query = { + "INSERT INTO mysql_users (username,default_hostgroup,attributes) " + "VALUES ('" + u.user_def.name + "'," + def_hg + ",'" + attrs + "')" + }; + } + + MYSQL_QUERY_T(admin, insert_query.c_str()); + } + + MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); + + return EXIT_SUCCESS; +} + +#endif diff --git a/test/tap/tests/test_auth_methods-t.cpp b/test/tap/tests/test_auth_methods-t.cpp index 9edb6191c..ef5570dc3 100644 --- a/test/tap/tests/test_auth_methods-t.cpp +++ b/test/tap/tests/test_auth_methods-t.cpp @@ -31,17 +31,18 @@ #include #include -#include "openssl/ssl.h" +#include "openssl/types.h" #include "json.hpp" #include "mysql.h" #include "tap.h" #include "command_line.h" #include "utils.h" +#include "utils_auth.h" // Additional env variables -uint32_t TAP_MYSQL8_BACKEND_HG = 30; -uint32_t TAP_NUM_CLIENT_THREADS = 4; +uint32_t MYSQL8_HG = get_env_int("TAP_MYSQL8_BACKEND_HG", 30); +uint32_t NUM_CLIENT_THREADS = get_env_int("TAP_NUM_CLIENT_THREADS", 4); using std::pair; using std::string; @@ -80,134 +81,6 @@ string my_escape_string(MYSQL* mysql, const string& q) { } } -bool is_empty_pass(const char* pass) { - return pass == nullptr || (pass && strlen(pass) == 0); -} - -bool match_pass(const char* p1, const char* p2) { - if (is_empty_pass(p1) && is_empty_pass(p2)) { - return true; - } else if (!is_empty_pass(p1) && !is_empty_pass(p2)) { - return strcmp(p1, p2) == 0; - } else { - return false; - } -} - -std::string unhex(const std::string& hex) { - if (hex.size() % 2) { 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; -} - -std::string hex(const std::string& 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(); -} - -struct free_deleter { - void operator()(void* x) { free(x); } - void operator()(const void* x) { free(const_cast(x)); } -}; - -template -using mf_unique_ptr = std::unique_ptr; - -mf_unique_ptr MF_CHAR_(const char* s) { - return mf_unique_ptr { s ? strdup(s) : nullptr }; -} - -struct user_def_t { - string name {}; - mf_unique_ptr prim_pass { nullptr }; - mf_unique_ptr addl_pass { nullptr }; - string auth {}; - bool rand_pass {}; - - user_def_t() {} - user_def_t(const string& name_) : name(name_) {} - - user_def_t( - const string& name_, - mf_unique_ptr prim_pass_, - mf_unique_ptr addl_pass_, - const string& auth_, - bool rand_pass_ = false - ) : - name(name_), - prim_pass(std::move(prim_pass_)), - addl_pass(std::move(addl_pass_)), - auth(auth_), - rand_pass(rand_pass_) - {} - - user_def_t(const user_def_t& other) : - name(other.name), auth(other.auth), rand_pass(other.rand_pass) - { - if (other.prim_pass) { - this->prim_pass = mf_unique_ptr(strdup(other.prim_pass.get())); - } else { - this->prim_pass = nullptr; - } - if (other.addl_pass) { - this->addl_pass = mf_unique_ptr(strdup(other.addl_pass.get())); - } else { - this->addl_pass = nullptr; - } - } - - void operator=(const user_def_t& other) { - this->name = other.name; - this->auth = other.auth; - this->rand_pass = other.rand_pass; - - if (other.prim_pass) { - this->prim_pass = mf_unique_ptr(strdup(other.prim_pass.get())); - } else { - this->prim_pass = nullptr; - } - if (other.addl_pass) { - this->addl_pass = mf_unique_ptr(strdup(other.addl_pass.get())); - } else { - this->addl_pass = nullptr; - } - } - - user_def_t(user_def_t&& other) : - name(other.name), - auth(other.auth), - rand_pass(other.rand_pass), - prim_pass(std::move(other.prim_pass)), - addl_pass(std::move(other.addl_pass)) - {} - - void operator=(user_def_t&& other) { - this->name = other.name; - this->auth = other.auth; - this->rand_pass = other.rand_pass; - this->prim_pass = std::move(other.prim_pass); - this->addl_pass = std::move(other.addl_pass); - } -}; - struct user_auth_stats_t { user_def_t user_def; uint64_t prim_pass_auths; @@ -217,21 +90,6 @@ struct user_auth_stats_t { using auth_reg_t = std::unordered_map; -struct user_creds_t { - user_def_t user_def; - mf_unique_ptr hashed_prim_pass_bin { nullptr }; - mf_unique_ptr hashed_addl_pass_bin { nullptr }; - - user_creds_t(const user_creds_t&) = delete; - user_creds_t(user_creds_t&&) noexcept(false) = default; - - void operator=(user_creds_t&& other) { - this->user_def = std::move(other.user_def); - this->hashed_prim_pass_bin = std::move(other.hashed_prim_pass_bin); - this->hashed_addl_pass_bin = std::move(other.hashed_addl_pass_bin); - } -}; - /** * @brief Extracts a nested JSON element from the supplied path. * @param j The JSON from which to extract the element. @@ -254,34 +112,6 @@ const nlohmann::json* get_nested_elem(const nlohmann::json& j, const vector -T get_nested_elem_val(const nlohmann::json& j, const std::vector& p, const T def_val) { - const nlohmann::json* next_step = get_nested_elem(j, p); - - try { - if (next_step != nullptr && !next_step->is_null()) { - return next_step->get(); - } else { - return def_val; - } - } catch (std::exception&) { - return def_val; - } -} - -struct test_conf_t { - /* @brief Default auth method announced by ProxySQL */ - string def_auth; - /* @brief Auth method requested by client */ - string req_auth; - /* @brief Wether to use hashed or 'clear_text' passwords. Implies a reload of 'mysql_users'. */ - bool hashed_pass; - /* @brief Wether to attempt auth under SSL conn or not. */ - bool use_ssl; - /* @brief Wether to attempt auth with compression enabled or not. */ - bool use_comp; -}; - struct sess_info_t { int sent_pkts; int recv_pkts; @@ -289,37 +119,6 @@ struct sess_info_t { int full_sha2_auth; }; -struct PASS_TYPE { - enum E { - UNKNOWN = 0, - PRIMARY, - ADDITIONAL, - }; -}; - -/** - * @brief Info from user defs (user_def_t), extracted for building 'test_creds_t'. - */ -struct creds_info_t { - PASS_TYPE::E type; - string auth; -}; - -/** - * @brief Info about user creds used in a particular test case. - * @details Multiple 'test_creds_t' are used while testing a single 'test_conf_t'. - */ -struct test_creds_t { - string name {}; - mf_unique_ptr pass { nullptr }; - creds_info_t info {}; - - test_creds_t(const string& name_, mf_unique_ptr pass_) : name(name_), pass(std::move(pass_)) {} - test_creds_t(const test_creds_t& other) : name(other.name), info(other.info) { - this->pass = other.pass ? MF_CHAR_(other.pass.get()) : nullptr; - } -}; - sess_info_t ext_sess_info(MYSQL* proxy) { sess_info_t sess_info { -3, -3, -3 }; nlohmann::json session { fetch_internal_session(proxy) }; @@ -348,319 +147,6 @@ auth_reg_t create_auth_reg(const vector& users_creds) { using chk_exp_scs_t = function; using chk_exp_seq_scs_t = function; -/** - * @brief Extract the auth strings (prim/addl) pass from an existing user. - * @param mysql Opened MySQL conn in which to perform the queries. - * @param user_def User definition; used to match by username. - * @return A pair of kind `{err_code, user_creds}`. - */ -pair ext_user_auth_strs(MYSQL* mysql, const user_def_t& user_def) { - const char* addl_pass { user_def.addl_pass.get() }; - const char* prim_pass { user_def.prim_pass.get() }; - - pair p_creds_res { EXIT_SUCCESS, user_creds_t {} }; - - const string ext_auths_query { - "SELECT HEX(authentication_string),json_value(user_attributes, '$.additional_password') " - "FROM mysql.user WHERE user='" + user_def.name + "'" - }; - - if (mysql_query_t(mysql, ext_auths_query.c_str())) { - fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql)); - return { EXIT_FAILURE, user_creds_t {} }; - } - - MYSQL_RES* myres = mysql_store_result(mysql); - MYSQL_ROW myrow = mysql_fetch_row(myres); - - if (myrow && myrow[0]) { - const char* p_addl_pass { myrow[1] }; - - if (p_addl_pass) { - p_creds_res = { - EXIT_SUCCESS, - user_creds_t { - user_def, - mf_unique_ptr { strdup(myrow[0]) }, - mf_unique_ptr { strdup(p_addl_pass) } - } - }; - } else { - // MySQL wont allow that 'aditional' pass for a backend user; we don't verify user attributes - // right now when loading to runtime; but we wont allow user to connect with empty - // 'additional' passwords either; - if (addl_pass && strlen(addl_pass) == 0) { - p_creds_res = { - EXIT_SUCCESS, - user_creds_t { - user_def, - mf_unique_ptr { strdup(myrow[0]) }, - mf_unique_ptr { strdup("") }, - } - }; - } else { - p_creds_res = { - EXIT_SUCCESS, - user_creds_t { - user_def, - mf_unique_ptr { strdup(myrow[0]) }, - mf_unique_ptr { nullptr }, - } - }; - } - } - } else { - diag("Empty result; no auth_string found for user user:'%s'", user_def.name.c_str()); - } - - mysql_free_result(myres); - - return p_creds_res; -} - -/** - * @brief TODO: Limitation ProxySQL doesn't allow a clear-text pass to start with '*'. See #1762. - * @param pass Password to check. - * @return 'true' if password is an invalid clear-text pass for ProxySQL. - */ -bool chk_inv_pass(const char* pass) { - if (is_empty_pass(pass)) { - return true; - } else { - if (strlen(pass)) { - return pass[0] == '*'; - } else { - return false; - } - } -} - -pair create_mysql_user_rnd_creds(MYSQL* mysql, const user_def_t& user_def) { - const string CREATE_USER { - "CREATE USER '" + user_def.name + "'@'%' IDENTIFIED WITH" - " '" + user_def.auth + "' BY RANDOM PASSWORD" - }; - const string DROP_USER { "DROP USER IF EXISTS '" + user_def.name + "'"}; - - mf_unique_ptr addl_text_pass { nullptr }; - - { - // NOTE: Required due to potential pass recreation - MYSQL_QUERY_T_(mysql, DROP_USER.c_str()); - MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); - - MYSQL_RES* myres = mysql_store_result(mysql); - MYSQL_ROW myrow = mysql_fetch_row(myres); - - if (myrow && myrow[2]) { - addl_text_pass = mf_unique_ptr(strdup(myrow[2])); - } - - mysql_free_result(myres); - } - - const string ALTER_USER { - "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED WITH" - " '" + user_def.auth + "' BY RANDOM PASSWORD RETAIN CURRENT PASSWORD" - }; - - mf_unique_ptr prim_text_pass {}; - - { - MYSQL_QUERY_T_(mysql, ALTER_USER.c_str()); - - MYSQL_RES* myres = mysql_store_result(mysql); - MYSQL_ROW myrow = mysql_fetch_row(myres); - - if (myrow && myrow[2]) { - prim_text_pass = mf_unique_ptr(strdup(myrow[2])); - } - - mysql_free_result(myres); - } - - return { - EXIT_SUCCESS, - user_def_t { - user_def.name, - std::move(prim_text_pass), - std::move(addl_text_pass), - user_def.auth, - user_def.rand_pass - } - }; -} - -pair create_mysql_user_exp_creds(MYSQL* mysql, const user_def_t& user_def) { - const char* addl_pass { user_def.addl_pass.get() }; - const char* prim_pass { user_def.prim_pass.get() }; - - if (addl_pass && strlen(addl_pass)) { - const string CREATE_USER { - "CREATE USER '" + user_def.name + "'@'%' IDENTIFIED WITH" - " '" + user_def.auth + "' BY '" + user_def.addl_pass.get() + "'" - }; - const string GRANT_USER_PRIVS { "GRANT ALL on *.* to '" + user_def.name + "'@'%'" }; - - MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); - MYSQL_QUERY_T_(mysql, GRANT_USER_PRIVS.c_str()); - - if (prim_pass && strlen(prim_pass)) { - const string ALTER_USER_RETAIN { - "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED BY '" + prim_pass + "'" - " RETAIN CURRENT PASSWORD" - }; - MYSQL_QUERY_T_(mysql, ALTER_USER_RETAIN.c_str()); - } else { - const string ALTER_USER_NO_RETAIN { - "ALTER USER '" + user_def.name + "'@'%' IDENTIFIED BY ''" - }; - // When new password is empty; retaining the previous one isn't possible - MYSQL_QUERY_T_(mysql, ALTER_USER_NO_RETAIN.c_str()); - } - } else { - string CREATE_USER { "CREATE USER '" + user_def.name + "'@'%'" }; - string GRANT_USER_PRIVS { "GRANT ALL on *.* to '" + user_def.name + "'@'%'" }; - - if (prim_pass) { - CREATE_USER += " IDENTIFIED WITH '" + user_def.auth + "' BY '" + prim_pass + "'"; - } - - MYSQL_QUERY_T_(mysql, CREATE_USER.c_str()); - MYSQL_QUERY_T_(mysql, GRANT_USER_PRIVS.c_str()); - } - - return { EXIT_SUCCESS, user_def }; -} - -pair create_mysql_user(MYSQL* mysql, const user_def_t& user_def) { - if (user_def.rand_pass) { - pair rnd_user_def {}; - - while ( - rnd_user_def.first == EXIT_SUCCESS && - (chk_inv_pass(rnd_user_def.second.prim_pass.get()) - || chk_inv_pass(rnd_user_def.second.addl_pass.get())) - ) { - rnd_user_def = create_mysql_user_rnd_creds(mysql, user_def); - } - - return rnd_user_def; - } else { - return create_mysql_user_exp_creds(mysql, user_def); - } -} - -pair create_backend_user(MYSQL* mysql, const user_def_t& user_def) { - const pair c_user_def { create_mysql_user(mysql, user_def) }; - - if (c_user_def.first == EXIT_SUCCESS) { - pair p_creds_res { ext_user_auth_strs(mysql, c_user_def.second) }; - - return p_creds_res; - } else { - return { EXIT_FAILURE, user_creds_t {} }; - } -} - -/** - * @brief Configure the backend MySQL 8 users for frontend-backend connection creation. - * @param mysql Already opened MySQL connection. - * @param backend_users The users to be created in the MySQL server. - * @return A pair of kind `{err_code, user_creds}`. - */ -pair> config_mysql_backend_users( - MYSQL* mysql, const vector& users_defs -) { - for (const auto& u : users_defs) { - MYSQL_QUERY_T__(mysql, ("DROP USER IF EXISTS '" + u.name + "'").c_str()); - } - - vector f_users_creds {}; - - for (const auto& user_def : users_defs) { - pair creds_res { create_backend_user(mysql, user_def) }; - - if (creds_res.first == EXIT_SUCCESS) { - f_users_creds.push_back(std::move(creds_res.second)); - } else { - return { EXIT_FAILURE, vector {} }; - } - } - - return { EXIT_SUCCESS, std::move(f_users_creds) }; -} - -int config_proxysql_users(MYSQL* admin, const test_conf_t& test_conf, const vector& users) { - const string DEF_HG { std::to_string(TAP_MYSQL8_BACKEND_HG) }; - - for (const auto& u : users) { - MYSQL_QUERY_T(admin, ("DELETE FROM mysql_users WHERE username='" + u.user_def.name + "'").c_str()); - } - - // Ensure cleanup of previously cached clear_text 'caching_sha2' passwords - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - - for (const auto& u : users) { - string attrs {}; - - // A user may not have an additional_password configured - if (u.user_def.addl_pass) { - string addl_pass {}; - - // NOTE: If the primary pass is empty, addl pass must be empty **by spec** - if (is_empty_pass(u.user_def.prim_pass.get())) { - addl_pass = {}; - } else if (test_conf.hashed_pass) { - const char* c_addl_pass { u.hashed_addl_pass_bin.get() }; - - if (c_addl_pass) { - addl_pass = c_addl_pass; - } - } else { - addl_pass = u.user_def.addl_pass.get(); - } - - const string hex_addl_pass { hex(addl_pass) }; - attrs = "{\"additional_password\": \"" + hex_addl_pass + "\"}"; - } - - string insert_query {}; - - if (u.user_def.prim_pass) { - const string prim_pass { - test_conf.hashed_pass && strlen(u.hashed_prim_pass_bin.get()) > 0 ? - "UNHEX('" + string { u.hashed_prim_pass_bin.get() } + "')" : - "'" + string { u.user_def.prim_pass.get() } + "'" - }; - - if (u.user_def.addl_pass) { - insert_query = { - "INSERT INTO mysql_users (username,password,default_hostgroup,attributes) " - "VALUES ('" + u.user_def.name + "'," + prim_pass + "," + DEF_HG + ",'" + attrs + "')" - }; - } else { - insert_query = { - "INSERT INTO mysql_users (username,password,default_hostgroup) " - "VALUES ('" + u.user_def.name + "'," + prim_pass + "," + DEF_HG + ")" - }; - } - } else { - insert_query = { - "INSERT INTO mysql_users (username,default_hostgroup,attributes) " - "VALUES ('" + u.user_def.name + "'," + DEF_HG + ",'" + attrs + "')" - }; - } - - MYSQL_QUERY_T(admin, insert_query.c_str()); - } - - MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); - - return EXIT_SUCCESS; -} - FILE* F_SSLKEYLOGFILE = nullptr; void ssl_keylog_callback(SSL*, const char* line) { @@ -671,33 +157,6 @@ void ssl_keylog_callback(SSL*, const char* line) { } } -string to_string(const test_conf_t& conf) { - return "{ " - "\"req_auth\":'" + conf.req_auth + "', " - "\"def_auth\":'" + conf.def_auth + "', " - "\"hashed_pass\":'" + std::to_string(conf.hashed_pass) + "', " - "\"use_ssl\":'" + std::to_string(conf.use_ssl) + "'" - " }"; -} - -string to_string(const PASS_TYPE::E type) { - if (type == PASS_TYPE::PRIMARY) { - return "PRIM"; - } else if (type == PASS_TYPE::ADDITIONAL) { - return "ADDL"; - } else { - return "UNKN"; - } -} - -string to_string(const test_creds_t& creds) { - return "{ " - "\"name\":'" + creds.name + "', " - "\"pass\":'" + (creds.pass ? creds.pass.get() : "NULL") + "', " - "\"type\":'" + to_string(creds.info.type) + "'" - " }"; -} - string to_string(const sess_info_t& sess) { return "{ " "\"recv_pkts\":'" + std::to_string(sess.recv_pkts) + "', " @@ -714,6 +173,16 @@ string to_string(const user_auth_stats_t& stats) { " }"; } +bool match_pass(const char* p1, const char* p2) { + if (is_empty_pass(p1) && is_empty_pass(p2)) { + return true; + } else if (!is_empty_pass(p1) && !is_empty_pass(p2)) { + return strcmp(p1, p2) == 0; + } else { + return false; + } +} + PASS_TYPE::E get_matching_pass(const user_creds_t& creds, const char* p) { const char* prim_pass { creds.user_def.prim_pass.get() }; const char* addl_pass { creds.user_def.addl_pass.get() }; @@ -990,38 +459,6 @@ bool chk_exp_scs_no_warmup(const test_conf_t& conf, const test_creds_t& creds) { return chk_exp_scs_basic(conf, creds) && !chk_exp_fail_except_no_warmup(conf, creds); } -/** - * @brief Gen all combinations of tests configs. - * @param def_auths Defaults auths to set for ProxySQL. - * @param req_auths Auth methods for client to request. - * @param hash_pass If passwords should be hashed or not. - * @param use_ssl If connection is started with SSL or not. - * @return Vector with the combinations. - */ -vector get_conf_combs( - const vector& def_auths, - const vector& req_auths, - const vector& hash_pass, - const vector& use_ssl, - const vector& use_comp -) { - vector confs {}; - - for (const auto& def_auth : def_auths) { - for (const auto& req_auth : req_auths) { - for (const auto& hashed : hash_pass) { - for (const auto& ssl : use_ssl) { - for (const auto& comp : use_comp) { - confs.push_back({def_auth, req_auth, hashed, ssl, comp}); - } - } - } - } - } - - return confs; -} - user_auth_stats_t update_auth_reg(MYSQL* mysql, const string& user, const char* pass, auth_reg_t& auth_reg) { user_auth_stats_t auth_info {}; @@ -1274,25 +711,25 @@ user_auth_stats_t check_auth_creds( } const vector backend_users { - { "dualpass1", MF_CHAR_(nullptr), MF_CHAR_(nullptr), "mysql_native_password" }, - { "dualpass2", MF_CHAR_(""), MF_CHAR_(nullptr), "mysql_native_password" }, - { "dualpass3", MF_CHAR_("newpass3"), MF_CHAR_(nullptr), "mysql_native_password" }, - { "dualpass4", MF_CHAR_(nullptr), MF_CHAR_(""), "mysql_native_password" }, - { "dualpass5", MF_CHAR_(""), MF_CHAR_(""), "mysql_native_password" }, - { "dualpass6", MF_CHAR_("newpass6"), MF_CHAR_(""), "mysql_native_password" }, - { "dualpass7", MF_CHAR_(""), MF_CHAR_("oldpass7"), "mysql_native_password" }, - { "dualpass8", MF_CHAR_(""), MF_CHAR_("oldpass8"), "mysql_native_password" }, - { "dualpass9", MF_CHAR_("newpass9"), MF_CHAR_("oldpass9"), "mysql_native_password" }, - - { "dualpass11", MF_CHAR_(nullptr), MF_CHAR_(nullptr), "caching_sha2_password" }, - { "dualpass12", MF_CHAR_(""), MF_CHAR_(nullptr), "caching_sha2_password" }, - { "dualpass13", MF_CHAR_("newpass13"), MF_CHAR_(nullptr), "caching_sha2_password" }, - { "dualpass14", MF_CHAR_(nullptr), MF_CHAR_(""), "caching_sha2_password" }, - { "dualpass15", MF_CHAR_(""), MF_CHAR_(""), "caching_sha2_password" }, - { "dualpass16", MF_CHAR_("newpass16"), MF_CHAR_(""), "caching_sha2_password" }, - { "dualpass17", MF_CHAR_(""), MF_CHAR_("oldpass17"), "caching_sha2_password" }, - { "dualpass18", MF_CHAR_(""), MF_CHAR_("oldpass18"), "caching_sha2_password" }, - { "dualpass19", MF_CHAR_("newpass19"), MF_CHAR_("oldpass19"), "caching_sha2_password" }, + { "dualpass1", MF_CHAR_(nullptr), MF_CHAR_(nullptr), "mysql_native_password", MYSQL8_HG }, + { "dualpass2", MF_CHAR_(""), MF_CHAR_(nullptr), "mysql_native_password", MYSQL8_HG }, + { "dualpass3", MF_CHAR_("newpass3"), MF_CHAR_(nullptr), "mysql_native_password", MYSQL8_HG }, + { "dualpass4", MF_CHAR_(nullptr), MF_CHAR_(""), "mysql_native_password", MYSQL8_HG }, + { "dualpass5", MF_CHAR_(""), MF_CHAR_(""), "mysql_native_password", MYSQL8_HG }, + { "dualpass6", MF_CHAR_("newpass6"), MF_CHAR_(""), "mysql_native_password", MYSQL8_HG }, + { "dualpass7", MF_CHAR_(""), MF_CHAR_("oldpass7"), "mysql_native_password", MYSQL8_HG }, + { "dualpass8", MF_CHAR_(""), MF_CHAR_("oldpass8"), "mysql_native_password", MYSQL8_HG }, + { "dualpass9", MF_CHAR_("newpass9"), MF_CHAR_("oldpass9"), "mysql_native_password", MYSQL8_HG }, + + { "dualpass11", MF_CHAR_(nullptr), MF_CHAR_(nullptr), "caching_sha2_password", MYSQL8_HG }, + { "dualpass12", MF_CHAR_(""), MF_CHAR_(nullptr), "caching_sha2_password", MYSQL8_HG }, + { "dualpass13", MF_CHAR_("newpass13"), MF_CHAR_(nullptr), "caching_sha2_password", MYSQL8_HG }, + { "dualpass14", MF_CHAR_(nullptr), MF_CHAR_(""), "caching_sha2_password", MYSQL8_HG }, + { "dualpass15", MF_CHAR_(""), MF_CHAR_(""), "caching_sha2_password", MYSQL8_HG }, + { "dualpass16", MF_CHAR_("newpass16"), MF_CHAR_(""), "caching_sha2_password", MYSQL8_HG }, + { "dualpass17", MF_CHAR_(""), MF_CHAR_("oldpass17"), "caching_sha2_password", MYSQL8_HG }, + { "dualpass18", MF_CHAR_(""), MF_CHAR_("oldpass18"), "caching_sha2_password", MYSQL8_HG }, + { "dualpass19", MF_CHAR_("newpass19"), MF_CHAR_("oldpass19"), "caching_sha2_password", MYSQL8_HG }, }; /** @@ -1423,14 +860,14 @@ int backend_conns_cleanup(MYSQL* admin) { diag("Cleaning up previous backend connections..."); MYSQL_QUERY(admin, ("UPDATE mysql_servers SET max_connections=0 " - "WHERE hostgroup_id=" + std::to_string(TAP_MYSQL8_BACKEND_HG)).c_str() + "WHERE hostgroup_id=" + std::to_string(MYSQL8_HG)).c_str() ); MYSQL_QUERY(admin, "LOAD MYSQL SERVERS TO RUNTIME"); // Wait for backend connection cleanup const string check_conn_cleanup { "SELECT IIF((SELECT SUM(ConnUsed + ConnFree) FROM stats.stats_mysql_connection_pool" - " WHERE hostgroup=" + std::to_string(TAP_MYSQL8_BACKEND_HG) + ")=0, 'TRUE', 'FALSE')" + " WHERE hostgroup=" + std::to_string(MYSQL8_HG) + ")=0, 'TRUE', 'FALSE')" }; int w_res = wait_for_cond(admin, check_conn_cleanup, 10); if (w_res != EXIT_SUCCESS) { @@ -1441,7 +878,7 @@ int backend_conns_cleanup(MYSQL* admin) { diag("Setup new connection limit max_connections='2000'"); MYSQL_QUERY(admin, ("UPDATE mysql_servers SET max_connections=2000 " - "WHERE hostgroup_id=" + std::to_string(TAP_MYSQL8_BACKEND_HG)).c_str() + "WHERE hostgroup_id=" + std::to_string(MYSQL8_HG)).c_str() ); MYSQL_QUERY(admin, "LOAD MYSQL SERVERS TO RUNTIME"); @@ -1522,7 +959,7 @@ int test_confs_creds_combs_frontend( std::vector client_threads {}; // Perform parallel fronted logging tests - for (uint32_t i = 0; i < TAP_NUM_CLIENT_THREADS; i++) { + for (uint32_t i = 0; i < NUM_CLIENT_THREADS; i++) { client_threads.push_back(std::thread([&cl, &p_conf_creds, &chk_exp_scs] () { for (const auto& creds : p_conf_creds.second) { test_creds_frontend(cl, p_conf_creds.first, creds, chk_exp_scs); @@ -1566,14 +1003,14 @@ int test_all_confs_creds( MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME"); std::vector client_thds {}; - std::vector thds_exp_sha2_auths(TAP_NUM_CLIENT_THREADS); + std::vector thds_exp_sha2_auths(NUM_CLIENT_THREADS); std::vector thds_auth_regs {}; - for (uint32_t i = 0; i < TAP_NUM_CLIENT_THREADS; i++) { + for (uint32_t i = 0; i < NUM_CLIENT_THREADS; i++) { thds_auth_regs.push_back(create_auth_reg(users_creds)); } - for (uint32_t i = 0; i < TAP_NUM_CLIENT_THREADS; i++) { + for (uint32_t i = 0; i < NUM_CLIENT_THREADS; i++) { client_thds.push_back( std::thread( [&cl, &conf, &thds_auth_regs, &thds_exp_sha2_auths, i, &users_creds, &tests_creds] () { @@ -1609,7 +1046,7 @@ int test_all_confs_creds( cthread.join(); } - for (uint32_t i = 0; i < TAP_NUM_CLIENT_THREADS; i++) { + for (uint32_t i = 0; i < NUM_CLIENT_THREADS; i++) { auth_reg_t& auth_reg { thds_auth_regs[i] }; for (const auto& auth_stats : auth_reg) { @@ -1622,7 +1059,7 @@ int test_all_confs_creds( } } - uint64_t exp_scs_total = non_warmup_tests_scs_count * TAP_NUM_CLIENT_THREADS; + uint64_t exp_scs_total = non_warmup_tests_scs_count * NUM_CLIENT_THREADS; uint64_t exp_full_sha2_total = exp_sha2_auths; ok( @@ -1648,9 +1085,6 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - TAP_MYSQL8_BACKEND_HG = get_env_int("TAP_MYSQL8_BACKEND_HG", 30); - TAP_NUM_CLIENT_THREADS = get_env_int("TAP_NUM_CLIENT_THREADS", 4); - MYSQL* mysql = mysql_init(NULL); if (!mysql_real_connect(mysql, cl.host, cl.mysql_username, cl.mysql_password, NULL, cl.mysql_port, NULL, 0)) { @@ -1734,7 +1168,7 @@ int main(int argc, char** argv) { // Sequential access tests; exercising full logic const vector all_conf_combs { - get_conf_combs(def_auths, req_auhts, hash_pass, use_ssl, use_comp) + get_auth_conf_combs(def_auths, req_auhts, hash_pass, use_ssl, use_comp) }; const auto scs_stats { count_exp_scs(all_conf_combs, cbres.second, tests_creds) };