Skip to content

Commit 29c0faa

Browse files
committed
[8.4] Merge branch 'percona/release-8.4.10-10' into 8.4
2 parents 427e1e7 + d76e81f commit 29c0faa

5 files changed

Lines changed: 110 additions & 4 deletions

File tree

MYSQL_VERSION

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
MYSQL_VERSION_MAJOR=8
22
MYSQL_VERSION_MINOR=4
3-
MYSQL_VERSION_PATCH=9
4-
MYSQL_VERSION_EXTRA=-9
3+
MYSQL_VERSION_PATCH=10
4+
MYSQL_VERSION_EXTRA=-10
55
MYSQL_VERSION_MATURITY="LTS"

router/src/routing/src/x_connection.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,7 @@ void MysqlRoutingXConnection::client_cap_set() {
14641464

14651465
if (switch_to_tls) {
14661466
bool continue_with_tls{false};
1467+
14671468
switch (source_ssl_mode()) {
14681469
case SslMode::kDisabled: {
14691470
continue_with_tls = false;
@@ -1518,6 +1519,11 @@ void MysqlRoutingXConnection::client_cap_set() {
15181519
discard_current_msg(src_channel, src_protocol);
15191520
std::vector<uint8_t> out_buf;
15201521

1522+
// The client tries to activate TLS when it is already enabled.
1523+
if (continue_with_tls && src_channel.ssl()) {
1524+
continue_with_tls = false;
1525+
}
1526+
15211527
if (!continue_with_tls) {
15221528
#ifdef DEBUG_IO
15231529
std::cerr << __LINE__ << ": "

router/tests/component/test_routing.cc

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,23 @@ static xcl::XError make_x_connection(
154154
password.c_str(), "");
155155
}
156156

157+
static xcl::XError make_x_raw_connection(
158+
XProtocolSession &session, const std::string &host, const uint16_t port,
159+
int64_t connect_timeout = 10000 /*10s*/) {
160+
session = xcl::create_session();
161+
xcl::XError err = setup_x_session(session, connect_timeout, "PREFERRED");
162+
if (err) return err;
163+
164+
return session->get_protocol().get_connection().connect(
165+
host, port, xcl::Internet_protocol::Any);
166+
}
167+
168+
static std::string format_xerror(const xcl::XError &e) {
169+
if (!e) return "no-error";
170+
171+
return "(code:" + std::to_string(e.error()) + ", message:" + e.what() + ")";
172+
}
173+
157174
#ifndef _WIN32
158175
static xcl::XError make_x_connection(XProtocolSession &session,
159176
const std::string &socket,
@@ -1941,6 +1958,78 @@ static size_t xproto_frame_encode(const T &msg, uint8_t msg_type,
19411958
return msg.SerializeToCodedStream(&codecouts);
19421959
}
19431960

1961+
/**
1962+
* @test Verify that repeated TLS activation requests are properly rejected
1963+
* and do not crash the Router.
1964+
*/
1965+
TEST_F(RouterRoutingTest, XProtocolRepeatedTlsUpgrade) {
1966+
const auto server_classic_port = port_pool_.get_next_available();
1967+
const auto server_x_port = port_pool_.get_next_available();
1968+
const auto router_x_rw_port = port_pool_.get_next_available();
1969+
1970+
const std::string json_stmts = get_data_dir().join("bootstrap_gr.js").str();
1971+
1972+
launch_mysql_server_mock(json_stmts, server_classic_port, EXIT_SUCCESS, false,
1973+
/*http_port*/ 0, server_x_port, /*module_prefix*/ "",
1974+
/*bind_address*/ "127.0.0.1",
1975+
/*wait_for_notify_ready*/ std::chrono::seconds(30),
1976+
/*enable_ssl*/ true);
1977+
1978+
const std::string routing_x_section = get_static_routing_section(
1979+
"x", router_x_rw_port, "", {server_x_port}, "x");
1980+
1981+
TempDirectory conf_dir("conf");
1982+
const std::string ssl_conf =
1983+
"client_ssl_mode=PREFERRED\n"
1984+
"server_ssl_mode=AS_CLIENT\n"
1985+
"client_ssl_key=" SSL_TEST_DATA_DIR
1986+
"/server-key-sha512.pem\n"
1987+
"client_ssl_cert=" SSL_TEST_DATA_DIR "/server-cert-sha512.pem";
1988+
std::string conf_file =
1989+
create_config_file(conf_dir.name(), routing_x_section, nullptr,
1990+
"mysqlrouter.conf", ssl_conf, true);
1991+
1992+
launch_router({"-c", conf_file});
1993+
1994+
Mysqlx::Connection::CapabilitiesSet switch_tls_msg;
1995+
auto *cap = switch_tls_msg.mutable_capabilities()->add_capabilities();
1996+
cap->set_name("tls");
1997+
auto *cap_value = cap->mutable_value();
1998+
cap_value->set_type(Mysqlx::Datatypes::Any_Type::Any_Type_SCALAR);
1999+
auto *cap_scalar = cap_value->mutable_scalar();
2000+
cap_scalar->set_type(Mysqlx::Datatypes::Scalar_Type::Scalar_Type_V_BOOL);
2001+
cap_scalar->set_v_bool(true);
2002+
2003+
XProtocolSession x_session;
2004+
const auto x_connect_error =
2005+
make_x_raw_connection(x_session, "127.0.0.1", router_x_rw_port);
2006+
ASSERT_FALSE(x_connect_error) << format_xerror(x_connect_error);
2007+
2008+
const auto x_cap_set_error =
2009+
x_session.get()->get_protocol().execute_set_capability(switch_tls_msg);
2010+
ASSERT_FALSE(x_cap_set_error) << format_xerror(x_cap_set_error);
2011+
2012+
const auto x_tls_error =
2013+
x_session.get()->get_protocol().get_connection().activate_tls();
2014+
2015+
ASSERT_FALSE(x_tls_error) << format_xerror(x_tls_error);
2016+
2017+
const auto x_cap_set2_error =
2018+
x_session.get()->get_protocol().execute_set_capability(switch_tls_msg);
2019+
ASSERT_EQ(x_cap_set2_error.error(), 5001) << format_xerror(x_cap_set2_error);
2020+
2021+
const auto x_login_error =
2022+
x_session.get()->get_protocol().execute_authenticate("root", "fake-pass",
2023+
"", "SHA256_MEMORY");
2024+
ASSERT_FALSE(x_login_error) << format_xerror(x_login_error);
2025+
2026+
// Router should still accept a fresh X Protocol connection after the loop.
2027+
XProtocolSession x_session2;
2028+
const auto res = make_x_connection(x_session2, "127.0.0.1", router_x_rw_port,
2029+
"root", "fake-pass");
2030+
EXPECT_THAT(res.error(), ::testing::AnyOf(0, 3159));
2031+
}
2032+
19442033
/**
19452034
* @test Check that if the x protocol client sends CONCLOSE message the Router
19462035
* replies with OK{bye!} message.

sql/auth/sql_authentication.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2411,9 +2411,20 @@ static bool read_client_connect_attrs(THD *thd, char **ptr,
24112411
size_t length, length_length;
24122412
char *ptr_save;
24132413

2414-
/* not enough bytes to hold the length */
2414+
/* Need one byte to determine the length-encoded field size. */
24152415
if (*max_bytes_available < 1) return true;
24162416

2417+
uchar *pos = (uchar *)*ptr;
2418+
DBUG_EXECUTE_IF("connect_attrs_too_short_3", *pos = 252;
2419+
*max_bytes_available = 2;);
2420+
DBUG_EXECUTE_IF("connect_attrs_too_short_4", *pos = 253;
2421+
*max_bytes_available = 3;);
2422+
DBUG_EXECUTE_IF("connect_attrs_too_short_9", *pos = 254;
2423+
*max_bytes_available = 8;);
2424+
2425+
const size_t required_length = (size_t)net_field_length_size(pos);
2426+
if (*max_bytes_available < required_length) return true;
2427+
24172428
/* read the length */
24182429
ptr_save = *ptr;
24192430
length = static_cast<size_t>(net_field_length_ll((uchar **)ptr));

storage/innobase/include/univ.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
5656
#define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH
5757

5858
#ifndef PERCONA_INNODB_VERSION
59-
#define PERCONA_INNODB_VERSION 9
59+
#define PERCONA_INNODB_VERSION 10
6060
#endif
6161

6262
/* The following is the InnoDB version as shown in

0 commit comments

Comments
 (0)