21#include <freerdp/config.h>
23#include <winpr/assert.h>
24#include <winpr/cast.h>
25#include <winpr/string.h>
26#include <winpr/print.h>
28#include "../pf_client.h"
29#include "../pf_server.h"
30#include "pf_channel_rdpdr.h"
31#include "pf_channel_smartcard.h"
33#include <freerdp/server/proxy/proxy_log.h>
34#include <freerdp/channels/rdpdr.h>
35#include <freerdp/channels/channels.h>
36#include <freerdp/utils/rdpdr_utils.h>
38#define RTAG PROXY_TAG("channel.rdpdr")
40#define SCARD_DEVICE_ID UINT32_MAX
50 UINT32 computerNameLen;
51 BOOL computerNameUnicode;
58 UINT32 SpecialDeviceCount;
59 UINT32 capabilityVersions[6];
60} pf_channel_common_context;
64 STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST = 0x01,
65 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST = 0x02,
66 STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM = 0x04,
67 STATE_CLIENT_CHANNEL_RUNNING = 0x10
68} pf_channel_client_state;
72 pf_channel_common_context common;
73 pf_channel_client_state state;
75 UINT16 maxMajorVersion;
76 UINT16 maxMinorVersion;
79} pf_channel_client_context;
84 STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY,
85 STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST,
86 STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE,
87 STATE_SERVER_CHANNEL_RUNNING
88} pf_channel_server_state;
92 pf_channel_common_context common;
93 pf_channel_server_state state;
96 wArrayList* blockedDevices;
98} pf_channel_server_context;
100#define proxy_client "[proxy<-->client]"
101#define proxy_server "[proxy<-->server]"
103#define proxy_client_rx proxy_client " receive"
104#define proxy_client_tx proxy_client " send"
105#define proxy_server_rx proxy_server " receive"
106#define proxy_server_tx proxy_server " send"
108#define SERVER_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_rx fmt, ##__VA_ARGS__)
109#define CLIENT_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_rx fmt, ##__VA_ARGS__)
110#define SERVER_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_tx fmt, ##__VA_ARGS__)
111#define CLIENT_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_tx fmt, ##__VA_ARGS__)
112#define RX_LOG(srv, lvl, fmt, ...) \
117 SERVER_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
121 CLIENT_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
125#define SERVER_RXTX_LOG(send, log, lvl, fmt, ...) \
130 SERVER_TX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
134 SERVER_RX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
138#define Stream_CheckAndLogRequiredLengthSrv(log, s, len) \
139 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
140 proxy_client_rx " %s(%s:%" PRIuz ")", __func__, \
141 __FILE__, (size_t)__LINE__)
142#define Stream_CheckAndLogRequiredLengthClient(log, s, len) \
143 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
144 proxy_server_rx " %s(%s:%" PRIuz ")", __func__, \
145 __FILE__, (size_t)__LINE__)
146#define Stream_CheckAndLogRequiredLengthRx(srv, log, s, len) \
147 Stream_CheckAndLogRequiredLengthRx_(srv, log, s, len, 1, __func__, __FILE__, __LINE__)
149static BOOL Stream_CheckAndLogRequiredLengthRx_(BOOL srv, wLog* log,
wStream* s,
size_t nmemb,
150 size_t size,
const char* fkt,
const char* file,
154 srv ? proxy_server_rx
" %s(%s:%" PRIuz
")" : proxy_client_rx
" %s(%s:%" PRIuz
")";
156 return Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, fmt, fkt, file,
161static const char* rdpdr_server_state_to_string(pf_channel_server_state state)
165 case STATE_SERVER_INITIAL:
166 return "STATE_SERVER_INITIAL";
167 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
168 return "STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY";
169 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
170 return "STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST";
171 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
172 return "STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE";
173 case STATE_SERVER_CHANNEL_RUNNING:
174 return "STATE_SERVER_CHANNEL_RUNNING";
176 return "STATE_SERVER_UNKNOWN";
181static const char* rdpdr_client_state_to_string(pf_channel_client_state state)
185 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
186 return "STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST";
187 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
188 return "STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST";
189 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
190 return "STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM";
191 case STATE_CLIENT_CHANNEL_RUNNING:
192 return "STATE_CLIENT_CHANNEL_RUNNING";
194 return "STATE_CLIENT_UNKNOWN";
199static wStream* rdpdr_get_send_buffer(pf_channel_common_context* rdpdr, UINT16 component,
200 UINT16 PacketID,
size_t capacity)
203 WINPR_ASSERT(rdpdr->s);
204 Stream_ResetPosition(rdpdr->s);
206 if (!Stream_EnsureCapacity(rdpdr->s, capacity + 4))
208 Stream_Write_UINT16(rdpdr->s, component);
209 Stream_Write_UINT16(rdpdr->s, PacketID);
214static wStream* rdpdr_client_get_send_buffer(pf_channel_client_context* rdpdr, UINT16 component,
215 UINT16 PacketID,
size_t capacity)
218 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
222static wStream* rdpdr_server_get_send_buffer(pf_channel_server_context* rdpdr, UINT16 component,
223 UINT16 PacketID,
size_t capacity)
226 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
230static UINT rdpdr_client_send(wLog* log, pClientContext* pc,
wStream* s)
232 UINT16 channelId = 0;
237 WINPR_ASSERT(pc->cctx.context.instance);
241 CLIENT_TX_LOG(log, WLOG_WARN,
"Ignoring channel %s message, not connected!",
242 RDPDR_SVC_CHANNEL_NAME);
243 return CHANNEL_RC_OK;
246 channelId = freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
249 if ((channelId == 0) || (channelId == UINT16_MAX))
250 return ERROR_INTERNAL_ERROR;
252 Stream_SealLength(s);
253 rdpdr_dump_send_packet(log, WLOG_TRACE, s, proxy_server_tx);
254 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
255 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
256 Stream_Buffer(s), Stream_Length(s)))
257 return ERROR_EVT_CHANNEL_NOT_FOUND;
258 return CHANNEL_RC_OK;
262static UINT rdpdr_seal_send_free_request(pf_channel_server_context* context,
wStream* s)
267 WINPR_ASSERT(context);
268 WINPR_ASSERT(context->handle);
271 Stream_SealLength(s);
272 len = Stream_Length(s);
273 WINPR_ASSERT(len <= UINT32_MAX);
275 rdpdr_dump_send_packet(context->log, WLOG_TRACE, s, proxy_client_tx);
276 status = WTSVirtualChannelWrite(context->handle, Stream_BufferAs(s,
char), (ULONG)len,
nullptr);
277 return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
281static BOOL rdpdr_process_server_header(BOOL server, wLog* log,
wStream* s, UINT16 component,
282 UINT16 PacketId,
size_t expect)
284 UINT16 rpacketid = 0;
285 UINT16 rcomponent = 0;
288 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, 4))
290 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: expected length 4, got %" PRIuz,
291 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
292 Stream_GetRemainingLength(s));
296 Stream_Read_UINT16(s, rcomponent);
297 Stream_Read_UINT16(s, rpacketid);
299 if (rcomponent != component)
301 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got component %s",
302 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
303 rdpdr_component_string(rcomponent));
307 if (rpacketid != PacketId)
309 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got PacketID %s",
310 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
311 rdpdr_packetid_string(rpacketid));
315 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, expect))
317 RX_LOG(server, log, WLOG_WARN,
318 "RDPDR_HEADER[%s | %s] not enough data, expected %" PRIuz
", "
320 rdpdr_component_string(component), rdpdr_packetid_string(PacketId), expect,
321 Stream_GetRemainingLength(s));
322 return ERROR_INVALID_DATA;
329static BOOL rdpdr_check_version(BOOL server, wLog* log, UINT16 versionMajor, UINT16 versionMinor,
330 UINT16 component, UINT16 PacketId)
332 if (versionMajor != RDPDR_VERSION_MAJOR)
334 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] expected MajorVersion %d, got %" PRIu16,
335 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
336 RDPDR_VERSION_MAJOR, versionMajor);
339 switch (versionMinor)
341 case RDPDR_VERSION_MINOR_RDP50:
342 case RDPDR_VERSION_MINOR_RDP51:
343 case RDPDR_VERSION_MINOR_RDP52:
344 case RDPDR_VERSION_MINOR_RDP6X:
345 case RDPDR_VERSION_MINOR_RDP10X:
349 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] unsupported MinorVersion %" PRIu16,
350 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
359static UINT rdpdr_process_server_announce_request(pf_channel_client_context* rdpdr,
wStream* s)
361 const UINT16 component = RDPDR_CTYP_CORE;
362 const UINT16 packetid = PAKID_CORE_SERVER_ANNOUNCE;
366 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, component, packetid, 8))
367 return ERROR_INVALID_DATA;
369 Stream_Read_UINT16(s, rdpdr->common.versionMajor);
370 Stream_Read_UINT16(s, rdpdr->common.versionMinor);
372 if (!rdpdr_check_version(FALSE, rdpdr->log, rdpdr->common.versionMajor,
373 rdpdr->common.versionMinor, component, packetid))
374 return ERROR_INVALID_DATA;
377 if (rdpdr->common.versionMajor > rdpdr->maxMajorVersion)
379 rdpdr->common.versionMajor = rdpdr->maxMajorVersion;
380 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
382 else if (rdpdr->common.versionMinor > rdpdr->maxMinorVersion)
383 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
385 Stream_Read_UINT32(s, rdpdr->common.clientID);
386 return CHANNEL_RC_OK;
390static UINT rdpdr_server_send_announce_request(pf_channel_server_context* context)
393 rdpdr_server_get_send_buffer(context, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_ANNOUNCE, 8);
395 return CHANNEL_RC_NO_MEMORY;
397 Stream_Write_UINT16(s, context->common.versionMajor);
398 Stream_Write_UINT16(s, context->common.versionMinor);
399 Stream_Write_UINT32(s, context->common.clientID);
400 return rdpdr_seal_send_free_request(context, s);
404static UINT rdpdr_process_client_announce_reply(pf_channel_server_context* rdpdr,
wStream* s)
406 const UINT16 component = RDPDR_CTYP_CORE;
407 const UINT16 packetid = PAKID_CORE_CLIENTID_CONFIRM;
408 UINT16 versionMajor = 0;
409 UINT16 versionMinor = 0;
415 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
416 return ERROR_INVALID_DATA;
418 Stream_Read_UINT16(s, versionMajor);
419 Stream_Read_UINT16(s, versionMinor);
421 if (!rdpdr_check_version(TRUE, rdpdr->log, versionMajor, versionMinor, component, packetid))
422 return ERROR_INVALID_DATA;
424 if ((rdpdr->common.versionMajor != versionMajor) ||
425 (rdpdr->common.versionMinor != versionMinor))
428 rdpdr->log, WLOG_WARN,
429 "[%s | %s] downgrading version from %" PRIu16
".%" PRIu16
" to %" PRIu16
".%" PRIu16,
430 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
431 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor, versionMinor);
432 rdpdr->common.versionMajor = versionMajor;
433 rdpdr->common.versionMinor = versionMinor;
435 Stream_Read_UINT32(s, clientID);
436 if (rdpdr->common.clientID != clientID)
438 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
439 "[%s | %s] changing clientID 0x%08" PRIu32
" to 0x%08" PRIu32,
440 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
441 rdpdr->common.clientID, clientID);
442 rdpdr->common.clientID = clientID;
445 return CHANNEL_RC_OK;
449static UINT rdpdr_send_client_announce_reply(pClientContext* pc, pf_channel_client_context* rdpdr)
452 rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
454 return CHANNEL_RC_NO_MEMORY;
456 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
457 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
458 Stream_Write_UINT32(s, rdpdr->common.clientID);
459 return rdpdr_client_send(rdpdr->log, pc, s);
463static UINT rdpdr_process_client_name_request(pf_channel_server_context* rdpdr,
wStream* s,
466 UINT32 unicodeFlag = 0;
473 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
475 return ERROR_INVALID_DATA;
477 Stream_Read_UINT32(s, unicodeFlag);
478 rdpdr->common.computerNameUnicode = ((unicodeFlag & 1) != 0);
480 Stream_Read_UINT32(s, codePage);
481 WINPR_UNUSED(codePage);
482 Stream_Read_UINT32(s, rdpdr->common.computerNameLen);
483 if (!Stream_CheckAndLogRequiredLengthSrv(rdpdr->log, s, rdpdr->common.computerNameLen))
486 rdpdr->log, WLOG_WARN,
"[%s | %s]: missing data, got %" PRIuz
", expected %" PRIu32,
487 rdpdr_component_string(RDPDR_CTYP_CORE), rdpdr_packetid_string(PAKID_CORE_CLIENT_NAME),
488 Stream_GetRemainingLength(s), rdpdr->common.computerNameLen);
489 return ERROR_INVALID_DATA;
491 void* tmp = realloc(rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
493 return CHANNEL_RC_NO_MEMORY;
494 rdpdr->common.computerName.v = tmp;
496 Stream_Read(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
498 pc->computerNameLen = rdpdr->common.computerNameLen;
499 pc->computerNameUnicode = rdpdr->common.computerNameUnicode;
500 tmp = realloc(pc->computerName.v, pc->computerNameLen);
502 return CHANNEL_RC_NO_MEMORY;
503 pc->computerName.v = tmp;
504 memcpy(pc->computerName.v, rdpdr->common.computerName.v, pc->computerNameLen);
506 return CHANNEL_RC_OK;
510static UINT rdpdr_send_client_name_request(pClientContext* pc, pf_channel_client_context* rdpdr)
518 void* tmp = realloc(rdpdr->common.computerName.v, pc->computerNameLen);
520 return CHANNEL_RC_NO_MEMORY;
521 rdpdr->common.computerName.v = tmp;
522 rdpdr->common.computerNameLen = pc->computerNameLen;
523 rdpdr->common.computerNameUnicode = pc->computerNameUnicode;
524 memcpy(rdpdr->common.computerName.v, pc->computerName.v, pc->computerNameLen);
526 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
527 12U + rdpdr->common.computerNameLen);
529 return CHANNEL_RC_NO_MEMORY;
531 Stream_Write_UINT32(s, rdpdr->common.computerNameUnicode
534 Stream_Write_UINT32(s, 0);
535 Stream_Write_UINT32(s, rdpdr->common.computerNameLen);
536 Stream_Write(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
537 return rdpdr_client_send(rdpdr->log, pc, s);
540#define rdpdr_ignore_capset(srv, log, s, header) \
541 rdpdr_ignore_capset_((srv), (log), (s), header, __func__)
543static UINT rdpdr_ignore_capset_(WINPR_ATTR_UNUSED BOOL srv, WINPR_ATTR_UNUSED wLog* log,
545 WINPR_ATTR_UNUSED
const char* fkt)
548 WINPR_ASSERT(header);
550 Stream_Seek(s, header->CapabilityLength);
551 return CHANNEL_RC_OK;
555static UINT rdpdr_client_process_general_capset(pf_channel_client_context* rdpdr,
wStream* s,
559 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
563static UINT rdpdr_process_printer_capset(pf_channel_client_context* rdpdr,
wStream* s,
567 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
571static UINT rdpdr_process_port_capset(pf_channel_client_context* rdpdr,
wStream* s,
575 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
579static UINT rdpdr_process_drive_capset(pf_channel_client_context* rdpdr,
wStream* s,
583 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
587static UINT rdpdr_process_smartcard_capset(pf_channel_client_context* rdpdr,
wStream* s,
591 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
595static UINT rdpdr_process_server_core_capability_request(pf_channel_client_context* rdpdr,
598 UINT status = CHANNEL_RC_OK;
599 UINT16 numCapabilities = 0;
603 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
604 PAKID_CORE_SERVER_CAPABILITY, 4))
605 return ERROR_INVALID_DATA;
607 Stream_Read_UINT16(s, numCapabilities);
610 for (UINT16 i = 0; i < numCapabilities; i++)
613 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
614 if (error != CHANNEL_RC_OK)
617 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
619 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
620 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
622 WLog_Print(rdpdr->log, WLOG_TRACE,
623 "capability %s got version %" PRIu32
", will use version %" PRIu32,
624 rdpdr_cap_type_string(header.CapabilityType), header.Version,
625 rdpdr->common.capabilityVersions[header.CapabilityType]);
628 switch (header.CapabilityType)
630 case CAP_GENERAL_TYPE:
631 status = rdpdr_client_process_general_capset(rdpdr, s, &header);
634 case CAP_PRINTER_TYPE:
635 status = rdpdr_process_printer_capset(rdpdr, s, &header);
639 status = rdpdr_process_port_capset(rdpdr, s, &header);
643 status = rdpdr_process_drive_capset(rdpdr, s, &header);
646 case CAP_SMARTCARD_TYPE:
647 status = rdpdr_process_smartcard_capset(rdpdr, s, &header);
651 WLog_Print(rdpdr->log, WLOG_WARN,
652 "unknown capability 0x%04" PRIx16
", length %" PRIu16
653 ", version %" PRIu32,
654 header.CapabilityType, header.CapabilityLength, header.Version);
655 Stream_Seek(s, header.CapabilityLength);
659 if (status != CHANNEL_RC_OK)
663 return CHANNEL_RC_OK;
667static BOOL rdpdr_write_general_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
673 rdpdr->capabilityVersions[CAP_GENERAL_TYPE] };
674 if (rdpdr_write_capset_header(log, s, &header) != CHANNEL_RC_OK)
676 Stream_Write_UINT32(s, 0);
677 Stream_Write_UINT32(s, 0);
678 Stream_Write_UINT16(s, rdpdr->versionMajor);
679 Stream_Write_UINT16(s, rdpdr->versionMinor);
680 Stream_Write_UINT32(s, 0x0000FFFF);
681 Stream_Write_UINT32(s, 0);
682 Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU |
683 RDPDR_USER_LOGGEDON_PDU);
684 Stream_Write_UINT32(s, ENABLE_ASYNCIO);
685 Stream_Write_UINT32(s, 0);
686 Stream_Write_UINT32(s, rdpdr->SpecialDeviceCount);
692static BOOL rdpdr_write_printer_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
698 rdpdr->capabilityVersions[CAP_PRINTER_TYPE] };
699 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
703static BOOL rdpdr_write_port_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
709 rdpdr->capabilityVersions[CAP_PORT_TYPE] };
710 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
714static BOOL rdpdr_write_drive_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
720 rdpdr->capabilityVersions[CAP_DRIVE_TYPE] };
721 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
725static BOOL rdpdr_write_smartcard_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
731 rdpdr->capabilityVersions[CAP_SMARTCARD_TYPE] };
732 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
736static UINT rdpdr_send_server_capability_request(pf_channel_server_context* rdpdr)
739 rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_CAPABILITY, 8);
741 return CHANNEL_RC_NO_MEMORY;
742 Stream_Write_UINT16(s, 5);
743 Stream_Write_UINT16(s, 0);
744 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
745 return CHANNEL_RC_NO_MEMORY;
746 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
747 return CHANNEL_RC_NO_MEMORY;
748 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
749 return CHANNEL_RC_NO_MEMORY;
750 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
751 return CHANNEL_RC_NO_MEMORY;
752 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
753 return CHANNEL_RC_NO_MEMORY;
754 return rdpdr_seal_send_free_request(rdpdr, s);
758static UINT rdpdr_process_client_capability_response(pf_channel_server_context* rdpdr,
wStream* s)
760 const UINT16 component = RDPDR_CTYP_CORE;
761 const UINT16 packetid = PAKID_CORE_CLIENT_CAPABILITY;
762 UINT status = CHANNEL_RC_OK;
763 UINT16 numCapabilities = 0;
766 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 4))
767 return ERROR_INVALID_DATA;
769 Stream_Read_UINT16(s, numCapabilities);
770 Stream_Seek_UINT16(s);
772 for (UINT16 x = 0; x < numCapabilities; x++)
775 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
776 if (error != CHANNEL_RC_OK)
778 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
780 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
781 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
783 WLog_Print(rdpdr->log, WLOG_TRACE,
784 "capability %s got version %" PRIu32
", will use version %" PRIu32,
785 rdpdr_cap_type_string(header.CapabilityType), header.Version,
786 rdpdr->common.capabilityVersions[header.CapabilityType]);
789 switch (header.CapabilityType)
791 case CAP_GENERAL_TYPE:
792 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
795 case CAP_PRINTER_TYPE:
796 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
800 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
804 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
807 case CAP_SMARTCARD_TYPE:
808 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
812 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
813 "[%s | %s] invalid capability type 0x%04" PRIx16,
814 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
815 header.CapabilityType);
816 status = ERROR_INVALID_DATA;
820 if (status != CHANNEL_RC_OK)
828static UINT rdpdr_send_client_capability_response(pClientContext* pc,
829 pf_channel_client_context* rdpdr)
834 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_CAPABILITY, 4);
836 return CHANNEL_RC_NO_MEMORY;
838 Stream_Write_UINT16(s, 5);
839 Stream_Write_UINT16(s, 0);
840 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
841 return CHANNEL_RC_NO_MEMORY;
842 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
843 return CHANNEL_RC_NO_MEMORY;
844 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
845 return CHANNEL_RC_NO_MEMORY;
846 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
847 return CHANNEL_RC_NO_MEMORY;
848 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
849 return CHANNEL_RC_NO_MEMORY;
850 return rdpdr_client_send(rdpdr->log, pc, s);
854static UINT rdpdr_send_server_clientid_confirm(pf_channel_server_context* rdpdr)
858 s = rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
860 return CHANNEL_RC_NO_MEMORY;
861 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
862 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
863 Stream_Write_UINT32(s, rdpdr->common.clientID);
864 return rdpdr_seal_send_free_request(rdpdr, s);
868static UINT rdpdr_process_server_clientid_confirm(pf_channel_client_context* rdpdr,
wStream* s)
870 UINT16 versionMajor = 0;
871 UINT16 versionMinor = 0;
877 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
878 PAKID_CORE_CLIENTID_CONFIRM, 8))
879 return ERROR_INVALID_DATA;
881 Stream_Read_UINT16(s, versionMajor);
882 Stream_Read_UINT16(s, versionMinor);
883 if (!rdpdr_check_version(FALSE, rdpdr->log, versionMajor, versionMinor, RDPDR_CTYP_CORE,
884 PAKID_CORE_CLIENTID_CONFIRM))
885 return ERROR_INVALID_DATA;
887 Stream_Read_UINT32(s, clientID);
889 if ((versionMajor != rdpdr->common.versionMajor) ||
890 (versionMinor != rdpdr->common.versionMinor))
892 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
893 "[%s | %s] Version mismatch, sent %" PRIu16
".%" PRIu16
894 ", downgraded to %" PRIu16
".%" PRIu16,
895 rdpdr_component_string(RDPDR_CTYP_CORE),
896 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM),
897 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor,
899 rdpdr->common.versionMajor = versionMajor;
900 rdpdr->common.versionMinor = versionMinor;
903 if (clientID != rdpdr->common.clientID)
905 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
906 "[%s | %s] clientID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
907 rdpdr_component_string(RDPDR_CTYP_CORE),
908 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM), rdpdr->common.clientID,
910 rdpdr->common.clientID = clientID;
913 return CHANNEL_RC_OK;
918rdpdr_process_server_capability_request_or_clientid_confirm(pf_channel_client_context* rdpdr,
921 const UINT32 mask = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM |
922 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
923 const UINT16 rcomponent = RDPDR_CTYP_CORE;
924 UINT16 component = 0;
930 if ((rdpdr->flags & mask) == mask)
932 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"already past this state, abort!");
936 if (!Stream_CheckAndLogRequiredLengthClient(rdpdr->log, s, 4))
939 Stream_Read_UINT16(s, component);
940 if (rcomponent != component)
942 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got component %s, expected %s",
943 rdpdr_component_string(component), rdpdr_component_string(rcomponent));
946 Stream_Read_UINT16(s, packetid);
951 case PAKID_CORE_SERVER_CAPABILITY:
952 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST)
954 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
955 rdpdr_packetid_string(packetid));
958 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
959 return rdpdr_process_server_core_capability_request(rdpdr, s) == CHANNEL_RC_OK;
960 case PAKID_CORE_CLIENTID_CONFIRM:
962 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM)
964 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
965 rdpdr_packetid_string(packetid));
968 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
969 return rdpdr_process_server_clientid_confirm(rdpdr, s) == CHANNEL_RC_OK;
973#if defined(WITH_PROXY_EMULATE_SMARTCARD)
975static UINT rdpdr_send_emulated_scard_device_list_announce_request(pClientContext* pc,
976 pf_channel_client_context* rdpdr)
980 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_ANNOUNCE, 24);
982 return CHANNEL_RC_NO_MEMORY;
984 Stream_Write_UINT32(s, 1);
985 Stream_Write_UINT32(s, RDPDR_DTYP_SMARTCARD);
988 Stream_Write(s,
"SCARD\0\0\0", 8);
989 Stream_Write_UINT32(s, 6);
990 Stream_Write(s,
"SCARD\0", 6);
992 return rdpdr_client_send(rdpdr->log, pc, s);
996static UINT rdpdr_send_emulated_scard_device_remove(pClientContext* pc,
997 pf_channel_client_context* rdpdr)
1001 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_REMOVE, 24);
1003 return CHANNEL_RC_NO_MEMORY;
1005 Stream_Write_UINT32(s, 1);
1006 Stream_Write_UINT32(
1007 s, SCARD_DEVICE_ID);
1009 return rdpdr_client_send(rdpdr->log, pc, s);
1013static UINT rdpdr_process_server_device_announce_response(pf_channel_client_context* rdpdr,
1016 const UINT16 component = RDPDR_CTYP_CORE;
1017 const UINT16 packetid = PAKID_CORE_DEVICE_REPLY;
1018 UINT32 deviceID = 0;
1019 UINT32 resultCode = 0;
1021 WINPR_ASSERT(rdpdr);
1024 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
1025 return ERROR_INVALID_DATA;
1027 Stream_Read_UINT32(s, deviceID);
1028 Stream_Read_UINT32(s, resultCode);
1030 if (deviceID != SCARD_DEVICE_ID)
1032 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1033 "[%s | %s] deviceID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
1034 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1035 SCARD_DEVICE_ID, deviceID);
1037 else if (resultCode != 0)
1039 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1040 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32,
1041 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1045 CLIENT_RX_LOG(rdpdr->log, WLOG_DEBUG,
1046 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32
1047 " -> emulated smartcard redirected!",
1048 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1051 return CHANNEL_RC_OK;
1056static BOOL pf_channel_rdpdr_rewrite_device_list_to(
wStream* s, UINT32 fromVersion,
1060 if (fromVersion == toVersion)
1063 const size_t cap = Stream_GetRemainingLength(s);
1064 wStream* clone = Stream_New(
nullptr, cap);
1069 const size_t pos = Stream_GetPosition(s);
1070 Stream_Copy(s, clone, cap);
1071 Stream_SealLength(clone);
1073 Stream_ResetPosition(clone);
1074 if (!Stream_SetPosition(s, pos))
1079 if (!Stream_SafeSeek(s, 4))
1084 if (Stream_GetRemainingLength(clone) < 4)
1086 Stream_Read_UINT32(clone, count);
1088 for (UINT32 x = 0; x < count; x++)
1091 const size_t charCount = ARRAYSIZE(device.PreferredDosName);
1092 if (Stream_GetRemainingLength(clone) < 20)
1095 Stream_Read_UINT32(clone, device.DeviceType);
1096 Stream_Read_UINT32(clone, device.DeviceId);
1097 Stream_Read(clone, device.PreferredDosName, charCount);
1098 Stream_Read_UINT32(clone, device.DeviceDataLength);
1099 device.DeviceData = Stream_Pointer(clone);
1100 if (!Stream_SafeSeek(clone, device.DeviceDataLength))
1103 if (!Stream_EnsureRemainingCapacity(s, 20))
1105 Stream_Write_UINT32(s, device.DeviceType);
1106 Stream_Write_UINT32(s, device.DeviceId);
1107 Stream_Write(s, device.PreferredDosName, charCount);
1109 if (device.DeviceType == RDPDR_DTYP_FILESYSTEM)
1111 if (toVersion == DRIVE_CAPABILITY_VERSION_01)
1112 Stream_Write_UINT32(s, 0);
1115 const size_t datalen = charCount *
sizeof(WCHAR);
1116 if (!Stream_EnsureRemainingCapacity(s, datalen +
sizeof(UINT32)))
1118 Stream_Write_UINT32(s, WINPR_ASSERTING_INT_CAST(uint32_t, datalen));
1120 const SSIZE_T rcw = Stream_Write_UTF16_String_From_UTF8(
1121 s, charCount, device.PreferredDosName, charCount - 1, TRUE);
1128 Stream_Write_UINT32(s, device.DeviceDataLength);
1129 if (!Stream_EnsureRemainingCapacity(s, device.DeviceDataLength))
1131 Stream_Write(s, device.DeviceData, device.DeviceDataLength);
1136 Stream_SealLength(s);
1140 Stream_Free(clone, TRUE);
1145static BOOL pf_channel_rdpdr_rewrite_device_list(pf_channel_client_context* rdpdr,
1146 pServerContext* ps,
wStream* s, BOOL toServer)
1148 WINPR_ASSERT(rdpdr);
1151 const size_t pos = Stream_GetPosition(s);
1152 UINT16 component = 0;
1153 UINT16 packetid = 0;
1154 Stream_ResetPosition(s);
1156 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1159 Stream_Read_UINT16(s, component);
1160 Stream_Read_UINT16(s, packetid);
1161 if ((component != RDPDR_CTYP_CORE) || (packetid != PAKID_CORE_DEVICELIST_ANNOUNCE))
1162 return Stream_SetPosition(s, pos);
1164 const pf_channel_server_context* srv =
1165 HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1168 WLog_Print(rdpdr->log, WLOG_ERROR,
"No channel %s in intercep map", RDPDR_SVC_CHANNEL_NAME);
1172 UINT32 from = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1173 UINT32 to = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1176 from = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1177 to = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1179 if (!pf_channel_rdpdr_rewrite_device_list_to(s, from, to))
1182 return Stream_SetPosition(s, pos);
1186static BOOL pf_channel_rdpdr_client_send_to_server(pf_channel_client_context* rdpdr,
1187 pServerContext* ps,
wStream* s)
1189 WINPR_ASSERT(rdpdr);
1192 UINT16 server_channel_id = WTSChannelGetId(ps->context.peer, RDPDR_SVC_CHANNEL_NAME);
1197 if (server_channel_id == 0)
1200 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, TRUE))
1202 size_t len = Stream_Length(s);
1203 if (!Stream_SetPosition(s, len))
1204 return ERROR_INVALID_DATA;
1205 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_tx);
1206 WINPR_ASSERT(ps->context.peer);
1207 WINPR_ASSERT(ps->context.peer->SendChannelData);
1208 return ps->context.peer->SendChannelData(ps->context.peer, server_channel_id,
1209 Stream_Buffer(s), len);
1215static BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr);
1217#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1219static BOOL rdpdr_process_server_loggedon_request(pServerContext* ps, pClientContext* pc,
1220 pf_channel_client_context* rdpdr,
wStream* s,
1221 UINT16 component, UINT16 packetid)
1223 WINPR_ASSERT(rdpdr);
1224 WLog_Print(rdpdr->log, WLOG_DEBUG,
"[%s | %s]", rdpdr_component_string(component),
1225 rdpdr_packetid_string(packetid));
1226 if (rdpdr_send_emulated_scard_device_remove(pc, rdpdr) != CHANNEL_RC_OK)
1228 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) != CHANNEL_RC_OK)
1230 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1234static BOOL filter_smartcard_io_requests(pf_channel_client_context* rdpdr,
wStream* s,
1238 UINT16 component = 0;
1239 UINT16 packetid = 0;
1240 UINT32 deviceID = 0;
1243 WINPR_ASSERT(rdpdr);
1244 WINPR_ASSERT(pPacketid);
1246 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1249 pos = Stream_GetPosition(s);
1250 Stream_Read_UINT16(s, component);
1251 Stream_Read_UINT16(s, packetid);
1253 if (Stream_GetRemainingLength(s) >= 4)
1254 Stream_Read_UINT32(s, deviceID);
1256 WLog_Print(rdpdr->log, WLOG_DEBUG,
"got: [%s | %s]: [0x%08" PRIx32
"]",
1257 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID);
1259 if (component != RDPDR_CTYP_CORE)
1264 case PAKID_CORE_SERVER_ANNOUNCE:
1265 case PAKID_CORE_CLIENTID_CONFIRM:
1266 case PAKID_CORE_CLIENT_NAME:
1267 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1268 case PAKID_CORE_DEVICELIST_REMOVE:
1269 case PAKID_CORE_SERVER_CAPABILITY:
1270 case PAKID_CORE_CLIENT_CAPABILITY:
1271 WLog_Print(rdpdr->log, WLOG_WARN,
"Filtering client -> server message [%s | %s]",
1272 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1273 *pPacketid = packetid;
1275 case PAKID_CORE_USER_LOGGEDON:
1276 *pPacketid = packetid;
1278 case PAKID_CORE_DEVICE_REPLY:
1279 case PAKID_CORE_DEVICE_IOREQUEST:
1280 if (deviceID != SCARD_DEVICE_ID)
1282 *pPacketid = packetid;
1285 if (deviceID != SCARD_DEVICE_ID)
1287 WLog_Print(rdpdr->log, WLOG_WARN,
1288 "Got [%s | %s] for deviceID 0x%08" PRIx32
", TODO: Not handled!",
1289 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1297 if (!Stream_SetPosition(s, pos))
1303BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr)
1306 WINPR_ASSERT(rdpdr);
1308 if (rdpdr->state != STATE_CLIENT_CHANNEL_RUNNING)
1310 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
"Client RDPDR channel not ready, dropping packet!");
1314 const UINT16 channelId =
1315 freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
1316 if ((channelId == 0) || (channelId == UINT16_MAX))
1318 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
1319 "Client RDPDR channel not available, dropping packet!");
1323 Queue_Lock(rdpdr->queue);
1324 while (Queue_Count(rdpdr->queue) > 0)
1326 wStream* s = Queue_Dequeue(rdpdr->queue);
1330 size_t len = Stream_Length(s);
1331 if (!Stream_SetPosition(s, len))
1333 Stream_Free(s, TRUE);
1337 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_tx
" (queue) ");
1338 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
1339 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
1340 Stream_Buffer(s), len))
1342 CLIENT_TX_LOG(rdpdr->log, WLOG_ERROR,
"xxxxxx TODO: Failed to send data!");
1344 Stream_Free(s, TRUE);
1346 Queue_Unlock(rdpdr->queue);
1351static BOOL rdpdr_handle_server_announce_request(pClientContext* pc,
1352 pf_channel_client_context* rdpdr,
wStream* s)
1355 WINPR_ASSERT(rdpdr);
1358 if (rdpdr_process_server_announce_request(rdpdr, s) != CHANNEL_RC_OK)
1360 if (rdpdr_send_client_announce_reply(pc, rdpdr) != CHANNEL_RC_OK)
1362 if (rdpdr_send_client_name_request(pc, rdpdr) != CHANNEL_RC_OK)
1364 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1368BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId,
const char* channel_name,
1369 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1371#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1372 UINT16 packetid = 0;
1376 WINPR_ASSERT(pc->pdata);
1377 WINPR_ASSERT(pc->interceptContextMap);
1378 WINPR_ASSERT(channel_name);
1379 WINPR_ASSERT(xdata);
1381 pServerContext* ps = proxy_data_get_server_context(pc->pdata);
1383 pf_channel_client_context* rdpdr =
1384 HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1387 CLIENT_RX_LOG(WLog_Get(RTAG), WLOG_ERROR,
1388 "Channel %s [0x%04" PRIx16
"] missing context in interceptContextMap",
1389 channel_name, channelId);
1393 wStream* s = rdpdr->common.buffer;
1394 if (flags & CHANNEL_FLAG_FIRST)
1395 Stream_ResetPosition(s);
1396 if (!Stream_EnsureRemainingCapacity(s, xsize))
1398 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1399 "Channel %s [0x%04" PRIx16
"] not enough memory [need %" PRIuz
"]",
1400 channel_name, channelId, xsize);
1403 Stream_Write(s, xdata, xsize);
1404 if ((flags & CHANNEL_FLAG_LAST) == 0)
1407 Stream_SealLength(s);
1408 Stream_ResetPosition(s);
1409 if (Stream_Length(s) != totalSize)
1411 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1412 "Received invalid %s channel data (server -> proxy), expected %" PRIuz
1413 "bytes, got %" PRIuz,
1414 channel_name, totalSize, Stream_Length(s));
1418 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_rx);
1419 switch (rdpdr->state)
1421 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
1422 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1425 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
1426 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1428 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
1430 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
1431 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1433 if (rdpdr_send_client_capability_response(pc, rdpdr) != CHANNEL_RC_OK)
1435#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1436 if (pf_channel_smartcard_client_emulate(pc))
1438 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) !=
1441 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1446 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1447 if (!pf_channel_send_client_queue(pc, rdpdr))
1452 case STATE_CLIENT_CHANNEL_RUNNING:
1453#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1454 if (!pf_channel_smartcard_client_emulate(pc) ||
1455 !filter_smartcard_io_requests(rdpdr, s, &packetid))
1456 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1461 case PAKID_CORE_USER_LOGGEDON:
1462 return rdpdr_process_server_loggedon_request(ps, pc, rdpdr, s,
1463 RDPDR_CTYP_CORE, packetid);
1464 case PAKID_CORE_DEVICE_IOREQUEST:
1466 wStream* out = rdpdr_client_get_send_buffer(
1467 rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOCOMPLETION, 0);
1470 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
1471 PAKID_CORE_DEVICE_IOREQUEST, 20))
1474 if (!pf_channel_smartcard_client_handle(rdpdr->log, pc, s, out,
1479 case PAKID_CORE_SERVER_ANNOUNCE:
1480 pf_channel_rdpdr_client_reset(pc);
1481 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1484 case PAKID_CORE_SERVER_CAPABILITY:
1485 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1487 return pf_channel_rdpdr_client_handle(pc, channelId, channel_name, xdata,
1488 xsize, flags, totalSize);
1489 case PAKID_CORE_DEVICE_REPLY:
1493 rdpdr->log, WLOG_ERROR,
1494 "Channel %s [0x%04" PRIx16
1495 "] we´ve reached an impossible state %s! [%s] aliens invaded!",
1496 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state),
1497 rdpdr_packetid_string(packetid));
1503 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1506 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1507 "Channel %s [0x%04" PRIx16
1508 "] we´ve reached an impossible state %s! aliens invaded!",
1509 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state));
1516static void pf_channel_rdpdr_common_context_free(pf_channel_common_context* common)
1520 free(common->computerName.v);
1521 Stream_Free(common->s, TRUE);
1522 Stream_Free(common->buffer, TRUE);
1527 pf_channel_client_context* entry = (pf_channel_client_context*)base;
1531 pf_channel_rdpdr_common_context_free(&entry->common);
1532 Queue_Free(entry->queue);
1533 WLog_Discard(entry->log);
1538static BOOL pf_channel_rdpdr_common_context_new(pf_channel_common_context* common,
1543 common->base.free = fkt;
1544 common->s = Stream_New(
nullptr, 1024);
1547 common->buffer = Stream_New(
nullptr, 1024);
1548 if (!common->buffer)
1550 common->computerNameUnicode = 1;
1551 common->computerName.v =
nullptr;
1552 common->versionMajor = RDPDR_VERSION_MAJOR;
1553 common->versionMinor = RDPDR_VERSION_MINOR_RDP10X;
1554 common->clientID = SCARD_DEVICE_ID;
1556 const UINT32 versions[] = { 0,
1557 GENERAL_CAPABILITY_VERSION_02,
1558 PRINT_CAPABILITY_VERSION_01,
1559 PORT_CAPABILITY_VERSION_01,
1560 DRIVE_CAPABILITY_VERSION_02,
1561 SMARTCARD_CAPABILITY_VERSION_01 };
1563 memcpy(common->capabilityVersions, versions,
sizeof(common->capabilityVersions));
1568static BOOL pf_channel_rdpdr_client_pass_message(pServerContext* ps, pClientContext* pc,
1569 WINPR_ATTR_UNUSED UINT16 channelId,
1570 const char* channel_name,
wStream* s)
1572 pf_channel_client_context* rdpdr =
nullptr;
1577 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1580 WINPR_ASSERT(rdpdr->queue);
1582 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, FALSE))
1584 if (!Queue_Enqueue(rdpdr->queue, s))
1586 return pf_channel_send_client_queue(pc, rdpdr);
1589#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1591static BOOL filter_smartcard_device_list_remove(pf_channel_server_context* rdpdr,
wStream* s)
1596 WINPR_ASSERT(rdpdr);
1597 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1599 pos = Stream_GetPosition(s);
1600 Stream_Read_UINT32(s, count);
1605 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdpdr->log, s, count,
sizeof(UINT32)))
1608 for (UINT32 x = 0; x < count; x++)
1610 UINT32 deviceID = 0;
1611 BYTE* dst = Stream_Pointer(s);
1612 Stream_Read_UINT32(s, deviceID);
1613 if (deviceID == SCARD_DEVICE_ID)
1615 ArrayList_Remove(rdpdr->blockedDevices, (
void*)(
size_t)deviceID);
1622 memmove(dst, Stream_ConstPointer(s), (count - x - 1) *
sizeof(UINT32));
1625 if (Stream_SetPosition(s, pos))
1626 Stream_Write_UINT32(s, count);
1635static BOOL filter_smartcard_device_io_request(pf_channel_server_context* rdpdr,
wStream* s)
1637 UINT32 DeviceID = 0;
1638 WINPR_ASSERT(rdpdr);
1640 Stream_Read_UINT32(s, DeviceID);
1641 return ArrayList_Contains(rdpdr->blockedDevices, (
void*)(
size_t)DeviceID);
1645static BOOL filter_smartcard_device_list_announce(pf_channel_server_context* rdpdr,
wStream* s)
1649 WINPR_ASSERT(rdpdr);
1650 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1652 const size_t pos = Stream_GetPosition(s);
1653 Stream_Read_UINT32(s, count);
1658 for (UINT32 x = 0; x < count; x++)
1660 UINT32 DeviceType = 0;
1661 UINT32 DeviceId = 0;
1662 char PreferredDosName[8];
1663 UINT32 DeviceDataLength = 0;
1664 BYTE* dst = Stream_Pointer(s);
1665 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 20))
1667 Stream_Read_UINT32(s, DeviceType);
1668 Stream_Read_UINT32(s, DeviceId);
1669 Stream_Read(s, PreferredDosName, ARRAYSIZE(PreferredDosName));
1670 Stream_Read_UINT32(s, DeviceDataLength);
1671 if (!Stream_SafeSeek(s, DeviceDataLength))
1673 if (DeviceType == RDPDR_DTYP_SMARTCARD)
1675 if (!ArrayList_Append(rdpdr->blockedDevices, (
void*)(
size_t)DeviceId))
1680 WLog_Print(rdpdr->log, WLOG_INFO,
"Filtering smartcard device 0x%08" PRIx32
"",
1683 memmove(dst, Stream_ConstPointer(s), Stream_GetRemainingLength(s));
1684 if (Stream_SetPosition(s, pos))
1685 Stream_Write_UINT32(s, count - 1);
1694static BOOL filter_smartcard_device_list_announce_request(pf_channel_server_context* rdpdr,
1699 UINT16 component = 0;
1700 UINT16 packetid = 0;
1702 WINPR_ASSERT(rdpdr);
1703 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8))
1706 pos = Stream_GetPosition(s);
1708 Stream_Read_UINT16(s, component);
1709 Stream_Read_UINT16(s, packetid);
1711 if (component != RDPDR_CTYP_CORE)
1716 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1717 if (filter_smartcard_device_list_announce(rdpdr, s))
1720 case PAKID_CORE_DEVICELIST_REMOVE:
1721 if (filter_smartcard_device_list_remove(rdpdr, s))
1724 case PAKID_CORE_DEVICE_IOREQUEST:
1725 if (filter_smartcard_device_io_request(rdpdr, s))
1729 case PAKID_CORE_SERVER_ANNOUNCE:
1730 case PAKID_CORE_CLIENTID_CONFIRM:
1731 case PAKID_CORE_CLIENT_NAME:
1732 case PAKID_CORE_DEVICE_REPLY:
1733 case PAKID_CORE_SERVER_CAPABILITY:
1734 case PAKID_CORE_CLIENT_CAPABILITY:
1735 case PAKID_CORE_USER_LOGGEDON:
1736 WLog_Print(rdpdr->log, WLOG_WARN,
"Filtering client -> server message [%s | %s]",
1737 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1745 if (!Stream_SetPosition(s, pos))
1751WINPR_ATTR_MALLOC(Stream_Free, 1)
1753static
void* stream_copy(const
void* obj)
1756 wStream* dst = Stream_New(
nullptr, Stream_Capacity(src));
1759 memcpy(Stream_Buffer(dst), Stream_ConstBuffer(src), Stream_Capacity(dst));
1760 if (!Stream_SetLength(dst, Stream_Length(src)))
1762 if (!Stream_SetPosition(dst, Stream_GetPosition(src)))
1766 Stream_Free(dst, TRUE);
1770static void stream_free(
void* obj)
1773 Stream_Free(s, TRUE);
1777static const char* pf_channel_rdpdr_client_context(
void* arg)
1779 pClientContext* pc = arg;
1783 return "pc->pdata=null";
1784 return pc->pdata->session_id;
1787BOOL pf_channel_rdpdr_client_new(pClientContext* pc)
1790 pf_channel_client_context* rdpdr =
nullptr;
1793 WINPR_ASSERT(pc->interceptContextMap);
1795 rdpdr = calloc(1,
sizeof(pf_channel_client_context));
1798 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1802 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_client_context, pc))
1805 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_client_context_free))
1808 rdpdr->maxMajorVersion = RDPDR_VERSION_MAJOR;
1809 rdpdr->maxMinorVersion = RDPDR_VERSION_MINOR_RDP10X;
1810 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
1812 rdpdr->queue = Queue_New(TRUE, 0, 0);
1815 obj = Queue_Object(rdpdr->queue);
1819 if (!HashTable_Insert(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1824 pf_channel_rdpdr_client_context_free(&rdpdr->common.base);
1828void pf_channel_rdpdr_client_free(pClientContext* pc)
1831 WINPR_ASSERT(pc->interceptContextMap);
1832 HashTable_Remove(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1837 pf_channel_server_context* entry = (pf_channel_server_context*)base;
1841 (void)WTSVirtualChannelClose(entry->handle);
1842 pf_channel_rdpdr_common_context_free(&entry->common);
1843 ArrayList_Free(entry->blockedDevices);
1844 WLog_Discard(entry->log);
1849static const char* pf_channel_rdpdr_server_context(
void* arg)
1851 pServerContext* ps = arg;
1855 return "ps->pdata=null";
1856 return ps->pdata->session_id;
1859BOOL pf_channel_rdpdr_server_new(pServerContext* ps)
1861 pf_channel_server_context* rdpdr =
nullptr;
1862 PULONG pSessionId =
nullptr;
1863 DWORD BytesReturned = 0;
1866 WINPR_ASSERT(ps->interceptContextMap);
1868 rdpdr = calloc(1,
sizeof(pf_channel_server_context));
1871 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1875 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_server_context, ps))
1878 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_server_context_free))
1880 rdpdr->state = STATE_SERVER_INITIAL;
1882 rdpdr->blockedDevices = ArrayList_New(FALSE);
1883 if (!rdpdr->blockedDevices)
1886 rdpdr->SessionId = WTS_CURRENT_SESSION;
1887 if (WTSQuerySessionInformationA(ps->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*)&pSessionId,
1890 rdpdr->SessionId = (DWORD)*pSessionId;
1891 WTSFreeMemory(pSessionId);
1894 rdpdr->handle = WTSVirtualChannelOpenEx(rdpdr->SessionId, RDPDR_SVC_CHANNEL_NAME, 0);
1895 if (rdpdr->handle ==
nullptr)
1897 if (!HashTable_Insert(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1903 pf_channel_rdpdr_server_context_free(&rdpdr->common.base);
1907void pf_channel_rdpdr_server_free(pServerContext* ps)
1910 WINPR_ASSERT(ps->interceptContextMap);
1911 HashTable_Remove(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1915static pf_channel_server_context* get_channel(pServerContext* ps, BOOL send)
1917 pf_channel_server_context* rdpdr =
nullptr;
1919 WINPR_ASSERT(ps->interceptContextMap);
1921 rdpdr = HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1924 SERVER_RXTX_LOG(send, WLog_Get(RTAG), WLOG_ERROR,
1925 "Channel %s missing context in interceptContextMap",
1926 RDPDR_SVC_CHANNEL_NAME);
1933BOOL pf_channel_rdpdr_server_handle(pServerContext* ps, UINT16 channelId,
const char* channel_name,
1934 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1936 pf_channel_server_context* rdpdr = get_channel(ps, FALSE);
1940 WINPR_ASSERT(ps->pdata);
1941 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
1943 wStream* s = rdpdr->common.buffer;
1945 if (flags & CHANNEL_FLAG_FIRST)
1946 Stream_ResetPosition(s);
1948 if (!Stream_EnsureRemainingCapacity(s, xsize))
1950 Stream_Write(s, xdata, xsize);
1952 if ((flags & CHANNEL_FLAG_LAST) == 0)
1955 Stream_SealLength(s);
1956 Stream_ResetPosition(s);
1958 if (Stream_Length(s) != totalSize)
1960 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
1961 "Received invalid %s channel data (client -> proxy), expected %" PRIuz
1962 "bytes, got %" PRIuz,
1963 channel_name, totalSize, Stream_Length(s));
1967 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_rx);
1968 switch (rdpdr->state)
1970 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
1971 if (rdpdr_process_client_announce_reply(rdpdr, s) != CHANNEL_RC_OK)
1973 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST;
1975 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
1976 if (rdpdr_process_client_name_request(rdpdr, s, pc) != CHANNEL_RC_OK)
1978 if (rdpdr_send_server_capability_request(rdpdr) != CHANNEL_RC_OK)
1980 if (rdpdr_send_server_clientid_confirm(rdpdr) != CHANNEL_RC_OK)
1982 rdpdr->state = STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE;
1984 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
1985 if (rdpdr_process_client_capability_response(rdpdr, s) != CHANNEL_RC_OK)
1987 rdpdr->state = STATE_SERVER_CHANNEL_RUNNING;
1989 case STATE_SERVER_CHANNEL_RUNNING:
1990#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1991 if (!pf_channel_smartcard_client_emulate(pc) ||
1992 !filter_smartcard_device_list_announce_request(rdpdr, s))
1994 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
1998 return pf_channel_smartcard_server_handle(ps, s);
2000 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2005 case STATE_SERVER_INITIAL:
2006 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
"Invalid state %s",
2007 rdpdr_server_state_to_string(rdpdr->state));
2014BOOL pf_channel_rdpdr_server_announce(pServerContext* ps)
2016 pf_channel_server_context* rdpdr = get_channel(ps, TRUE);
2020 WINPR_ASSERT(rdpdr->state == STATE_SERVER_INITIAL);
2021 if (rdpdr_server_send_announce_request(rdpdr) != CHANNEL_RC_OK)
2023 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY;
2027BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
2029 pf_channel_client_context* rdpdr =
nullptr;
2032 WINPR_ASSERT(pc->pdata);
2033 WINPR_ASSERT(pc->interceptContextMap);
2035 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
2039 Queue_Clear(rdpdr->queue);
2041 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
2047static PfChannelResult pf_rdpdr_back_data(proxyData* pdata,
2048 const pServerStaticChannelContext* channel,
2049 const BYTE* xdata,
size_t xsize, UINT32 flags,
2052 WINPR_ASSERT(pdata);
2053 WINPR_ASSERT(channel);
2055 pClientContext* pc = proxy_data_get_client_context(pdata);
2056 if (!pf_channel_rdpdr_client_handle(pc,
2057 WINPR_ASSERTING_INT_CAST(UINT16, channel->back_channel_id),
2058 channel->channel_name, xdata, xsize, flags, totalSize))
2059 return PF_CHANNEL_RESULT_ERROR;
2061#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2062 if (pf_channel_smartcard_client_emulate(pdata->pc))
2063 return PF_CHANNEL_RESULT_DROP;
2065 return PF_CHANNEL_RESULT_DROP;
2069static PfChannelResult pf_rdpdr_front_data(proxyData* pdata,
2070 const pServerStaticChannelContext* channel,
2071 const BYTE* xdata,
size_t xsize, UINT32 flags,
2074 WINPR_ASSERT(pdata);
2075 WINPR_ASSERT(channel);
2077 pServerContext* ps = proxy_data_get_server_context(pdata);
2078 if (!pf_channel_rdpdr_server_handle(ps,
2079 WINPR_ASSERTING_INT_CAST(UINT16, channel->front_channel_id),
2080 channel->channel_name, xdata, xsize, flags, totalSize))
2081 return PF_CHANNEL_RESULT_ERROR;
2083#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2084 if (pf_channel_smartcard_client_emulate(pdata->pc))
2085 return PF_CHANNEL_RESULT_DROP;
2087 return PF_CHANNEL_RESULT_DROP;
2090BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
2092 channel->onBackData = pf_rdpdr_back_data;
2093 channel->onFrontData = pf_rdpdr_front_data;
2095 if (!pf_channel_rdpdr_server_new(ps))
2097 if (!pf_channel_rdpdr_server_announce(ps))
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew