From 37454c74204a8ebcd8da82e9d8da0e98a464a62b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 22 Dec 2022 12:04:13 +0100 Subject: [PATCH] [utils] improve rdpdr packet dump --- channels/rdpdr/client/rdpdr_main.c | 4 +- include/freerdp/utils/rdpdr_utils.h | 4 +- libfreerdp/utils/rdpdr_utils.c | 234 +++++++++++++++-------- server/proxy/channels/pf_channel_rdpdr.c | 13 +- 4 files changed, 167 insertions(+), 88 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 6e1234f27..19966167e 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -1502,7 +1502,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) if (!rdpdr || !s) return CHANNEL_RC_NULL_DATA; - rdpdr_dump_received_packet(s, "rdpdr-channel"); + rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] receive"); if (Stream_GetRemainingLength(s) >= 4) { Stream_Read_UINT16(s, component); /* Component (2 bytes) */ @@ -1650,7 +1650,7 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) else { const size_t pos = Stream_GetPosition(s); - rdpdr_dump_send_packet(s, "rdpdr-channel"); + rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] send"); status = plugin->channelEntryPoints.pVirtualChannelWriteEx( plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), pos, s); } diff --git a/include/freerdp/utils/rdpdr_utils.h b/include/freerdp/utils/rdpdr_utils.h index e0711f0e4..a13365717 100644 --- a/include/freerdp/utils/rdpdr_utils.h +++ b/include/freerdp/utils/rdpdr_utils.h @@ -35,7 +35,7 @@ FREERDP_API const char* scard_get_ioctl_string(UINT32 ioControlCode, BOOL funcNa FREERDP_API BOOL rdpdr_write_iocompletion_header(wStream* out, UINT32 DeviceId, UINT32 CompletionId, UINT32 ioStatus); -FREERDP_API void rdpdr_dump_received_packet(wStream* out, const char* custom); -FREERDP_API void rdpdr_dump_send_packet(wStream* out, const char* custom); +FREERDP_API void rdpdr_dump_received_packet(wLog* log, DWORD lvl, wStream* out, const char* custom); +FREERDP_API void rdpdr_dump_send_packet(wLog* log, DWORD lvl, wStream* out, const char* custom); #endif diff --git a/libfreerdp/utils/rdpdr_utils.c b/libfreerdp/utils/rdpdr_utils.c index b6df954db..cf65575f3 100644 --- a/libfreerdp/utils/rdpdr_utils.c +++ b/libfreerdp/utils/rdpdr_utils.c @@ -268,102 +268,180 @@ BOOL rdpdr_write_iocompletion_header(wStream* out, UINT32 DeviceId, UINT32 Compl return TRUE; } -void rdpdr_dump_received_packet(wStream* s, const char* custom) +static void rdpdr_dump_packet(wLog* log, DWORD lvl, wStream* s, const char* custom, BOOL send) { + if (!WLog_IsLevelActive(log, lvl)) + return; + const size_t gpos = Stream_GetPosition(s); + const size_t pos = send ? Stream_GetPosition(s) : Stream_Length(s); + + UINT16 component = 0, packetid = 0; + Stream_SetPosition(s, 0); - if (Stream_Length(s) >= 4) - { - BOOL done = FALSE; - UINT16 component, packetid; - UINT32 deviceID = 0; - UINT32 FileId = 0; - UINT32 CompletionId = 0; - UINT32 MajorFunction = 0; - UINT32 MinorFunction = 0; - const size_t pos = Stream_GetPosition(s); - wLog* log = WLog_Get(TAG); + if (pos >= 2) Stream_Read_UINT16(s, component); + if (pos >= 4) Stream_Read_UINT16(s, packetid); - if (Stream_GetRemainingLength(s) >= 4) - Stream_Read_UINT32(s, deviceID); - if (component == RDPDR_CTYP_CORE) - { - if (packetid == PAKID_CORE_DEVICE_IOREQUEST) - { - if (Stream_GetRemainingLength(s) >= 16) - { - Stream_Read_UINT32(s, FileId); /* FileId (4 bytes) */ - Stream_Read_UINT32(s, CompletionId); /* CompletionId (4 bytes) */ - Stream_Read_UINT32(s, MajorFunction); /* MajorFunction (4 bytes) */ - Stream_Read_UINT32(s, MinorFunction); /* MinorFunction (4 bytes) */ - WLog_Print(log, WLOG_DEBUG, - "[%s] receive [%s | %s] [0x%08" PRIx32 "] FileID=0x%08" PRIx32 - ", CompletionID=0x%08" PRIx32 ", MajorFunction=%s [0x%08" PRIx32 - "] -> %" PRIuz, - custom, rdpdr_component_string(component), - rdpdr_packetid_string(packetid), deviceID, FileId, CompletionId, - rdpdr_irp_string(MajorFunction), MinorFunction, deviceID, - Stream_Length(s)); - done = TRUE; - } + switch (packetid) + { + case PAKID_CORE_SERVER_ANNOUNCE: + case PAKID_CORE_CLIENTID_CONFIRM: + { + UINT16 versionMajor = 0, versionMinor = 0; + UINT32 clientID = 0; + + if (pos >= 6) + Stream_Read_UINT16(s, versionMajor); + if (pos >= 8) + Stream_Read_UINT16(s, versionMinor); + if (pos >= 12) + Stream_Read_UINT32(s, clientID); + WLog_Print(log, lvl, + "%s [%s | %s] [version:%" PRIu16 ".%" PRIu16 "][id:0x%08" PRIx32 + "] -> %" PRIuz, + custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), + versionMajor, versionMinor, clientID, pos); + } + break; + case PAKID_CORE_CLIENT_NAME: + { + char name[256] = { 0 }; + UINT32 unicodeFlag = 0; + UINT32 codePage = 0; + UINT32 computerNameLen = 0; + if (pos >= 8) + Stream_Read_UINT32(s, unicodeFlag); + if (pos >= 12) + Stream_Read_UINT32(s, codePage); + if (pos >= 16) + Stream_Read_UINT32(s, computerNameLen); + if (pos >= 16 + computerNameLen) + { + if (unicodeFlag == 0) + Stream_Read(s, name, MIN(sizeof(name), computerNameLen)); + else + ConvertWCharNToUtf8((const WCHAR*)Stream_Pointer(s), + computerNameLen / sizeof(WCHAR), name, sizeof(name)); + } + WLog_Print(log, lvl, + "%s [%s | %s] [ucs:%" PRIu32 "|cp:%" PRIu32 "][len:0x%08" PRIx32 + "] '%s' -> %" PRIuz, + custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), + unicodeFlag, codePage, computerNameLen, name, pos); + } + break; + + case PAKID_CORE_DEVICE_IOREQUEST: + { + UINT32 CompletionId = 0; + UINT32 deviceID = 0, FileId = 0, MajorFunction = 0, MinorFunction = 0; + + if (pos >= 8) + Stream_Read_UINT32(s, deviceID); + if (pos >= 12) + Stream_Read_UINT32(s, FileId); + if (pos >= 16) + Stream_Read_UINT32(s, CompletionId); + if (pos >= 20) + Stream_Read_UINT32(s, MajorFunction); + if (pos >= 24) + Stream_Read_UINT32(s, MinorFunction); + WLog_Print(log, lvl, + "%s [%s | %s] [0x%08" PRIx32 "] FileId=0x%08" PRIx32 + ", CompletionId=0x%08" PRIx32 ", MajorFunction=0x%08" PRIx32 + ", MinorFunction=0x%08" PRIx32 " -> %" PRIuz, + custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), + deviceID, FileId, CompletionId, MajorFunction, MinorFunction, pos); + } + break; + case PAKID_CORE_DEVICE_IOCOMPLETION: + { + UINT32 completionID = 0, ioStatus = 0; + UINT32 deviceID = 0; + if (pos >= 8) + Stream_Read_UINT32(s, deviceID); + if (pos >= 12) + Stream_Read_UINT32(s, completionID); + if (pos >= 16) + Stream_Read_UINT32(s, ioStatus); + + WLog_Print(log, lvl, + "%s [%s | %s] [0x%08" PRIx32 "] completionID=0x%08" PRIx32 + ", ioStatus=0x%08" PRIx32 " -> %" PRIuz, + custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), + deviceID, completionID, ioStatus, pos); + } + break; + case PAKID_CORE_DEVICE_REPLY: + { + UINT32 deviceID = 0, status = 0; + + if (pos >= 8) + Stream_Read_UINT32(s, deviceID); + if (pos >= 12) + Stream_Read_UINT32(s, status); + WLog_Print(log, lvl, + "%s [%s | %s] [id:0x%08" PRIx32 ",status=0x%08" PRIx32 "] -> %" PRIuz, + custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), + deviceID, status, pos); + } + break; + case PAKID_CORE_CLIENT_CAPABILITY: + case PAKID_CORE_SERVER_CAPABILITY: + { + UINT16 numCapabilities = 0; + if (pos >= 6) + Stream_Read_UINT16(s, numCapabilities); + if (pos >= 8) + Stream_Seek_UINT16(s); /* padding */ + WLog_Print(log, lvl, "%s [%s | %s] [caps:%" PRIu16 "] -> %" PRIuz, custom, + rdpdr_component_string(component), rdpdr_packetid_string(packetid), + numCapabilities, pos); + } + break; + case PAKID_CORE_DEVICELIST_ANNOUNCE: + case PAKID_CORE_DEVICELIST_REMOVE: + { + { + UINT32 count = 0; + + if (pos >= 8) + Stream_Read_UINT32(s, count); + WLog_Print(log, lvl, "%s [%s | %s] [%" PRIu32 "] -> %" PRIuz, custom, + rdpdr_component_string(component), rdpdr_packetid_string(packetid), + count, pos); + if (count > 0) + WLog_WARN(TAG, "xxx"); } } - Stream_SetPosition(s, pos); - - if (!done) + break; + case PAKID_CORE_USER_LOGGEDON: + WLog_Print(log, lvl, "%s [%s | %s] -> %" PRIuz, custom, + rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos); + break; + default: { - WLog_Print(log, WLOG_DEBUG, "[%s] receive [%s | %s] [0x%08" PRIx32 "] -> %" PRIuz, - custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), - deviceID, Stream_Length(s)); + WLog_Print(log, lvl, "%s [%s | %s] -> %" PRIuz, custom, + rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos); } - winpr_HexLogDump(log, WLOG_TRACE, Stream_Buffer(s), Stream_Length(s)); + break; } + // winpr_HexLogDump(log, lvl, Stream_Buffer(s), pos); Stream_SetPosition(s, gpos); } -void rdpdr_dump_send_packet(wStream* s, const char* custom) +void rdpdr_dump_received_packet(wLog* log, DWORD lvl, wStream* s, const char* custom) { - WINPR_ASSERT(s); + rdpdr_dump_packet(log, lvl, s, custom, FALSE); +} - if (Stream_Length(s) >= 8) - { - UINT16 component, packetid; - UINT32 deviceID; - const size_t pos = Stream_GetPosition(s); - Stream_SetPosition(s, 0); - - Stream_Read_UINT16(s, component); - Stream_Read_UINT16(s, packetid); - Stream_Read_UINT32(s, deviceID); - switch (packetid) - { - case PAKID_CORE_DEVICE_IOCOMPLETION: - { - UINT32 completionID, ioStatus; - Stream_Read_UINT32(s, completionID); - Stream_Read_UINT32(s, ioStatus); - - WLog_DBG(TAG, - "[%s] sending [%s | %s] [0x%08" PRIx32 "] completionID=0x%08" PRIx32 - ", ioStatus=0x%08" PRIx32 " -> %" PRIuz, - custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid), - deviceID, completionID, ioStatus, pos); - } - break; - default: - WLog_DBG(TAG, "[%s] sending [%s | %s] [0x%08" PRIx32 "] -> %" PRIuz, custom, - rdpdr_component_string(component), rdpdr_packetid_string(packetid), - deviceID, pos); - break; - } - - winpr_HexDump(TAG, WLOG_TRACE, Stream_Buffer(s), pos); - Stream_SetPosition(s, pos); - } +void rdpdr_dump_send_packet(wLog* log, DWORD lvl, wStream* s, const char* custom) +{ + rdpdr_dump_packet(log, lvl, s, custom, TRUE); } const char* rdpdr_irp_string(UINT32 major) diff --git a/server/proxy/channels/pf_channel_rdpdr.c b/server/proxy/channels/pf_channel_rdpdr.c index a3139a859..5c099a134 100644 --- a/server/proxy/channels/pf_channel_rdpdr.c +++ b/server/proxy/channels/pf_channel_rdpdr.c @@ -176,7 +176,7 @@ static UINT rdpdr_client_send(pClientContext* pc, wStream* s) return ERROR_INTERNAL_ERROR; Stream_SealLength(s); - rdpdr_dump_send_packet(s, "proxy-client"); + rdpdr_dump_send_packet(WLog_Get(TAG), WLOG_TRACE, s, "proxy-client"); WINPR_ASSERT(pc->context.instance->SendChannelData); if (!pc->context.instance->SendChannelData(pc->context.instance, channelId, Stream_Buffer(s), Stream_Length(s))) @@ -1072,11 +1072,12 @@ BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* if (!s) continue; - Stream_SetPosition(s, Stream_Length(s)); - rdpdr_dump_send_packet(s, "proxy-client-queue"); + const size_t len = Stream_Length(s); + Stream_SetPosition(s, len); + rdpdr_dump_send_packet(WLog_Get(TAG), WLOG_TRACE, s, "proxy-client-queue"); WINPR_ASSERT(pc->context.instance->SendChannelData); if (!pc->context.instance->SendChannelData(pc->context.instance, channelId, - Stream_Buffer(s), Stream_Length(s))) + Stream_Buffer(s), len)) { WLog_WARN(TAG, "xxxxxx TODO: Failed to send data!"); } @@ -1152,7 +1153,7 @@ BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId, const return FALSE; } - rdpdr_dump_received_packet(s, "proxy-client"); + rdpdr_dump_received_packet(WLog_Get(TAG), WLOG_TRACE, s, "proxy-client"); switch (rdpdr->state) { case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST: @@ -1235,7 +1236,7 @@ BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId, const } break; #else - return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s); + return pf_channel_rdpdr_client_send_to_server(ps, s); #endif default: WLog_ERR(TAG,