Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for #4866: Added additional length checks #4871

Merged
merged 1 commit into from Sep 21, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Fix for #4866: Added additional length checks
  • Loading branch information
akallabeth committed Sep 20, 2018
commit baee520e3dd9be6511c45a14c5f5e77784de1471
61 changes: 53 additions & 8 deletions channels/drdynvc/client/drdynvc_main.c
Expand Up @@ -639,16 +639,15 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc,
if (channel->dvc_data)
{
/* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(
channel->dvc_data))
if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
return ERROR_INVALID_DATA;
}

Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
Stream_Copy(data, channel->dvc_data, dataSize);

if (Stream_GetPosition(channel->dvc_data) >= channel->dvc_data_length)
{
Expand Down Expand Up @@ -880,6 +879,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
if (!drdynvc)
return CHANNEL_RC_BAD_INIT_HANDLE;

if (Stream_GetRemainingLength(s) < 3)
return ERROR_INVALID_DATA;

WLog_Print(drdynvc->log, WLOG_TRACE, "capability_request Sp=%d cbChId=%d", Sp, cbChId);
Stream_Seek(s, 1); /* pad */
Stream_Read_UINT16(s, drdynvc->version);
Expand All @@ -889,6 +891,9 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
*/
if ((drdynvc->version == 2) || (drdynvc->version == 3))
{
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;

Stream_Read_UINT16(s, drdynvc->PriorityCharge0);
Stream_Read_UINT16(s, drdynvc->PriorityCharge1);
Stream_Read_UINT16(s, drdynvc->PriorityCharge2);
Expand All @@ -900,6 +905,21 @@ static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp,
return status;
}

static UINT32 drdynvc_cblen_to_bytes(int cbLen)
{
switch (cbLen)
{
case 0:
return 1;

case 1:
return 2;

default:
return 4;
}
}

static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen)
{
UINT32 val;
Expand Down Expand Up @@ -935,6 +955,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
UINT32 ChannelId;
wStream* data_out;
UINT channel_status;
char* name;
size_t length;

if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
Expand All @@ -957,13 +979,20 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp,
drdynvc->state = DRDYNVC_STATE_READY;
}

if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;

ChannelId = drdynvc_read_variable_uint(s, cbChId);
pos = Stream_GetPosition(s);
name = Stream_Pointer(s);
length = Stream_GetRemainingLength(s);

if (strnlen(name, length) >= length)
return ERROR_INVALID_DATA;

WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s",
ChannelId,
Stream_Pointer(s));
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId,
(char*) Stream_Pointer(s));
ChannelId, name);
channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name);
data_out = Stream_New(NULL, pos + 4);

if (!data_out)
Expand Down Expand Up @@ -1024,6 +1053,10 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp,
UINT status;
UINT32 Length;
UINT32 ChannelId;

if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId) + drdynvc_cblen_to_bytes(Sp))
return ERROR_INVALID_DATA;

ChannelId = drdynvc_read_variable_uint(s, cbChId);
Length = drdynvc_read_variable_uint(s, Sp);
WLog_Print(drdynvc->log, WLOG_DEBUG,
Expand All @@ -1047,6 +1080,10 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId,
wStream* s)
{
UINT32 ChannelId;

if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;

ChannelId = drdynvc_read_variable_uint(s, cbChId);
WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp,
cbChId,
Expand All @@ -1066,6 +1103,10 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp,
UINT error;
UINT32 ChannelId;
wStream* data_out;

if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId))
return ERROR_INVALID_DATA;

ChannelId = drdynvc_read_variable_uint(s, cbChId);
WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"",
Sp,
Expand Down Expand Up @@ -1108,6 +1149,10 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
int Cmd;
int Sp;
int cbChId;

if (Stream_GetRemainingLength(s) < 1)
return ERROR_INVALID_DATA;

Stream_Read_UINT8(s, value);
Cmd = (value & 0xf0) >> 4;
Sp = (value & 0x0c) >> 2;
Expand Down Expand Up @@ -1166,7 +1211,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
return CHANNEL_RC_NO_MEMORY;
}

if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
{
WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
Stream_Free(drdynvc->data_in, TRUE);
Expand Down