MXS-1826: Respond with AuthSwitchRequest to COM_CHANGE_USER
To support a wider range of client connectors, MaxScale should respond with an AuthSwitchRequest packet to all COM_CHANGE_USER commands. Only MariaDB connectors understand the OK packet as the only response to a COM_CHANGE_USER but all connectors understand the AuthSwitchRequest packet.
This commit is contained in:
parent
66d7281d97
commit
e311b86800
@ -513,6 +513,9 @@ 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);
|
||||
|
||||
/** Sends an AuthSwitchRequest packet with the default auth plugin to the DCB */
|
||||
bool send_auth_switch_request_packet(DCB* dcb);
|
||||
|
||||
/** Write an OK packet to a DCB */
|
||||
int mxs_mysql_send_ok(DCB *dcb, int sequence, uint8_t affected_rows, const char* message);
|
||||
|
||||
|
@ -986,7 +986,14 @@ gw_read_normal_data(DCB *dcb, GWBUF *read_buffer, int nbytes_read)
|
||||
* the smallest version number. */
|
||||
qc_set_server_version(service_get_version(session->service, SERVICE_VERSION_MIN));
|
||||
|
||||
spec_com_res_t res = process_special_commands(dcb, read_buffer, nbytes_read);
|
||||
spec_com_res_t res = RES_CONTINUE;
|
||||
MySQLProtocol* proto = static_cast<MySQLProtocol*>(dcb->protocol);
|
||||
|
||||
if (!proto->changing_user)
|
||||
{
|
||||
res = process_special_commands(dcb, read_buffer, nbytes_read);
|
||||
}
|
||||
|
||||
int rval = 1;
|
||||
switch (res)
|
||||
{
|
||||
@ -1449,6 +1456,37 @@ void update_current_command(DCB* dcb, GWBUF* buffer)
|
||||
check_pool_candidate(dcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform re-authentication of the client
|
||||
*
|
||||
* @param session Client session
|
||||
* @param packetbuf Client's response to the AuthSwitchRequest
|
||||
*
|
||||
* @return True if the user is allowed access
|
||||
*/
|
||||
static bool reauthenticate_client(MXS_SESSION* session, GWBUF* packetbuf)
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
if (session->client_dcb->authfunc.reauthenticate)
|
||||
{
|
||||
MySQLProtocol* proto = (MySQLProtocol*)session->client_dcb->protocol;
|
||||
MYSQL_session* data = (MYSQL_session*)session->client_dcb->data;
|
||||
uint8_t client_sha1[MYSQL_SCRAMBLE_LEN] = {};
|
||||
uint8_t payload[gwbuf_length(packetbuf) - MYSQL_HEADER_LEN];
|
||||
gwbuf_copy_data(packetbuf, MYSQL_HEADER_LEN, sizeof(payload), payload);
|
||||
|
||||
int rc = session->client_dcb->authfunc.reauthenticate(session->client_dcb, data->user,
|
||||
payload, sizeof(payload),
|
||||
proto->scramble, sizeof(proto->scramble),
|
||||
client_sha1, sizeof(client_sha1));
|
||||
|
||||
rval = rc == MXS_AUTH_SUCCEEDED;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect if buffer includes partial mysql packet or multiple packets.
|
||||
* Store partial packet to dcb_readqueue. Send complete packets one by one
|
||||
@ -1480,11 +1518,15 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF
|
||||
if (packetbuf != NULL)
|
||||
{
|
||||
CHK_GWBUF(packetbuf);
|
||||
MySQLProtocol* proto = (MySQLProtocol*)session->client_dcb->protocol;
|
||||
|
||||
/**
|
||||
* Update the currently command being executed.
|
||||
*/
|
||||
update_current_command(session->client_dcb, packetbuf);
|
||||
if (!proto->changing_user)
|
||||
{
|
||||
update_current_command(session->client_dcb, packetbuf);
|
||||
}
|
||||
|
||||
if (rcap_type_required(capabilities, RCAP_TYPE_CONTIGUOUS_INPUT))
|
||||
{
|
||||
@ -1559,8 +1601,26 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF
|
||||
}
|
||||
}
|
||||
|
||||
/** Route query */
|
||||
rc = MXS_SESSION_ROUTE_QUERY(session, packetbuf);
|
||||
bool changed_user = false;
|
||||
|
||||
if (!proto->changing_user && proto->current_command == MXS_COM_CHANGE_USER)
|
||||
{
|
||||
changed_user = true;
|
||||
send_auth_switch_request_packet(session->client_dcb);
|
||||
}
|
||||
|
||||
if (proto->changing_user)
|
||||
{
|
||||
rc = reauthenticate_client(session, packetbuf) ? 1 : 0;
|
||||
gwbuf_free(packetbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/** Route query */
|
||||
rc = MXS_SESSION_ROUTE_QUERY(session, packetbuf);
|
||||
}
|
||||
|
||||
proto->changing_user = changed_user;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1404,6 +1404,23 @@ int send_mysql_native_password_response(DCB* dcb)
|
||||
return dcb_write(dcb, buffer);
|
||||
}
|
||||
|
||||
bool send_auth_switch_request_packet(DCB* dcb)
|
||||
{
|
||||
MySQLProtocol* proto = (MySQLProtocol*) dcb->protocol;
|
||||
const char plugin[] = DEFAULT_MYSQL_AUTH_PLUGIN;
|
||||
uint32_t len = 1 + sizeof(plugin) + GW_MYSQL_SCRAMBLE_SIZE;
|
||||
GWBUF* buffer = gwbuf_alloc(MYSQL_HEADER_LEN + len);
|
||||
|
||||
uint8_t* data = GWBUF_DATA(buffer);
|
||||
gw_mysql_set_byte3(data, len);
|
||||
data[3] = 1; // First response to the COM_CHANGE_USER
|
||||
data[MYSQL_HEADER_LEN] = MYSQL_REPLY_AUTHSWITCHREQUEST;
|
||||
memcpy(data + MYSQL_HEADER_LEN + 1, plugin, sizeof(plugin));
|
||||
memcpy(data + MYSQL_HEADER_LEN + 1 + sizeof(plugin), proto->scramble, GW_MYSQL_SCRAMBLE_SIZE);
|
||||
|
||||
return dcb_write(dcb, buffer) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode mysql server handshake
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user