mirror of https://github.com/sysown/proxysql
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
7.1 KiB
235 lines
7.1 KiB
/**
|
|
* @file reg_test_4935-caching_sha2-t
|
|
* @brief Regression tests checking that info send during handshake like:
|
|
* - character_set
|
|
* - default_schema
|
|
* - ...
|
|
* Is preserved after authentication has taken place.
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#include "mysql.h"
|
|
|
|
#include "tap.h"
|
|
#include "command_line.h"
|
|
|
|
#include "utils.h"
|
|
#include "utils_auth.h"
|
|
|
|
using std::string;
|
|
using std::vector;
|
|
|
|
#define TAP_NAME "TAP_REG_TEST_4935_CACHING_SHA2___"
|
|
|
|
uint32_t MYSQL8_HG = get_env_int("TAP_MYSQL8_BACKEND_HG", 30);
|
|
|
|
const vector<user_def_t> backend_users {
|
|
{ "dualpass1", MF_CHAR_("newpass1"), MF_CHAR_(nullptr), "mysql_native_password", MYSQL8_HG, TAP_NAME"schema1" },
|
|
{ "dualpass2", MF_CHAR_("newpass2"), MF_CHAR_("oldpass2"), "mysql_native_password", MYSQL8_HG, TAP_NAME"schema2" },
|
|
|
|
{ "dualpass3", MF_CHAR_("newpass3"), MF_CHAR_(nullptr), "caching_sha2_password", MYSQL8_HG, TAP_NAME"schema1" },
|
|
{ "dualpass4", MF_CHAR_("newpass4"), MF_CHAR_("oldpass4"), "caching_sha2_password", MYSQL8_HG, TAP_NAME"schema2" },
|
|
};
|
|
|
|
const vector<test_creds_t> tests_creds {
|
|
{ "dualpass1", MF_CHAR_("newpass1"), { PASS_TYPE::PRIMARY, "mysql_native_password" } },
|
|
{ "dualpass2", MF_CHAR_("newpass2"), { PASS_TYPE::PRIMARY, "mysql_native_password" } },
|
|
{ "dualpass2", MF_CHAR_("oldpass2"), { PASS_TYPE::ADDITIONAL, "mysql_native_password" } },
|
|
|
|
{ "dualpass3", MF_CHAR_("newpass3"), { PASS_TYPE::PRIMARY, "caching_sha2_password" } },
|
|
{ "dualpass4", MF_CHAR_("newpass4"), { PASS_TYPE::PRIMARY, "caching_sha2_password" } },
|
|
{ "dualpass4", MF_CHAR_("oldpass4"), { PASS_TYPE::ADDITIONAL, "caching_sha2_password"} }
|
|
};
|
|
|
|
int config_proxy_conn(const CommandLine& cl, const test_conf_t& conf, MYSQL* proxy) {
|
|
unsigned long cflags = 0;
|
|
mysql_options(proxy, MYSQL_DEFAULT_AUTH, conf.req_auth.c_str());
|
|
|
|
if (conf.req_auth == "mysql_clear_password") {
|
|
bool enable_cleartext = true;
|
|
mysql_options(proxy, MYSQL_ENABLE_CLEARTEXT_PLUGIN, &enable_cleartext);
|
|
}
|
|
|
|
if (conf.use_ssl) {
|
|
mysql_ssl_set(proxy, NULL, NULL, NULL, NULL, NULL);
|
|
cflags |= CLIENT_SSL;
|
|
}
|
|
|
|
if (conf.use_comp) {
|
|
cflags |= CLIENT_COMPRESS;
|
|
}
|
|
|
|
return cflags;
|
|
}
|
|
|
|
vector<pair<string,string>> get_conns_opts_combs(
|
|
const vector<string> charsets, const vector<string> schemas
|
|
) {
|
|
vector<pair<string,string>> res {};
|
|
|
|
for (const string& charset : charsets) {
|
|
for (const string& schema : schemas) {
|
|
res.push_back({charset, schema});
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/**
|
|
* @brief Logic borrowed from 'test_auth_methods-t.cpp'
|
|
*/
|
|
bool exp_first_login_failure(const test_creds_t& creds, const test_conf_t& conf) {
|
|
return
|
|
(!conf.use_ssl && conf.hashed_pass && creds.info.auth == "caching_sha2_password")
|
|
||
|
|
(
|
|
!conf.use_ssl && conf.hashed_pass && creds.info.auth == "mysql_native_password"
|
|
&& conf.req_auth == "caching_sha2_password" && conf.def_auth == "caching_sha2_password"
|
|
)
|
|
||
|
|
(
|
|
conf.use_ssl && conf.hashed_pass && creds.info.auth == "caching_sha2_password"
|
|
&& conf.req_auth != "caching_sha2_password"
|
|
)
|
|
||
|
|
(
|
|
conf.use_ssl && conf.hashed_pass && creds.info.auth == "caching_sha2_password"
|
|
&& conf.req_auth == "caching_sha2_password" && conf.def_auth != "caching_sha2_password"
|
|
);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
plan(864);
|
|
|
|
CommandLine cl;
|
|
|
|
if (cl.getEnv()) {
|
|
diag("Failed to get the required environmental variables.");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
MYSQL* admin = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(admin));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
MYSQL* mysql = mysql_init(NULL);
|
|
|
|
if (!mysql_real_connect(mysql, cl.host, cl.mysql_username, cl.mysql_password, NULL, cl.mysql_port, NULL, 0)) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(mysql));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
|
|
const auto cbres { config_mysql_backend_users(mysql, ::backend_users) };
|
|
if (cbres.first) { return EXIT_FAILURE; }
|
|
|
|
mysql_close(mysql);
|
|
|
|
MYSQL_QUERY_T(admin, "SET mysql-have_ssl=1");
|
|
MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME");
|
|
|
|
const vector<string> def_auths {
|
|
"mysql_native_password",
|
|
"caching_sha2_password"
|
|
};
|
|
const vector<string> req_auhts {
|
|
"mysql_clear_password",
|
|
"mysql_native_password",
|
|
"caching_sha2_password"
|
|
};
|
|
const vector<bool> hash_pass { false, true };
|
|
const vector<bool> use_ssl { false, true };
|
|
const vector<bool> use_comp { false, true };
|
|
|
|
// Sequential access tests; exercising full logic
|
|
const vector<test_conf_t> all_conf_combs {
|
|
get_auth_conf_combs(def_auths, req_auhts, hash_pass, use_ssl, use_comp)
|
|
};
|
|
|
|
for (const test_conf_t& conf : all_conf_combs) {
|
|
diag("Starting new testing conf conf=\"%s\"", to_string(conf).c_str());
|
|
int cres = config_proxysql_users(admin, conf, cbres.second);
|
|
if (cres) { return EXIT_FAILURE; }
|
|
|
|
diag("%s", ("Switching to '" + conf.def_auth + "' on ProxySQL side").c_str());
|
|
MYSQL_QUERY_T(admin, ("SET mysql-default_authentication_plugin='" + conf.def_auth + "'").c_str());
|
|
MYSQL_QUERY_T(admin, "LOAD MYSQL VARIABLES TO RUNTIME");
|
|
MYSQL_QUERY_T(admin, "LOAD MYSQL USERS TO RUNTIME");
|
|
|
|
const vector<string> charsets { "latin2", "latin1" };
|
|
const vector<string> schemas { TAP_NAME"schema1", TAP_NAME"schema2" };
|
|
|
|
auto conns_opts { get_conns_opts_combs(charsets, schemas) };
|
|
|
|
for (const test_creds_t& creds : tests_creds) {
|
|
for (const auto& c_opts : conns_opts) {
|
|
if (exp_first_login_failure(creds, conf)) {
|
|
continue;
|
|
}
|
|
|
|
MYSQL* proxy = mysql_init(NULL);
|
|
int cflags = config_proxy_conn(cl, conf, proxy);
|
|
|
|
diag(
|
|
"Configuring conn opts charset=\"%s\" auth=\"%s\"",
|
|
c_opts.first.c_str(), creds.info.auth.c_str()
|
|
);
|
|
if (mysql_options(proxy, MYSQL_SET_CHARSET_NAME, c_opts.first.c_str())) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy));
|
|
return exit_status();
|
|
}
|
|
|
|
diag(
|
|
"Performing connection attempt creds=\"%s\" charset:\"%s\" schema=\"%s\"",
|
|
to_string(creds).c_str(), c_opts.first.c_str(), c_opts.second.c_str()
|
|
);
|
|
if (
|
|
!mysql_real_connect(
|
|
proxy,
|
|
cl.host,
|
|
creds.name.c_str(),
|
|
creds.pass.get(),
|
|
c_opts.second.c_str(),
|
|
cl.port,
|
|
NULL,
|
|
cflags
|
|
)
|
|
) {
|
|
fprintf(stderr, "File %s, line %d, Error: %s\n", __FILE__, __LINE__, mysql_error(proxy));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
int rc = mysql_query_t(proxy, "SELECT @@character_set_client, database()");
|
|
if (rc) {
|
|
diag("Query failed, unable to continue testing error=\"%s\"", mysql_error(proxy));
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
MYSQL_RES* myres = mysql_store_result(proxy);
|
|
MYSQL_ROW myrow = mysql_fetch_row(myres);
|
|
|
|
ok(
|
|
strcasecmp(c_opts.first.c_str(), myrow[0]) == 0
|
|
&& strcasecmp(c_opts.second.c_str(), myrow[1]) == 0,
|
|
"Conn properties should match expected "
|
|
"exp_charset=\"%s\" act_charset=\"%s\" exp_db=\"%s\" act_db=\"%s\"",
|
|
c_opts.first.c_str(), myrow[0], c_opts.second.c_str(), myrow[1]
|
|
);
|
|
|
|
mysql_free_result(myres);
|
|
mysql_close(proxy);
|
|
}
|
|
}
|
|
}
|
|
|
|
mysql_close(admin);
|
|
|
|
return exit_status();
|
|
}
|