MXS-2883: Handle AuthSwitchRequest packets
The backend didn't expect AuthSwitchRequest packets in response to the handshake response packets. This is allowed by the protocol and appears to happen with at least MySQL 8.0.
This commit is contained in:
parent
ef769573e4
commit
c18f9c6bd7
@ -510,7 +510,7 @@ bool gw_read_backend_handshake(DCB* dcb, GWBUF* buffer);
|
||||
mxs_auth_state_t gw_send_backend_auth(DCB* dcb);
|
||||
|
||||
/** Sends a response for an AuthSwitchRequest to the default auth plugin */
|
||||
int send_mysql_native_password_response(DCB* dcb);
|
||||
int send_mysql_native_password_response(DCB* dcb, GWBUF* buffer);
|
||||
|
||||
/** Sends an AuthSwitchRequest packet with the default auth plugin to the DCB */
|
||||
bool send_auth_switch_request_packet(DCB* dcb);
|
||||
|
@ -92,6 +92,11 @@ static bool auth_backend_extract(DCB* dcb, GWBUF* buf)
|
||||
rval = true;
|
||||
mba->state = MBA_AUTH_OK;
|
||||
}
|
||||
else if (mxs_mysql_get_command(buf) == MYSQL_REPLY_AUTHSWITCHREQUEST
|
||||
&& send_mysql_native_password_response(dcb, buf))
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mba->state = MBA_AUTH_FAILED;
|
||||
@ -124,6 +129,11 @@ static int auth_backend_authenticate(DCB* dcb)
|
||||
/** Authentication completed successfully */
|
||||
rval = MXS_AUTH_SUCCEEDED;
|
||||
}
|
||||
else if (mba->state == MBA_NEED_OK)
|
||||
{
|
||||
/** Sent AuthSwitchRequest response */
|
||||
rval = MXS_AUTH_INCOMPLETE;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
@ -784,14 +784,7 @@ static bool handle_auth_change_response(GWBUF* reply, MySQLProtocol* proto, DCB*
|
||||
* a new scramble for the re-authentication process.
|
||||
*/
|
||||
|
||||
// Load the new scramble into the protocol...
|
||||
gwbuf_copy_data(reply,
|
||||
5 + strlen(DEFAULT_MYSQL_AUTH_PLUGIN) + 1,
|
||||
GW_MYSQL_SCRAMBLE_SIZE,
|
||||
proto->scramble);
|
||||
|
||||
/// ... and use it to send the encrypted password to the server
|
||||
rval = send_mysql_native_password_response(dcb);
|
||||
rval = send_mysql_native_password_response(dcb, reply);
|
||||
}
|
||||
|
||||
return rval;
|
||||
|
@ -1009,19 +1009,30 @@ mxs_auth_state_t gw_send_backend_auth(DCB* dcb)
|
||||
return rval;
|
||||
}
|
||||
|
||||
int send_mysql_native_password_response(DCB* dcb)
|
||||
int send_mysql_native_password_response(DCB* dcb, GWBUF* reply)
|
||||
{
|
||||
MySQLProtocol* proto = (MySQLProtocol*) dcb->protocol;
|
||||
MYSQL_session local_session;
|
||||
gw_get_shared_session_auth_info(dcb, &local_session);
|
||||
|
||||
const char default_plugin_name[] = DEFAULT_MYSQL_AUTH_PLUGIN;
|
||||
|
||||
// Calculate the next sequence number
|
||||
uint8_t seqno = 0;
|
||||
gwbuf_copy_data(reply, 3, 1, &seqno);
|
||||
++seqno;
|
||||
|
||||
// Copy the new scramble. Skip packet header, command byte and null-terminated plugin name.
|
||||
gwbuf_copy_data(reply, MYSQL_HEADER_LEN + 1 + sizeof(default_plugin_name),
|
||||
sizeof(proto->scramble), proto->scramble);
|
||||
|
||||
uint8_t* curr_passwd = memcmp(local_session.client_sha1, null_client_sha1, MYSQL_SCRAMBLE_LEN) ?
|
||||
local_session.client_sha1 : null_client_sha1;
|
||||
|
||||
GWBUF* buffer = gwbuf_alloc(MYSQL_HEADER_LEN + GW_MYSQL_SCRAMBLE_SIZE);
|
||||
uint8_t* data = GWBUF_DATA(buffer);
|
||||
gw_mysql_set_byte3(data, GW_MYSQL_SCRAMBLE_SIZE);
|
||||
data[3] = 2; // This is the third packet after the COM_CHANGE_USER
|
||||
data[3] = seqno;
|
||||
calculate_hash(proto->scramble, curr_passwd, data + MYSQL_HEADER_LEN);
|
||||
|
||||
return dcb_write(dcb, buffer);
|
||||
@ -1060,7 +1071,7 @@ int gw_decode_mysql_server_handshake(MySQLProtocol* conn, uint8_t* payload)
|
||||
uint8_t scramble_data_1[GW_SCRAMBLE_LENGTH_323] = "";
|
||||
uint8_t scramble_data_2[GW_MYSQL_SCRAMBLE_SIZE - GW_SCRAMBLE_LENGTH_323] = "";
|
||||
uint8_t capab_ptr[4] = "";
|
||||
int scramble_len = 0;
|
||||
uint8_t scramble_len = 0;
|
||||
uint8_t mxs_scramble[GW_MYSQL_SCRAMBLE_SIZE] = "";
|
||||
int protocol_version = 0;
|
||||
|
||||
@ -1116,21 +1127,15 @@ int gw_decode_mysql_server_handshake(MySQLProtocol* conn, uint8_t* payload)
|
||||
// get scramble len
|
||||
if (payload[0] > 0)
|
||||
{
|
||||
scramble_len = payload[0] - 1;
|
||||
mxb_assert(scramble_len > GW_SCRAMBLE_LENGTH_323);
|
||||
mxb_assert(scramble_len <= GW_MYSQL_SCRAMBLE_SIZE);
|
||||
|
||||
if ((scramble_len < GW_SCRAMBLE_LENGTH_323)
|
||||
|| scramble_len > GW_MYSQL_SCRAMBLE_SIZE)
|
||||
{
|
||||
/* log this */
|
||||
return -2;
|
||||
}
|
||||
scramble_len = std::min(payload[0] - 1, GW_MYSQL_SCRAMBLE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
scramble_len = GW_MYSQL_SCRAMBLE_SIZE;
|
||||
}
|
||||
|
||||
mxb_assert(scramble_len > GW_SCRAMBLE_LENGTH_323);
|
||||
|
||||
// skip 10 zero bytes
|
||||
payload += 11;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user