MXS-1628: Respond with correct error to malformed packets
If the client sent a malformed authentication response packet, MaxScale would interpret that as failed authentication.
This commit is contained in:
@ -99,6 +99,7 @@ typedef struct mxs_authenticator
|
|||||||
#define MXS_AUTH_INCOMPLETE 4 /**< Authentication is not yet complete */
|
#define MXS_AUTH_INCOMPLETE 4 /**< Authentication is not yet complete */
|
||||||
#define MXS_AUTH_SSL_INCOMPLETE 5 /**< SSL connection is not yet complete */
|
#define MXS_AUTH_SSL_INCOMPLETE 5 /**< SSL connection is not yet complete */
|
||||||
#define MXS_AUTH_NO_SESSION 6
|
#define MXS_AUTH_NO_SESSION 6
|
||||||
|
#define MXS_AUTH_BAD_HANDSHAKE 7 /**< Malformed client packet */
|
||||||
|
|
||||||
/** Return values for the loadusers entry point */
|
/** Return values for the loadusers entry point */
|
||||||
#define MXS_AUTH_LOADUSERS_OK 0 /**< Users loaded successfully */
|
#define MXS_AUTH_LOADUSERS_OK 0 /**< Users loaded successfully */
|
||||||
|
@ -475,11 +475,21 @@ mysql_auth_set_client_data(
|
|||||||
if (client_auth_packet_size > MYSQL_AUTH_PACKET_BASE_SIZE)
|
if (client_auth_packet_size > MYSQL_AUTH_PACKET_BASE_SIZE)
|
||||||
{
|
{
|
||||||
/* Should have a username */
|
/* Should have a username */
|
||||||
char *first_letter_of_username = (char *)(client_auth_packet + MYSQL_AUTH_PACKET_BASE_SIZE);
|
uint8_t* name = client_auth_packet + MYSQL_AUTH_PACKET_BASE_SIZE;
|
||||||
int user_length = strlen(first_letter_of_username);
|
uint8_t* end = client_auth_packet + sizeof(client_auth_packet);
|
||||||
|
int user_length = 0;
|
||||||
|
|
||||||
ss_dassert(client_auth_packet_size > (MYSQL_AUTH_PACKET_BASE_SIZE + user_length)
|
while (name < end && *name)
|
||||||
&& user_length <= MYSQL_USER_MAXLEN);
|
{
|
||||||
|
name++;
|
||||||
|
user_length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == end)
|
||||||
|
{
|
||||||
|
// The name is not null terminated
|
||||||
|
return MXS_AUTH_BAD_HANDSHAKE;
|
||||||
|
}
|
||||||
|
|
||||||
if (client_auth_packet_size > (MYSQL_AUTH_PACKET_BASE_SIZE + user_length + 1))
|
if (client_auth_packet_size > (MYSQL_AUTH_PACKET_BASE_SIZE + user_length + 1))
|
||||||
{
|
{
|
||||||
@ -487,14 +497,14 @@ mysql_auth_set_client_data(
|
|||||||
packet_length_used = MYSQL_AUTH_PACKET_BASE_SIZE + user_length + 1;
|
packet_length_used = MYSQL_AUTH_PACKET_BASE_SIZE + user_length + 1;
|
||||||
/* We should find an authentication token next */
|
/* We should find an authentication token next */
|
||||||
/* One byte of packet is the length of authentication token */
|
/* One byte of packet is the length of authentication token */
|
||||||
memcpy(&client_data->auth_token_len,
|
client_data->auth_token_len = client_auth_packet[packet_length_used];
|
||||||
client_auth_packet + packet_length_used, 1);
|
|
||||||
|
|
||||||
if (client_auth_packet_size >
|
if (client_auth_packet_size >
|
||||||
(packet_length_used + client_data->auth_token_len))
|
(packet_length_used + client_data->auth_token_len))
|
||||||
{
|
{
|
||||||
/* Packet is large enough for authentication token */
|
client_data->auth_token = (uint8_t*)MXS_MALLOC(client_data->auth_token_len);
|
||||||
if (NULL != (client_data->auth_token = (uint8_t *)MXS_MALLOC(client_data->auth_token_len)))
|
|
||||||
|
if (client_data->auth_token)
|
||||||
{
|
{
|
||||||
/* The extra 1 is for the token length byte, just extracted*/
|
/* The extra 1 is for the token length byte, just extracted*/
|
||||||
memcpy(client_data->auth_token,
|
memcpy(client_data->auth_token,
|
||||||
@ -510,9 +520,13 @@ mysql_auth_set_client_data(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Packet was too small to contain authentication token */
|
/* Packet was too small to contain authentication token */
|
||||||
return MXS_AUTH_FAILED;
|
return MXS_AUTH_BAD_HANDSHAKE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return MXS_AUTH_BAD_HANDSHAKE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return MXS_AUTH_SUCCEEDED;
|
return MXS_AUTH_SUCCEEDED;
|
||||||
}
|
}
|
||||||
|
@ -1132,6 +1132,10 @@ mysql_client_auth_error_handling(DCB *dcb, int auth_val, int packet_number)
|
|||||||
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str);
|
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MXS_AUTH_BAD_HANDSHAKE:
|
||||||
|
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "08S01", "Bad handshake");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, "
|
MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, "
|
||||||
"state unrecognized.", pthread_self(), dcb->fd);
|
"state unrecognized.", pthread_self(), dcb->fd);
|
||||||
|
Reference in New Issue
Block a user