Fixed cliprdr_server_receive_capabilities
Thanks to hac425 CVE-2020-11017, CVE-2020-11018
@@ -432,6 +432,9 @@ cliprdr_server_file_contents_response(CliprdrServerContext* context,
static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* context, wStream* s,
CLIPRDR_GENERAL_CAPABILITY_SET* cap_set)
{
+ if (Stream_GetRemainingLength(s) < 8)
+ return ERROR_INVALID_DATA;
+
Stream_Read_UINT32(s, cap_set->version); /* version (4 bytes) */
Stream_Read_UINT32(s, cap_set->generalFlags); /* generalFlags (4 bytes) */
@@ -464,28 +467,32 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w
UINT16 index;
UINT16 capabilitySetType;
UINT16 capabilitySetLength;
- UINT error = CHANNEL_RC_OK;
+ UINT error = ERROR_INVALID_DATA;
size_t cap_sets_size = 0;
- CLIPRDR_CAPABILITIES capabilities;
+ CLIPRDR_CAPABILITIES capabilities = { 0 };
CLIPRDR_CAPABILITY_SET* capSet;
- void* tmp;
WINPR_UNUSED(header);
- /* set `capabilitySets` to NULL so `realloc` will know to alloc the first block */
- capabilities.capabilitySets = NULL;
WLog_DBG(TAG, "CliprdrClientCapabilities");
+ if (Stream_GetRemainingLength(s) < 4)
+ return ERROR_INVALID_DATA;
+
Stream_Read_UINT16(s, capabilities.cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
for (index = 0; index < capabilities.cCapabilitiesSets; index++)
{
+ void* tmp = NULL;
+ if (Stream_GetRemainingLength(s) < 4)
+ goto out;
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
Stream_Read_UINT16(s, capabilitySetLength); /* capabilitySetLength (2 bytes) */
cap_sets_size += capabilitySetLength;
+ if (cap_sets_size > 0)
tmp = realloc(capabilities.capabilitySets, cap_sets_size);
if (tmp == NULL)
{
@@ -504,8 +511,9 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w
switch (capSet->capabilitySetType)
{
case CB_CAPSTYPE_GENERAL:
- if ((error = cliprdr_server_receive_general_capability(
- context, s, (CLIPRDR_GENERAL_CAPABILITY_SET*)capSet)))
+ error = cliprdr_server_receive_general_capability(
+ context, s, (CLIPRDR_GENERAL_CAPABILITY_SET*)capSet);
+ if (error)
{
WLog_ERR(TAG,
"cliprdr_server_receive_general_capability failed with error %" PRIu32
@@ -518,11 +526,11 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, w
default:
WLog_ERR(TAG, "unknown cliprdr capability set: %" PRIu16 "",
capSet->capabilitySetType);
- error = ERROR_INVALID_DATA;
goto out;
}
}
+ error = CHANNEL_RC_OK;
IFCALLRET(context->ClientCapabilities, error, context, &capabilities);
out:
free(capabilities.capabilitySets);
