MXS-1628: Prevent out-of-bounds read on bad handshake packet

If the client would send a malformed handshake packet, out-of-bounds
memory could be read.
This commit is contained in:
Markus Mäkelä
2018-05-10 13:16:07 +03:00
parent d7ca5f5b5d
commit 9c8cd07a00

View File

@ -542,6 +542,34 @@ int gw_read_client_event(DCB* dcb)
return return_code;
}
/**
* Get length of a null-terminated string
*
* @param str String to measure
* @param len Maximum length to read
*
* @return Length of @c str or -1 if the string is not null-terminated
*/
static int get_zstr_len(const char* str, int len)
{
const char* end = str + len;
int slen = 0;
while (str < end && *str)
{
str++;
slen++;
}
if (str == end)
{
// The string is not null terminated
slen = -1;
}
return slen;
}
/**
* @brief Store client connection information into the DCB
* @param dcb Client DCB
@ -570,22 +598,28 @@ static void store_client_information(DCB *dcb, GWBUF *buffer)
if (len > MYSQL_AUTH_PACKET_BASE_SIZE)
{
strcpy(ses->user, (char*)data + MYSQL_AUTH_PACKET_BASE_SIZE);
const char* username = (const char*)data + MYSQL_AUTH_PACKET_BASE_SIZE;
int userlen = get_zstr_len(username, len - MYSQL_AUTH_PACKET_BASE_SIZE);
if (userlen != -1 && (int)sizeof(ses->user) > userlen)
{
strcpy(ses->user, username);
}
if (proto->client_capabilities & GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB)
{
/** Client supports default database on connect */
size_t userlen = strlen(ses->user) + 1;
/** Skip the authentication token, it is handled by the authenticators */
/** Client is connecting with a default database */
uint8_t authlen = data[MYSQL_AUTH_PACKET_BASE_SIZE + userlen];
size_t dboffset = MYSQL_AUTH_PACKET_BASE_SIZE + userlen + authlen + 1;
if (data[dboffset])
if (dboffset < len)
{
/** Client is connecting with a default database */
strcpy(ses->db, (char*)data + dboffset);
int dblen = get_zstr_len((const char*)data + dboffset, len - dboffset);
if (dblen != -1 && (int)sizeof(ses->db) < dblen)
{
strcpy(ses->db, (const char*)data + dboffset);
}
}
}
}