Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
markus456 committed May 10, 2018
1 parent 11e20f9 commit 07bc432
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/maxscale/authenticator.h
Expand Up @@ -99,6 +99,7 @@ typedef struct mxs_authenticator
#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_NO_SESSION 6
#define MXS_AUTH_BAD_HANDSHAKE 7 /**< Malformed client packet */

/** Return values for the loadusers entry point */
#define MXS_AUTH_LOADUSERS_OK 0 /**< Users loaded successfully */
Expand Down
32 changes: 23 additions & 9 deletions server/modules/authenticator/MySQLAuth/mysql_auth.c
Expand Up @@ -475,26 +475,36 @@ mysql_auth_set_client_data(
if (client_auth_packet_size > MYSQL_AUTH_PACKET_BASE_SIZE)
{
/* Should have a username */
char *first_letter_of_username = (char *)(client_auth_packet + MYSQL_AUTH_PACKET_BASE_SIZE);
int user_length = strlen(first_letter_of_username);
uint8_t* name = client_auth_packet + MYSQL_AUTH_PACKET_BASE_SIZE;
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)
&& user_length <= MYSQL_USER_MAXLEN);
while (name < end && *name)
{
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))
{
/* Extra 1 is for the terminating null after user name */
packet_length_used = MYSQL_AUTH_PACKET_BASE_SIZE + user_length + 1;
/* We should find an authentication token next */
/* One byte of packet is the length of authentication token */
memcpy(&client_data->auth_token_len,
client_auth_packet + packet_length_used, 1);
client_data->auth_token_len = client_auth_packet[packet_length_used];

if (client_auth_packet_size >
(packet_length_used + client_data->auth_token_len))
{
/* Packet is large enough for authentication token */
if (NULL != (client_data->auth_token = (uint8_t *)MXS_MALLOC(client_data->auth_token_len)))
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*/
memcpy(client_data->auth_token,
Expand All @@ -510,9 +520,13 @@ mysql_auth_set_client_data(
else
{
/* 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;
}
Expand Down
4 changes: 4 additions & 0 deletions server/modules/protocol/MySQL/MySQLClient/mysql_client.c
Expand Up @@ -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);
break;

case MXS_AUTH_BAD_HANDSHAKE:
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "08S01", "Bad handshake");
break;

default:
MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, "
"state unrecognized.", pthread_self(), dcb->fd);
Expand Down

0 comments on commit 07bc432

Please sign in to comment.