From 8e1a1b407565eb0a48923c796f5b1f69167b3c48 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Wed, 15 Apr 2020 16:41:52 +0200 Subject: [PATCH] Fixed cliprdr_server_receive_capabilities Thanks to hac425 CVE-2020-11017, CVE-2020-11018 --- channels/cliprdr/server/cliprdr_main.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 34ff4d74d..8854a0fb7 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -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,29 +467,33 @@ 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; - tmp = realloc(capabilities.capabilitySets, cap_sets_size); + if (cap_sets_size > 0) + tmp = realloc(capabilities.capabilitySets, cap_sets_size); if (tmp == NULL) { WLog_ERR(TAG, "capabilities.capabilitySets realloc failed!"); @@ -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);