Skip to content

Commit cb9eb90

Browse files
committed
WL#16192 remove sha256_password
sha256_password is deprecated by MySQL Server 5.7. Change ====== - removed support for sha256_password in the authentication and change_user. - removed tests that check the sha256_password support. - added support to the mock-server to require a authentication "method_name". - in mock-server, aligned parameter name of handshake() - added mysql_server_mock_spawner() to component-tests Change-Id: Ic7edc368c34d87ba9feca346b2236ae3864eddb2
1 parent f4b2773 commit cb9eb90

30 files changed

+532
-1931
lines changed

router/src/mock_server/src/authentication.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ namespace impl {
3939
* - mysql_native_password
4040
* - message-digest: SHA1
4141
* - inner message-digest-order: nonce + double_hashed_password
42-
* - caching_sha256_password
42+
* - caching_sha2_password
4343
* - message-digest: SHA256
4444
* - inner message-digest-order: double_hashed_password + nonce
4545
*

router/src/mock_server/src/classic_mock_session.cc

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,65 @@ void MySQLServerMockSessionClassic::client_greeting() {
254254
protocol_.auth_method_name(MySQLNativePassword::name);
255255
}
256256

257+
auto handshake_data_res =
258+
json_reader_->handshake(false /* not is_greeting */);
259+
if (!handshake_data_res) {
260+
protocol_.encode_error(handshake_data_res.error());
261+
262+
send_response_then_disconnect();
263+
264+
return;
265+
}
266+
267+
handshake_data_ = *handshake_data_res;
268+
269+
if (handshake_data_->username.has_value()) {
270+
if (handshake_data_->username.value() != protocol_.username()) {
271+
protocol_.encode_error(
272+
{ER_ACCESS_DENIED_ERROR, // 1045
273+
"Access Denied for user '" + protocol_.username() + "'@'localhost'",
274+
"28000"});
275+
276+
send_response_then_disconnect();
277+
278+
return;
279+
}
280+
}
281+
282+
if (handshake_data_->auth_method_name.has_value()) {
283+
if (protocol_.auth_method_name() != *handshake_data_->auth_method_name) {
284+
protocol_.auth_method_name(*handshake_data_->auth_method_name);
285+
286+
// auth_response() should be empty
287+
//
288+
// ask for the real full authentication
289+
protocol_.auth_method_data(std::string(20, 'a'));
290+
291+
protocol_.encode_auth_switch_message(
292+
{protocol_.auth_method_name(),
293+
protocol_.auth_method_data() + std::string(1, '\0')});
294+
295+
protocol_.async_send([this, to_send = protocol_.send_buffer().size()](
296+
std::error_code ec, size_t transferred) {
297+
if (ec) {
298+
if (ec != std::errc::operation_canceled) {
299+
log_warning("send auto result failed: %s", ec.message().c_str());
300+
}
301+
302+
disconnect();
303+
return;
304+
}
305+
306+
if (to_send < transferred) {
307+
std::terminate();
308+
} else {
309+
auth_switched();
310+
}
311+
});
312+
return;
313+
}
314+
}
315+
257316
if (protocol_.auth_method_name() == CachingSha2Password::name) {
258317
// auth_response() should be empty
259318
//
@@ -691,25 +750,17 @@ stdx::expected<std::string, std::error_code> cert_get_issuer_name(X509 *cert) {
691750

692751
stdx::expected<void, ErrorResponse> MySQLServerMockSessionClassic::authenticate(
693752
const std::vector<uint8_t> &client_auth_method_data) {
694-
auto handshake_data_res =
695-
json_reader_->handshake(false /* not is_greeting */);
696-
if (!handshake_data_res) {
697-
return stdx::unexpected(handshake_data_res.error());
753+
if (!handshake_data_) {
754+
return stdx::unexpected(ErrorResponse{
755+
ER_ACCESS_DENIED_ERROR, // 1045
756+
"Access Denied for user '" + protocol_.username() + "'@'localhost'",
757+
"28000"});
698758
}
699759

700-
auto handshake = handshake_data_res.value();
701-
702-
if (handshake.username.has_value()) {
703-
if (handshake.username.value() != protocol_.username()) {
704-
return stdx::unexpected(ErrorResponse{
705-
ER_ACCESS_DENIED_ERROR, // 1045
706-
"Access Denied for user '" + protocol_.username() + "'@'localhost'",
707-
"28000"});
708-
}
709-
}
760+
const auto &handshake = *handshake_data_;
710761

711762
if (handshake.password.has_value()) {
712-
if (!protocol_.authenticate(
763+
if (!ProtocolBase::authenticate(
713764
protocol_.auth_method_name(), protocol_.auth_method_data(),
714765
handshake.password.value(), client_auth_method_data)) {
715766
return stdx::unexpected(ErrorResponse{
@@ -720,7 +771,7 @@ stdx::expected<void, ErrorResponse> MySQLServerMockSessionClassic::authenticate(
720771
}
721772

722773
if (handshake.cert_required) {
723-
auto *ssl = protocol_.ssl();
774+
const auto *ssl = protocol_.ssl();
724775

725776
std::unique_ptr<X509, decltype(&X509_free)> client_cert{
726777
SSL_get_peer_certificate(ssl), &X509_free};

router/src/mock_server/src/classic_mock_session.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class MySQLServerMockSessionClassic : public MySQLServerMockSession {
124124
MySQLClassicProtocol protocol_;
125125

126126
bool with_tls_{false};
127+
128+
std::optional<StatementReaderBase::handshake_data> handshake_data_;
127129
};
128130

129131
} // namespace server_mock

router/src/mock_server/src/duktape_statement_reader.cc

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,7 @@ DuktapeStatementReader::handshake(bool is_greeting) {
10841084
stdx::expected<classic_protocol::message::server::Greeting, std::error_code>
10851085
server_greeting_res = default_server_greeting();
10861086
std::chrono::microseconds exec_time{};
1087+
std::optional<std::string> auth_method_name;
10871088
std::error_code ec{};
10881089

10891090
duk_get_prop_string(ctx, -1, "handshake");
@@ -1160,6 +1161,15 @@ DuktapeStatementReader::handshake(bool is_greeting) {
11601161
duk_pop(ctx);
11611162
}
11621163
duk_pop(ctx);
1164+
1165+
duk_get_prop_literal(ctx, -1, "method_name");
1166+
if (duk_is_string(ctx, -1)) {
1167+
auth_method_name = std::string(duk_to_string(ctx, -1));
1168+
} else if (!duk_is_undefined(ctx, -1)) {
1169+
ec = make_error_code(std::errc::invalid_argument);
1170+
}
1171+
duk_pop(ctx);
1172+
11631173
} else if (!duk_is_undefined(ctx, -1)) {
11641174
ec = make_error_code(std::errc::invalid_argument);
11651175
}
@@ -1181,8 +1191,10 @@ DuktapeStatementReader::handshake(bool is_greeting) {
11811191
}
11821192

11831193
return handshake_data{
1184-
*server_greeting_res, username, password, cert_required,
1185-
cert_subject, cert_issuer, exec_time};
1194+
*server_greeting_res, username, password,
1195+
auth_method_name, std::nullopt, cert_required,
1196+
cert_subject, cert_issuer, exec_time,
1197+
};
11861198
}
11871199

11881200
// @pre on the stack is an object

router/src/mock_server/src/duktape_statement_reader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ class DuktapeStatementReader : public StatementReaderBase {
112112
std::vector<AsyncNotice> get_async_notices() override;
113113

114114
stdx::expected<handshake_data, ErrorResponse> handshake(
115-
bool with_tls) override;
115+
bool is_greeting) override;
116116

117117
private:
118118
stdx::expected<classic_protocol::message::server::Greeting, std::error_code>

router/src/mock_server/src/protocol_base.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ bool ProtocolBase::authenticate(const std::string &auth_method_name,
9797
} else {
9898
// there is also
9999
// - old_password (3.23, 4.0)
100-
// - sha256_password (5.6, ...)
100+
// - sha256_password (5.6, 8.3)
101101
// - windows_authentication (5.6, ...)
102102
return false;
103103
}

router/src/mock_server/src/statement_reader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ class StatementReaderBase {
358358

359359
std::optional<std::string> username;
360360
std::optional<std::string> password;
361+
std::optional<std::string> auth_method_name;
362+
std::optional<std::string> auth_method_data;
361363
bool cert_required{false};
362364
std::optional<std::string> cert_subject;
363365
std::optional<std::string> cert_issuer;

router/src/router/tests/test_log_filter.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ TEST_F(LogFilterTest, IsPasswordHiddenWhenPatternSameAsReplacement) {
108108

109109
TEST_F(LogFilterTest, IsMoreThenOneGroupHidden) {
110110
const std::string statement =
111-
"ALTER USER \'jeffrey\'@\'localhost\' IDENTIFIED WITH sha256_password BY "
111+
"ALTER USER \'jeffrey\'@\'localhost\' IDENTIFIED WITH "
112+
"mysql_native_password BY "
112113
"\'new_password\' PASSWORD EXPIRE INTERVAL 180 DAY";
113114
const std::string expected_result =
114115
"ALTER USER \'jeffrey\'@\'localhost\' IDENTIFIED WITH *** BY *** "

router/src/routing/src/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ ADD_LIBRARY(routing SHARED
6464
classic_auth_cleartext.cc
6565
classic_auth_caching_sha2.cc
6666
classic_auth_native.cc
67-
classic_auth_sha256_password.cc
6867
classic_command.cc
6968
classic_connect.cc
7069
classic_flow.cc
@@ -76,7 +75,6 @@ ADD_LIBRARY(routing SHARED
7675
classic_auth_caching_sha2_forwarder.cc
7776
classic_auth_forwarder.cc
7877
classic_auth_native_forwarder.cc
79-
classic_auth_sha256_password_forwarder.cc
8078
classic_binlog_dump_forwarder.cc
8179
classic_change_user_forwarder.cc
8280
classic_clone_forwarder.cc
@@ -103,7 +101,6 @@ ADD_LIBRARY(routing SHARED
103101
classic_auth_cleartext_sender.cc
104102
classic_auth_caching_sha2_sender.cc
105103
classic_auth_native_sender.cc
106-
classic_auth_sha256_password_sender.cc
107104
classic_change_user_sender.cc
108105
# classic_greeting_sender.cc
109106
classic_init_schema_sender.cc

router/src/routing/src/classic_auth_forwarder.cc

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@
3838
#include "classic_auth_cleartext_sender.h"
3939
#include "classic_auth_native_forwarder.h"
4040
#include "classic_auth_native_sender.h"
41-
#include "classic_auth_sha256_password_forwarder.h"
42-
#include "classic_auth_sha256_password_sender.h"
4341
#include "classic_frame.h"
4442
#include "harness_assert.h"
4543
#include "hexify.h"
@@ -244,6 +242,8 @@ AuthGenericForwarder::error() {
244242
return Result::Again;
245243
}
246244

245+
// AuthForwarder
246+
247247
stdx::expected<Processor::Result, std::error_code> AuthForwarder::process() {
248248
switch (stage()) {
249249
case Stage::Init:
@@ -299,10 +299,7 @@ stdx::expected<Processor::Result, std::error_code> AuthForwarder::init() {
299299
Tracer::Event().stage("auth::forwarder::direct: " + auth_method_name));
300300
}
301301

302-
if (auth_method_name == AuthSha256Password::kName) {
303-
connection()->push_processor(std::make_unique<AuthSha256Forwarder>(
304-
connection(), initial_auth_method_data, true));
305-
} else if (auth_method_name == AuthCachingSha2Password::kName) {
302+
if (auth_method_name == AuthCachingSha2Password::kName) {
306303
connection()->push_processor(std::make_unique<AuthCachingSha2Forwarder>(
307304
connection(), initial_auth_method_data, true,
308305
client_requested_full_auth_));
@@ -313,8 +310,17 @@ stdx::expected<Processor::Result, std::error_code> AuthForwarder::init() {
313310
connection()->push_processor(std::make_unique<AuthCleartextForwarder>(
314311
connection(), initial_auth_method_data, true));
315312
} else {
316-
connection()->push_processor(std::make_unique<AuthGenericForwarder>(
317-
connection(), auth_method_name, initial_auth_method_data, true));
313+
// an unknown auth-method.
314+
auto send_res = ClassicFrame::send_msg<
315+
classic_protocol::borrowed::message::server::Error>(
316+
dst_conn, {2059, // CR_AUTH_PLUGIN_CANNOT_LOAD
317+
"Authentication plugin '" + auth_method_name +
318+
"' cannot be loaded: not supported by router",
319+
"28000"});
320+
if (!send_res) return send_client_failed(send_res.error());
321+
322+
stage(Stage::Done);
323+
return Result::SendToClient;
318324
}
319325

320326
stage(Stage::Response);
@@ -350,18 +356,7 @@ AuthForwarder::auth_method_switch() {
350356
// invalidates 'msg'
351357
discard_current_msg(src_conn);
352358

353-
if (auth_method_name == AuthSha256Password::kName) {
354-
dst_protocol.auth_method_name(auth_method_name);
355-
dst_protocol.auth_method_data(auth_method_data);
356-
357-
if (dst_protocol.password().has_value()) {
358-
connection()->push_processor(std::make_unique<AuthSha256Sender>(
359-
connection(), auth_method_data, dst_protocol.password().value()));
360-
} else {
361-
connection()->push_processor(std::make_unique<AuthSha256Forwarder>(
362-
connection(), auth_method_data, false));
363-
}
364-
} else if (auth_method_name == AuthCachingSha2Password::kName) {
359+
if (auth_method_name == AuthCachingSha2Password::kName) {
365360
dst_protocol.auth_method_name(auth_method_name);
366361
dst_protocol.auth_method_data(auth_method_data);
367362

@@ -399,8 +394,16 @@ AuthForwarder::auth_method_switch() {
399394
dst_protocol.auth_method_name(auth_method_name);
400395
dst_protocol.auth_method_data(auth_method_data);
401396

402-
connection()->push_processor(std::make_unique<AuthGenericForwarder>(
403-
connection(), auth_method_name, auth_method_data));
397+
auto send_res = ClassicFrame::send_msg<
398+
classic_protocol::borrowed::message::server::Error>(
399+
dst_conn, {2059, // CR_AUTH_PLUGIN_CANNOT_LOAD
400+
"Authentication plugin '" + auth_method_name +
401+
"' cannot be loaded: not supported by router",
402+
"28000"});
403+
if (!send_res) return send_client_failed(send_res.error());
404+
405+
stage(Stage::Done);
406+
return Result::SendToClient;
404407
}
405408

406409
stage(Stage::Response);

router/src/routing/src/classic_auth_sha256_password.cc

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)