Fix packet decoding logic

This patch totally reworks the logic of the packet decoding for the
server-side sound channel.
This commit is contained in:
Hardening 2014-06-19 10:06:37 +02:00
parent f33f755635
commit 11f8e40d50

View File

@ -195,37 +195,41 @@ static void* rdpsnd_server_thread(void* arg)
UINT16 BodySize; UINT16 BodySize;
HANDLE events[8]; HANDLE events[8];
HANDLE ChannelEvent; HANDLE ChannelEvent;
DWORD BytesReturned; DWORD bytesReturned;
RdpsndServerContext* context; RdpsndServerContext* context;
BOOL doRun; BOOL doRun;
BOOL waitingHeader;
DWORD expectedBytes;
context = (RdpsndServerContext *)arg; context = (RdpsndServerContext *)arg;
buffer = NULL; buffer = NULL;
BytesReturned = 0; bytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096); s = Stream_New(NULL, 4096);
if (!s) if (!s)
return NULL; return NULL;
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned)) if (!WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{ {
if (BytesReturned == sizeof(HANDLE)) fprintf(stderr, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); __FUNCTION__, bytesReturned);
return NULL;
WTSFreeMemory(buffer);
} }
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
nCount = 0; nCount = 0;
if (ChannelEvent) events[nCount++] = ChannelEvent;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent; events[nCount++] = context->priv->StopEvent;
if (!rdpsnd_server_send_formats(context, s)) if (!rdpsnd_server_send_formats(context, s))
goto out; goto out;
doRun = TRUE; doRun = TRUE;
waitingHeader = TRUE;
expectedBytes = 4;
while (doRun) while (doRun)
{ {
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
@ -233,31 +237,34 @@ static void* rdpsnd_server_thread(void* arg)
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0) if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
break; break;
Stream_SetPosition(s, 0); if (!WTSVirtualChannelRead(ChannelEvent, 0, (PCHAR)Stream_Pointer(s), expectedBytes, &bytesReturned))
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned))
{ {
if (!BytesReturned) fprintf(stderr, "%s: channel connection closed\n", __FUNCTION__);
break; break;
}
expectedBytes -= bytesReturned;
Stream_Seek(s, bytesReturned);
Stream_EnsureRemainingCapacity(s, BytesReturned); if (expectedBytes)
continue;
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s), Stream_SetPosition(s, 0);
Stream_Capacity(s), &BytesReturned)) if (waitingHeader)
break; {
/* header case */
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
expectedBytes = BodySize;
waitingHeader = FALSE;
Stream_SetPosition(s, 0);
Stream_EnsureCapacity(s, BodySize);
if (expectedBytes)
continue;
} }
if (Stream_GetRemainingLength(s) < 4) /* when here we have the header + the body */
break;
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
if (Stream_GetRemainingLength(s) < BodySize)
break;
switch (msgType) switch (msgType)
{ {
case SNDC_WAVECONFIRM: case SNDC_WAVECONFIRM:
@ -280,6 +287,10 @@ static void* rdpsnd_server_thread(void* arg)
fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, msgType); fprintf(stderr, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, msgType);
break; break;
} }
expectedBytes = 4;
waitingHeader = TRUE;
Stream_SetPosition(s, 0);
} }
out: out: