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_channel_rdpdr.h"
29#include "pf_channel_smartcard.h"
31#include <freerdp/server/proxy/proxy_log.h>
32#include <freerdp/channels/rdpdr.h>
33#include <freerdp/channels/channels.h>
34#include <freerdp/utils/rdpdr_utils.h>
36#define RTAG PROXY_TAG("channel.rdpdr")
38#define SCARD_DEVICE_ID UINT32_MAX
48 UINT32 computerNameLen;
49 BOOL computerNameUnicode;
56 UINT32 SpecialDeviceCount;
57 UINT32 capabilityVersions[6];
58} pf_channel_common_context;
62 STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST = 0x01,
63 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST = 0x02,
64 STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM = 0x04,
65 STATE_CLIENT_CHANNEL_RUNNING = 0x10
66} pf_channel_client_state;
70 pf_channel_common_context common;
71 pf_channel_client_state state;
73 UINT16 maxMajorVersion;
74 UINT16 maxMinorVersion;
77} pf_channel_client_context;
82 STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY,
83 STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST,
84 STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE,
85 STATE_SERVER_CHANNEL_RUNNING
86} pf_channel_server_state;
90 pf_channel_common_context common;
91 pf_channel_server_state state;
94 wArrayList* blockedDevices;
96} pf_channel_server_context;
98#define proxy_client "[proxy<-->client]"
99#define proxy_server "[proxy<-->server]"
101#define proxy_client_rx proxy_client " receive"
102#define proxy_client_tx proxy_client " send"
103#define proxy_server_rx proxy_server " receive"
104#define proxy_server_tx proxy_server " send"
106#define SERVER_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_rx fmt, ##__VA_ARGS__)
107#define CLIENT_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_rx fmt, ##__VA_ARGS__)
108#define SERVER_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_tx fmt, ##__VA_ARGS__)
109#define CLIENT_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_tx fmt, ##__VA_ARGS__)
110#define RX_LOG(srv, lvl, fmt, ...) \
115 SERVER_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
119 CLIENT_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
123#define SERVER_RXTX_LOG(send, log, lvl, fmt, ...) \
128 SERVER_TX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
132 SERVER_RX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
136#define Stream_CheckAndLogRequiredLengthSrv(log, s, len) \
137 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
138 proxy_client_rx " %s(%s:%" PRIuz ")", __func__, \
139 __FILE__, (size_t)__LINE__)
140#define Stream_CheckAndLogRequiredLengthClient(log, s, len) \
141 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
142 proxy_server_rx " %s(%s:%" PRIuz ")", __func__, \
143 __FILE__, (size_t)__LINE__)
144#define Stream_CheckAndLogRequiredLengthRx(srv, log, s, len) \
145 Stream_CheckAndLogRequiredLengthRx_(srv, log, s, len, 1, __func__, __FILE__, __LINE__)
147static BOOL Stream_CheckAndLogRequiredLengthRx_(BOOL srv, wLog* log,
wStream* s,
size_t nmemb,
148 size_t size,
const char* fkt,
const char* file,
152 srv ? proxy_server_rx
" %s(%s:%" PRIuz
")" : proxy_client_rx
" %s(%s:%" PRIuz
")";
154 return Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, fmt, fkt, file,
159static const char* rdpdr_server_state_to_string(pf_channel_server_state state)
163 case STATE_SERVER_INITIAL:
164 return "STATE_SERVER_INITIAL";
165 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
166 return "STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY";
167 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
168 return "STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST";
169 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
170 return "STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE";
171 case STATE_SERVER_CHANNEL_RUNNING:
172 return "STATE_SERVER_CHANNEL_RUNNING";
174 return "STATE_SERVER_UNKNOWN";
179static const char* rdpdr_client_state_to_string(pf_channel_client_state state)
183 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
184 return "STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST";
185 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
186 return "STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST";
187 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
188 return "STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM";
189 case STATE_CLIENT_CHANNEL_RUNNING:
190 return "STATE_CLIENT_CHANNEL_RUNNING";
192 return "STATE_CLIENT_UNKNOWN";
197static wStream* rdpdr_get_send_buffer(pf_channel_common_context* rdpdr, UINT16 component,
198 UINT16 PacketID,
size_t capacity)
201 WINPR_ASSERT(rdpdr->s);
202 if (!Stream_SetPosition(rdpdr->s, 0))
204 if (!Stream_EnsureCapacity(rdpdr->s, capacity + 4))
206 Stream_Write_UINT16(rdpdr->s, component);
207 Stream_Write_UINT16(rdpdr->s, PacketID);
212static wStream* rdpdr_client_get_send_buffer(pf_channel_client_context* rdpdr, UINT16 component,
213 UINT16 PacketID,
size_t capacity)
216 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
220static wStream* rdpdr_server_get_send_buffer(pf_channel_server_context* rdpdr, UINT16 component,
221 UINT16 PacketID,
size_t capacity)
224 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
228static UINT rdpdr_client_send(wLog* log, pClientContext* pc,
wStream* s)
230 UINT16 channelId = 0;
235 WINPR_ASSERT(pc->context.instance);
239 CLIENT_TX_LOG(log, WLOG_WARN,
"Ignoring channel %s message, not connected!",
240 RDPDR_SVC_CHANNEL_NAME);
241 return CHANNEL_RC_OK;
244 channelId = freerdp_channels_get_id_by_name(pc->context.instance, RDPDR_SVC_CHANNEL_NAME);
247 if ((channelId == 0) || (channelId == UINT16_MAX))
248 return ERROR_INTERNAL_ERROR;
250 Stream_SealLength(s);
251 rdpdr_dump_send_packet(log, WLOG_TRACE, s, proxy_server_tx);
252 WINPR_ASSERT(pc->context.instance->SendChannelData);
253 if (!pc->context.instance->SendChannelData(pc->context.instance, channelId, Stream_Buffer(s),
255 return ERROR_EVT_CHANNEL_NOT_FOUND;
256 return CHANNEL_RC_OK;
260static UINT rdpdr_seal_send_free_request(pf_channel_server_context* context,
wStream* s)
265 WINPR_ASSERT(context);
266 WINPR_ASSERT(context->handle);
269 Stream_SealLength(s);
270 len = Stream_Length(s);
271 WINPR_ASSERT(len <= UINT32_MAX);
273 rdpdr_dump_send_packet(context->log, WLOG_TRACE, s, proxy_client_tx);
274 status = WTSVirtualChannelWrite(context->handle, Stream_BufferAs(s,
char), (ULONG)len,
nullptr);
275 return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
279static BOOL rdpdr_process_server_header(BOOL server, wLog* log,
wStream* s, UINT16 component,
280 UINT16 PacketId,
size_t expect)
282 UINT16 rpacketid = 0;
283 UINT16 rcomponent = 0;
286 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, 4))
288 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: expected length 4, got %" PRIuz,
289 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
290 Stream_GetRemainingLength(s));
294 Stream_Read_UINT16(s, rcomponent);
295 Stream_Read_UINT16(s, rpacketid);
297 if (rcomponent != component)
299 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got component %s",
300 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
301 rdpdr_component_string(rcomponent));
305 if (rpacketid != PacketId)
307 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got PacketID %s",
308 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
309 rdpdr_packetid_string(rpacketid));
313 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, expect))
315 RX_LOG(server, log, WLOG_WARN,
316 "RDPDR_HEADER[%s | %s] not enough data, expected %" PRIuz
", "
318 rdpdr_component_string(component), rdpdr_packetid_string(PacketId), expect,
319 Stream_GetRemainingLength(s));
320 return ERROR_INVALID_DATA;
327static BOOL rdpdr_check_version(BOOL server, wLog* log, UINT16 versionMajor, UINT16 versionMinor,
328 UINT16 component, UINT16 PacketId)
330 if (versionMajor != RDPDR_VERSION_MAJOR)
332 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] expected MajorVersion %d, got %" PRIu16,
333 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
334 RDPDR_VERSION_MAJOR, versionMajor);
337 switch (versionMinor)
339 case RDPDR_VERSION_MINOR_RDP50:
340 case RDPDR_VERSION_MINOR_RDP51:
341 case RDPDR_VERSION_MINOR_RDP52:
342 case RDPDR_VERSION_MINOR_RDP6X:
343 case RDPDR_VERSION_MINOR_RDP10X:
347 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] unsupported MinorVersion %" PRIu16,
348 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
357static UINT rdpdr_process_server_announce_request(pf_channel_client_context* rdpdr,
wStream* s)
359 const UINT16 component = RDPDR_CTYP_CORE;
360 const UINT16 packetid = PAKID_CORE_SERVER_ANNOUNCE;
364 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, component, packetid, 8))
365 return ERROR_INVALID_DATA;
367 Stream_Read_UINT16(s, rdpdr->common.versionMajor);
368 Stream_Read_UINT16(s, rdpdr->common.versionMinor);
370 if (!rdpdr_check_version(FALSE, rdpdr->log, rdpdr->common.versionMajor,
371 rdpdr->common.versionMinor, component, packetid))
372 return ERROR_INVALID_DATA;
375 if (rdpdr->common.versionMajor > rdpdr->maxMajorVersion)
377 rdpdr->common.versionMajor = rdpdr->maxMajorVersion;
378 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
380 else if (rdpdr->common.versionMinor > rdpdr->maxMinorVersion)
381 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
383 Stream_Read_UINT32(s, rdpdr->common.clientID);
384 return CHANNEL_RC_OK;
388static UINT rdpdr_server_send_announce_request(pf_channel_server_context* context)
391 rdpdr_server_get_send_buffer(context, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_ANNOUNCE, 8);
393 return CHANNEL_RC_NO_MEMORY;
395 Stream_Write_UINT16(s, context->common.versionMajor);
396 Stream_Write_UINT16(s, context->common.versionMinor);
397 Stream_Write_UINT32(s, context->common.clientID);
398 return rdpdr_seal_send_free_request(context, s);
402static UINT rdpdr_process_client_announce_reply(pf_channel_server_context* rdpdr,
wStream* s)
404 const UINT16 component = RDPDR_CTYP_CORE;
405 const UINT16 packetid = PAKID_CORE_CLIENTID_CONFIRM;
406 UINT16 versionMajor = 0;
407 UINT16 versionMinor = 0;
413 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
414 return ERROR_INVALID_DATA;
416 Stream_Read_UINT16(s, versionMajor);
417 Stream_Read_UINT16(s, versionMinor);
419 if (!rdpdr_check_version(TRUE, rdpdr->log, versionMajor, versionMinor, component, packetid))
420 return ERROR_INVALID_DATA;
422 if ((rdpdr->common.versionMajor != versionMajor) ||
423 (rdpdr->common.versionMinor != versionMinor))
426 rdpdr->log, WLOG_WARN,
427 "[%s | %s] downgrading version from %" PRIu16
".%" PRIu16
" to %" PRIu16
".%" PRIu16,
428 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
429 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor, versionMinor);
430 rdpdr->common.versionMajor = versionMajor;
431 rdpdr->common.versionMinor = versionMinor;
433 Stream_Read_UINT32(s, clientID);
434 if (rdpdr->common.clientID != clientID)
436 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
437 "[%s | %s] changing clientID 0x%08" PRIu32
" to 0x%08" PRIu32,
438 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
439 rdpdr->common.clientID, clientID);
440 rdpdr->common.clientID = clientID;
443 return CHANNEL_RC_OK;
447static UINT rdpdr_send_client_announce_reply(pClientContext* pc, pf_channel_client_context* rdpdr)
450 rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
452 return CHANNEL_RC_NO_MEMORY;
454 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
455 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
456 Stream_Write_UINT32(s, rdpdr->common.clientID);
457 return rdpdr_client_send(rdpdr->log, pc, s);
461static UINT rdpdr_process_client_name_request(pf_channel_server_context* rdpdr,
wStream* s,
464 UINT32 unicodeFlag = 0;
471 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
473 return ERROR_INVALID_DATA;
475 Stream_Read_UINT32(s, unicodeFlag);
476 rdpdr->common.computerNameUnicode = ((unicodeFlag & 1) != 0);
478 Stream_Read_UINT32(s, codePage);
479 WINPR_UNUSED(codePage);
480 Stream_Read_UINT32(s, rdpdr->common.computerNameLen);
481 if (!Stream_CheckAndLogRequiredLengthSrv(rdpdr->log, s, rdpdr->common.computerNameLen))
484 rdpdr->log, WLOG_WARN,
"[%s | %s]: missing data, got %" PRIuz
", expected %" PRIu32,
485 rdpdr_component_string(RDPDR_CTYP_CORE), rdpdr_packetid_string(PAKID_CORE_CLIENT_NAME),
486 Stream_GetRemainingLength(s), rdpdr->common.computerNameLen);
487 return ERROR_INVALID_DATA;
489 void* tmp = realloc(rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
491 return CHANNEL_RC_NO_MEMORY;
492 rdpdr->common.computerName.v = tmp;
494 Stream_Read(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
496 pc->computerNameLen = rdpdr->common.computerNameLen;
497 pc->computerNameUnicode = rdpdr->common.computerNameUnicode;
498 tmp = realloc(pc->computerName.v, pc->computerNameLen);
500 return CHANNEL_RC_NO_MEMORY;
501 pc->computerName.v = tmp;
502 memcpy(pc->computerName.v, rdpdr->common.computerName.v, pc->computerNameLen);
504 return CHANNEL_RC_OK;
508static UINT rdpdr_send_client_name_request(pClientContext* pc, pf_channel_client_context* rdpdr)
516 void* tmp = realloc(rdpdr->common.computerName.v, pc->computerNameLen);
518 return CHANNEL_RC_NO_MEMORY;
519 rdpdr->common.computerName.v = tmp;
520 rdpdr->common.computerNameLen = pc->computerNameLen;
521 rdpdr->common.computerNameUnicode = pc->computerNameUnicode;
522 memcpy(rdpdr->common.computerName.v, pc->computerName.v, pc->computerNameLen);
524 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
525 12U + rdpdr->common.computerNameLen);
527 return CHANNEL_RC_NO_MEMORY;
529 Stream_Write_UINT32(s, rdpdr->common.computerNameUnicode
532 Stream_Write_UINT32(s, 0);
533 Stream_Write_UINT32(s, rdpdr->common.computerNameLen);
534 Stream_Write(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
535 return rdpdr_client_send(rdpdr->log, pc, s);
538#define rdpdr_ignore_capset(srv, log, s, header) \
539 rdpdr_ignore_capset_((srv), (log), (s), header, __func__)
541static UINT rdpdr_ignore_capset_(WINPR_ATTR_UNUSED BOOL srv, WINPR_ATTR_UNUSED wLog* log,
543 WINPR_ATTR_UNUSED
const char* fkt)
546 WINPR_ASSERT(header);
548 Stream_Seek(s, header->CapabilityLength);
549 return CHANNEL_RC_OK;
553static UINT rdpdr_client_process_general_capset(pf_channel_client_context* rdpdr,
wStream* s,
557 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
561static UINT rdpdr_process_printer_capset(pf_channel_client_context* rdpdr,
wStream* s,
565 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
569static UINT rdpdr_process_port_capset(pf_channel_client_context* rdpdr,
wStream* s,
573 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
577static UINT rdpdr_process_drive_capset(pf_channel_client_context* rdpdr,
wStream* s,
581 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
585static UINT rdpdr_process_smartcard_capset(pf_channel_client_context* rdpdr,
wStream* s,
589 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
593static UINT rdpdr_process_server_core_capability_request(pf_channel_client_context* rdpdr,
596 UINT status = CHANNEL_RC_OK;
597 UINT16 numCapabilities = 0;
601 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
602 PAKID_CORE_SERVER_CAPABILITY, 4))
603 return ERROR_INVALID_DATA;
605 Stream_Read_UINT16(s, numCapabilities);
608 for (UINT16 i = 0; i < numCapabilities; i++)
611 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
612 if (error != CHANNEL_RC_OK)
615 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
617 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
618 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
620 WLog_Print(rdpdr->log, WLOG_TRACE,
621 "capability %s got version %" PRIu32
", will use version %" PRIu32,
622 rdpdr_cap_type_string(header.CapabilityType), header.Version,
623 rdpdr->common.capabilityVersions[header.CapabilityType]);
626 switch (header.CapabilityType)
628 case CAP_GENERAL_TYPE:
629 status = rdpdr_client_process_general_capset(rdpdr, s, &header);
632 case CAP_PRINTER_TYPE:
633 status = rdpdr_process_printer_capset(rdpdr, s, &header);
637 status = rdpdr_process_port_capset(rdpdr, s, &header);
641 status = rdpdr_process_drive_capset(rdpdr, s, &header);
644 case CAP_SMARTCARD_TYPE:
645 status = rdpdr_process_smartcard_capset(rdpdr, s, &header);
649 WLog_Print(rdpdr->log, WLOG_WARN,
650 "unknown capability 0x%04" PRIx16
", length %" PRIu16
651 ", version %" PRIu32,
652 header.CapabilityType, header.CapabilityLength, header.Version);
653 Stream_Seek(s, header.CapabilityLength);
657 if (status != CHANNEL_RC_OK)
661 return CHANNEL_RC_OK;
665static BOOL rdpdr_write_general_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
671 rdpdr->capabilityVersions[CAP_GENERAL_TYPE] };
672 if (rdpdr_write_capset_header(log, s, &header) != CHANNEL_RC_OK)
674 Stream_Write_UINT32(s, 0);
675 Stream_Write_UINT32(s, 0);
676 Stream_Write_UINT16(s, rdpdr->versionMajor);
677 Stream_Write_UINT16(s, rdpdr->versionMinor);
678 Stream_Write_UINT32(s, 0x0000FFFF);
679 Stream_Write_UINT32(s, 0);
680 Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU |
681 RDPDR_USER_LOGGEDON_PDU);
682 Stream_Write_UINT32(s, ENABLE_ASYNCIO);
683 Stream_Write_UINT32(s, 0);
684 Stream_Write_UINT32(s, rdpdr->SpecialDeviceCount);
690static BOOL rdpdr_write_printer_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
696 rdpdr->capabilityVersions[CAP_PRINTER_TYPE] };
697 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
701static BOOL rdpdr_write_port_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
707 rdpdr->capabilityVersions[CAP_PORT_TYPE] };
708 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
712static BOOL rdpdr_write_drive_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
718 rdpdr->capabilityVersions[CAP_DRIVE_TYPE] };
719 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
723static BOOL rdpdr_write_smartcard_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
729 rdpdr->capabilityVersions[CAP_SMARTCARD_TYPE] };
730 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
734static UINT rdpdr_send_server_capability_request(pf_channel_server_context* rdpdr)
737 rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_CAPABILITY, 8);
739 return CHANNEL_RC_NO_MEMORY;
740 Stream_Write_UINT16(s, 5);
741 Stream_Write_UINT16(s, 0);
742 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
743 return CHANNEL_RC_NO_MEMORY;
744 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
745 return CHANNEL_RC_NO_MEMORY;
746 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
747 return CHANNEL_RC_NO_MEMORY;
748 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
749 return CHANNEL_RC_NO_MEMORY;
750 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
751 return CHANNEL_RC_NO_MEMORY;
752 return rdpdr_seal_send_free_request(rdpdr, s);
756static UINT rdpdr_process_client_capability_response(pf_channel_server_context* rdpdr,
wStream* s)
758 const UINT16 component = RDPDR_CTYP_CORE;
759 const UINT16 packetid = PAKID_CORE_CLIENT_CAPABILITY;
760 UINT status = CHANNEL_RC_OK;
761 UINT16 numCapabilities = 0;
764 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 4))
765 return ERROR_INVALID_DATA;
767 Stream_Read_UINT16(s, numCapabilities);
768 Stream_Seek_UINT16(s);
770 for (UINT16 x = 0; x < numCapabilities; x++)
773 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
774 if (error != CHANNEL_RC_OK)
776 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
778 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
779 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
781 WLog_Print(rdpdr->log, WLOG_TRACE,
782 "capability %s got version %" PRIu32
", will use version %" PRIu32,
783 rdpdr_cap_type_string(header.CapabilityType), header.Version,
784 rdpdr->common.capabilityVersions[header.CapabilityType]);
787 switch (header.CapabilityType)
789 case CAP_GENERAL_TYPE:
790 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
793 case CAP_PRINTER_TYPE:
794 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
798 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
802 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
805 case CAP_SMARTCARD_TYPE:
806 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
810 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
811 "[%s | %s] invalid capability type 0x%04" PRIx16,
812 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
813 header.CapabilityType);
814 status = ERROR_INVALID_DATA;
818 if (status != CHANNEL_RC_OK)
826static UINT rdpdr_send_client_capability_response(pClientContext* pc,
827 pf_channel_client_context* rdpdr)
832 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_CAPABILITY, 4);
834 return CHANNEL_RC_NO_MEMORY;
836 Stream_Write_UINT16(s, 5);
837 Stream_Write_UINT16(s, 0);
838 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
839 return CHANNEL_RC_NO_MEMORY;
840 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
841 return CHANNEL_RC_NO_MEMORY;
842 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
843 return CHANNEL_RC_NO_MEMORY;
844 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
845 return CHANNEL_RC_NO_MEMORY;
846 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
847 return CHANNEL_RC_NO_MEMORY;
848 return rdpdr_client_send(rdpdr->log, pc, s);
852static UINT rdpdr_send_server_clientid_confirm(pf_channel_server_context* rdpdr)
856 s = rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
858 return CHANNEL_RC_NO_MEMORY;
859 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
860 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
861 Stream_Write_UINT32(s, rdpdr->common.clientID);
862 return rdpdr_seal_send_free_request(rdpdr, s);
866static UINT rdpdr_process_server_clientid_confirm(pf_channel_client_context* rdpdr,
wStream* s)
868 UINT16 versionMajor = 0;
869 UINT16 versionMinor = 0;
875 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
876 PAKID_CORE_CLIENTID_CONFIRM, 8))
877 return ERROR_INVALID_DATA;
879 Stream_Read_UINT16(s, versionMajor);
880 Stream_Read_UINT16(s, versionMinor);
881 if (!rdpdr_check_version(FALSE, rdpdr->log, versionMajor, versionMinor, RDPDR_CTYP_CORE,
882 PAKID_CORE_CLIENTID_CONFIRM))
883 return ERROR_INVALID_DATA;
885 Stream_Read_UINT32(s, clientID);
887 if ((versionMajor != rdpdr->common.versionMajor) ||
888 (versionMinor != rdpdr->common.versionMinor))
890 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
891 "[%s | %s] Version mismatch, sent %" PRIu16
".%" PRIu16
892 ", downgraded to %" PRIu16
".%" PRIu16,
893 rdpdr_component_string(RDPDR_CTYP_CORE),
894 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM),
895 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor,
897 rdpdr->common.versionMajor = versionMajor;
898 rdpdr->common.versionMinor = versionMinor;
901 if (clientID != rdpdr->common.clientID)
903 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
904 "[%s | %s] clientID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
905 rdpdr_component_string(RDPDR_CTYP_CORE),
906 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM), rdpdr->common.clientID,
908 rdpdr->common.clientID = clientID;
911 return CHANNEL_RC_OK;
916rdpdr_process_server_capability_request_or_clientid_confirm(pf_channel_client_context* rdpdr,
919 const UINT32 mask = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM |
920 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
921 const UINT16 rcomponent = RDPDR_CTYP_CORE;
922 UINT16 component = 0;
928 if ((rdpdr->flags & mask) == mask)
930 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"already past this state, abort!");
934 if (!Stream_CheckAndLogRequiredLengthClient(rdpdr->log, s, 4))
937 Stream_Read_UINT16(s, component);
938 if (rcomponent != component)
940 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got component %s, expected %s",
941 rdpdr_component_string(component), rdpdr_component_string(rcomponent));
944 Stream_Read_UINT16(s, packetid);
949 case PAKID_CORE_SERVER_CAPABILITY:
950 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST)
952 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
953 rdpdr_packetid_string(packetid));
956 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
957 return rdpdr_process_server_core_capability_request(rdpdr, s) == CHANNEL_RC_OK;
958 case PAKID_CORE_CLIENTID_CONFIRM:
960 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM)
962 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
963 rdpdr_packetid_string(packetid));
966 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
967 return rdpdr_process_server_clientid_confirm(rdpdr, s) == CHANNEL_RC_OK;
971#if defined(WITH_PROXY_EMULATE_SMARTCARD)
973static UINT rdpdr_send_emulated_scard_device_list_announce_request(pClientContext* pc,
974 pf_channel_client_context* rdpdr)
978 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_ANNOUNCE, 24);
980 return CHANNEL_RC_NO_MEMORY;
982 Stream_Write_UINT32(s, 1);
983 Stream_Write_UINT32(s, RDPDR_DTYP_SMARTCARD);
986 Stream_Write(s,
"SCARD\0\0\0", 8);
987 Stream_Write_UINT32(s, 6);
988 Stream_Write(s,
"SCARD\0", 6);
990 return rdpdr_client_send(rdpdr->log, pc, s);
994static UINT rdpdr_send_emulated_scard_device_remove(pClientContext* pc,
995 pf_channel_client_context* rdpdr)
999 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_REMOVE, 24);
1001 return CHANNEL_RC_NO_MEMORY;
1003 Stream_Write_UINT32(s, 1);
1004 Stream_Write_UINT32(
1005 s, SCARD_DEVICE_ID);
1007 return rdpdr_client_send(rdpdr->log, pc, s);
1011static UINT rdpdr_process_server_device_announce_response(pf_channel_client_context* rdpdr,
1014 const UINT16 component = RDPDR_CTYP_CORE;
1015 const UINT16 packetid = PAKID_CORE_DEVICE_REPLY;
1016 UINT32 deviceID = 0;
1017 UINT32 resultCode = 0;
1019 WINPR_ASSERT(rdpdr);
1022 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
1023 return ERROR_INVALID_DATA;
1025 Stream_Read_UINT32(s, deviceID);
1026 Stream_Read_UINT32(s, resultCode);
1028 if (deviceID != SCARD_DEVICE_ID)
1030 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1031 "[%s | %s] deviceID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
1032 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1033 SCARD_DEVICE_ID, deviceID);
1035 else if (resultCode != 0)
1037 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1038 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32,
1039 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1043 CLIENT_RX_LOG(rdpdr->log, WLOG_DEBUG,
1044 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32
1045 " -> emulated smartcard redirected!",
1046 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1049 return CHANNEL_RC_OK;
1054static BOOL pf_channel_rdpdr_rewrite_device_list_to(
wStream* s, UINT32 fromVersion,
1058 if (fromVersion == toVersion)
1061 const size_t cap = Stream_GetRemainingLength(s);
1062 wStream* clone = Stream_New(
nullptr, cap);
1067 const size_t pos = Stream_GetPosition(s);
1068 Stream_Copy(s, clone, cap);
1069 Stream_SealLength(clone);
1071 Stream_SetPosition(clone, 0);
1072 Stream_SetPosition(s, pos);
1076 if (!Stream_SafeSeek(s, 4))
1081 if (Stream_GetRemainingLength(clone) < 4)
1083 Stream_Read_UINT32(clone, count);
1085 for (UINT32 x = 0; x < count; x++)
1088 const size_t charCount = ARRAYSIZE(device.PreferredDosName);
1089 if (Stream_GetRemainingLength(clone) < 20)
1092 Stream_Read_UINT32(clone, device.DeviceType);
1093 Stream_Read_UINT32(clone, device.DeviceId);
1094 Stream_Read(clone, device.PreferredDosName, charCount);
1095 Stream_Read_UINT32(clone, device.DeviceDataLength);
1096 device.DeviceData = Stream_Pointer(clone);
1097 if (!Stream_SafeSeek(clone, device.DeviceDataLength))
1100 if (!Stream_EnsureRemainingCapacity(s, 20))
1102 Stream_Write_UINT32(s, device.DeviceType);
1103 Stream_Write_UINT32(s, device.DeviceId);
1104 Stream_Write(s, device.PreferredDosName, charCount);
1106 if (device.DeviceType == RDPDR_DTYP_FILESYSTEM)
1108 if (toVersion == DRIVE_CAPABILITY_VERSION_01)
1109 Stream_Write_UINT32(s, 0);
1112 const size_t datalen = charCount *
sizeof(WCHAR);
1113 if (!Stream_EnsureRemainingCapacity(s, datalen +
sizeof(UINT32)))
1115 Stream_Write_UINT32(s, WINPR_ASSERTING_INT_CAST(uint32_t, datalen));
1117 const SSIZE_T rcw = Stream_Write_UTF16_String_From_UTF8(
1118 s, charCount, device.PreferredDosName, charCount - 1, TRUE);
1125 Stream_Write_UINT32(s, device.DeviceDataLength);
1126 if (!Stream_EnsureRemainingCapacity(s, device.DeviceDataLength))
1128 Stream_Write(s, device.DeviceData, device.DeviceDataLength);
1133 Stream_SealLength(s);
1137 Stream_Free(clone, TRUE);
1142static BOOL pf_channel_rdpdr_rewrite_device_list(pf_channel_client_context* rdpdr,
1143 pServerContext* ps,
wStream* s, BOOL toServer)
1145 WINPR_ASSERT(rdpdr);
1148 const size_t pos = Stream_GetPosition(s);
1149 UINT16 component = 0;
1150 UINT16 packetid = 0;
1151 Stream_SetPosition(s, 0);
1153 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1156 Stream_Read_UINT16(s, component);
1157 Stream_Read_UINT16(s, packetid);
1158 if ((component != RDPDR_CTYP_CORE) || (packetid != PAKID_CORE_DEVICELIST_ANNOUNCE))
1160 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 Stream_SetPosition(s, pos);
1187static BOOL pf_channel_rdpdr_client_send_to_server(pf_channel_client_context* rdpdr,
1188 pServerContext* ps,
wStream* s)
1190 WINPR_ASSERT(rdpdr);
1193 UINT16 server_channel_id = WTSChannelGetId(ps->context.peer, RDPDR_SVC_CHANNEL_NAME);
1198 if (server_channel_id == 0)
1201 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, TRUE))
1203 size_t len = Stream_Length(s);
1204 Stream_SetPosition(s, len);
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 Stream_SetPosition(s, pos);
1302BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr)
1305 WINPR_ASSERT(rdpdr);
1307 if (rdpdr->state != STATE_CLIENT_CHANNEL_RUNNING)
1310 const UINT16 channelId =
1311 freerdp_channels_get_id_by_name(pc->context.instance, RDPDR_SVC_CHANNEL_NAME);
1312 if ((channelId == 0) || (channelId == UINT16_MAX))
1315 Queue_Lock(rdpdr->queue);
1316 while (Queue_Count(rdpdr->queue) > 0)
1318 wStream* s = Queue_Dequeue(rdpdr->queue);
1322 size_t len = Stream_Length(s);
1323 Stream_SetPosition(s, len);
1325 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_tx
" (queue) ");
1326 WINPR_ASSERT(pc->context.instance->SendChannelData);
1327 if (!pc->context.instance->SendChannelData(pc->context.instance, channelId,
1328 Stream_Buffer(s), len))
1330 CLIENT_TX_LOG(rdpdr->log, WLOG_ERROR,
"xxxxxx TODO: Failed to send data!");
1332 Stream_Free(s, TRUE);
1334 Queue_Unlock(rdpdr->queue);
1339static BOOL rdpdr_handle_server_announce_request(pClientContext* pc,
1340 pf_channel_client_context* rdpdr,
wStream* s)
1343 WINPR_ASSERT(rdpdr);
1346 if (rdpdr_process_server_announce_request(rdpdr, s) != CHANNEL_RC_OK)
1348 if (rdpdr_send_client_announce_reply(pc, rdpdr) != CHANNEL_RC_OK)
1350 if (rdpdr_send_client_name_request(pc, rdpdr) != CHANNEL_RC_OK)
1352 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1356BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId,
const char* channel_name,
1357 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1359 pf_channel_client_context* rdpdr =
nullptr;
1360 pServerContext* ps =
nullptr;
1362#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1363 UINT16 packetid = 0;
1367 WINPR_ASSERT(pc->pdata);
1368 WINPR_ASSERT(pc->interceptContextMap);
1369 WINPR_ASSERT(channel_name);
1370 WINPR_ASSERT(xdata);
1374 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1377 CLIENT_RX_LOG(WLog_Get(RTAG), WLOG_ERROR,
1378 "Channel %s [0x%04" PRIx16
"] missing context in interceptContextMap",
1379 channel_name, channelId);
1382 s = rdpdr->common.buffer;
1383 if (flags & CHANNEL_FLAG_FIRST)
1384 Stream_SetPosition(s, 0);
1385 if (!Stream_EnsureRemainingCapacity(s, xsize))
1387 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1388 "Channel %s [0x%04" PRIx16
"] not enough memory [need %" PRIuz
"]",
1389 channel_name, channelId, xsize);
1392 Stream_Write(s, xdata, xsize);
1393 if ((flags & CHANNEL_FLAG_LAST) == 0)
1396 Stream_SealLength(s);
1397 Stream_SetPosition(s, 0);
1398 if (Stream_Length(s) != totalSize)
1400 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1401 "Received invalid %s channel data (server -> proxy), expected %" PRIuz
1402 "bytes, got %" PRIuz,
1403 channel_name, totalSize, Stream_Length(s));
1407 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_rx);
1408 switch (rdpdr->state)
1410 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
1411 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1414 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
1415 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1417 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
1419 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
1420 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1422 if (rdpdr_send_client_capability_response(pc, rdpdr) != CHANNEL_RC_OK)
1424#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1425 if (pf_channel_smartcard_client_emulate(pc))
1427 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) !=
1430 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1435 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1436 if (!pf_channel_send_client_queue(pc, rdpdr))
1441 case STATE_CLIENT_CHANNEL_RUNNING:
1442#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1443 if (!pf_channel_smartcard_client_emulate(pc) ||
1444 !filter_smartcard_io_requests(rdpdr, s, &packetid))
1445 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1450 case PAKID_CORE_USER_LOGGEDON:
1451 return rdpdr_process_server_loggedon_request(ps, pc, rdpdr, s,
1452 RDPDR_CTYP_CORE, packetid);
1453 case PAKID_CORE_DEVICE_IOREQUEST:
1455 wStream* out = rdpdr_client_get_send_buffer(
1456 rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOCOMPLETION, 0);
1459 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
1460 PAKID_CORE_DEVICE_IOREQUEST, 20))
1463 if (!pf_channel_smartcard_client_handle(rdpdr->log, pc, s, out,
1468 case PAKID_CORE_SERVER_ANNOUNCE:
1469 pf_channel_rdpdr_client_reset(pc);
1470 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1473 case PAKID_CORE_SERVER_CAPABILITY:
1474 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1476 return pf_channel_rdpdr_client_handle(pc, channelId, channel_name, xdata,
1477 xsize, flags, totalSize);
1478 case PAKID_CORE_DEVICE_REPLY:
1482 rdpdr->log, WLOG_ERROR,
1483 "Channel %s [0x%04" PRIx16
1484 "] we´ve reached an impossible state %s! [%s] aliens invaded!",
1485 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state),
1486 rdpdr_packetid_string(packetid));
1492 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1495 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1496 "Channel %s [0x%04" PRIx16
1497 "] we´ve reached an impossible state %s! aliens invaded!",
1498 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state));
1505static void pf_channel_rdpdr_common_context_free(pf_channel_common_context* common)
1509 free(common->computerName.v);
1510 Stream_Free(common->s, TRUE);
1511 Stream_Free(common->buffer, TRUE);
1516 pf_channel_client_context* entry = (pf_channel_client_context*)base;
1520 pf_channel_rdpdr_common_context_free(&entry->common);
1521 Queue_Free(entry->queue);
1526static BOOL pf_channel_rdpdr_common_context_new(pf_channel_common_context* common,
1531 common->base.free = fkt;
1532 common->s = Stream_New(
nullptr, 1024);
1535 common->buffer = Stream_New(
nullptr, 1024);
1536 if (!common->buffer)
1538 common->computerNameUnicode = 1;
1539 common->computerName.v =
nullptr;
1540 common->versionMajor = RDPDR_VERSION_MAJOR;
1541 common->versionMinor = RDPDR_VERSION_MINOR_RDP10X;
1542 common->clientID = SCARD_DEVICE_ID;
1544 const UINT32 versions[] = { 0,
1545 GENERAL_CAPABILITY_VERSION_02,
1546 PRINT_CAPABILITY_VERSION_01,
1547 PORT_CAPABILITY_VERSION_01,
1548 DRIVE_CAPABILITY_VERSION_02,
1549 SMARTCARD_CAPABILITY_VERSION_01 };
1551 memcpy(common->capabilityVersions, versions,
sizeof(common->capabilityVersions));
1556static BOOL pf_channel_rdpdr_client_pass_message(pServerContext* ps, pClientContext* pc,
1557 WINPR_ATTR_UNUSED UINT16 channelId,
1558 const char* channel_name,
wStream* s)
1560 pf_channel_client_context* rdpdr =
nullptr;
1565 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1568 WINPR_ASSERT(rdpdr->queue);
1570 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, FALSE))
1572 if (!Queue_Enqueue(rdpdr->queue, s))
1574 return pf_channel_send_client_queue(pc, rdpdr);
1577#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1579static BOOL filter_smartcard_device_list_remove(pf_channel_server_context* rdpdr,
wStream* s)
1584 WINPR_ASSERT(rdpdr);
1585 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1587 pos = Stream_GetPosition(s);
1588 Stream_Read_UINT32(s, count);
1593 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdpdr->log, s, count,
sizeof(UINT32)))
1596 for (UINT32 x = 0; x < count; x++)
1598 UINT32 deviceID = 0;
1599 BYTE* dst = Stream_Pointer(s);
1600 Stream_Read_UINT32(s, deviceID);
1601 if (deviceID == SCARD_DEVICE_ID)
1603 ArrayList_Remove(rdpdr->blockedDevices, (
void*)(
size_t)deviceID);
1610 memmove(dst, Stream_ConstPointer(s), (count - x - 1) *
sizeof(UINT32));
1613 Stream_SetPosition(s, pos);
1614 Stream_Write_UINT32(s, count);
1623static BOOL filter_smartcard_device_io_request(pf_channel_server_context* rdpdr,
wStream* s)
1625 UINT32 DeviceID = 0;
1626 WINPR_ASSERT(rdpdr);
1628 Stream_Read_UINT32(s, DeviceID);
1629 return ArrayList_Contains(rdpdr->blockedDevices, (
void*)(
size_t)DeviceID);
1633static BOOL filter_smartcard_device_list_announce(pf_channel_server_context* rdpdr,
wStream* s)
1637 WINPR_ASSERT(rdpdr);
1638 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1640 const size_t pos = Stream_GetPosition(s);
1641 Stream_Read_UINT32(s, count);
1646 for (UINT32 x = 0; x < count; x++)
1648 UINT32 DeviceType = 0;
1649 UINT32 DeviceId = 0;
1650 char PreferredDosName[8];
1651 UINT32 DeviceDataLength = 0;
1652 BYTE* dst = Stream_Pointer(s);
1653 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 20))
1655 Stream_Read_UINT32(s, DeviceType);
1656 Stream_Read_UINT32(s, DeviceId);
1657 Stream_Read(s, PreferredDosName, ARRAYSIZE(PreferredDosName));
1658 Stream_Read_UINT32(s, DeviceDataLength);
1659 if (!Stream_SafeSeek(s, DeviceDataLength))
1661 if (DeviceType == RDPDR_DTYP_SMARTCARD)
1663 ArrayList_Append(rdpdr->blockedDevices, (
void*)(
size_t)DeviceId);
1667 WLog_Print(rdpdr->log, WLOG_INFO,
"Filtering smartcard device 0x%08" PRIx32
"",
1670 memmove(dst, Stream_ConstPointer(s), Stream_GetRemainingLength(s));
1671 Stream_SetPosition(s, pos);
1672 Stream_Write_UINT32(s, count - 1);
1681static BOOL filter_smartcard_device_list_announce_request(pf_channel_server_context* rdpdr,
1686 UINT16 component = 0;
1687 UINT16 packetid = 0;
1689 WINPR_ASSERT(rdpdr);
1690 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8))
1693 pos = Stream_GetPosition(s);
1695 Stream_Read_UINT16(s, component);
1696 Stream_Read_UINT16(s, packetid);
1698 if (component != RDPDR_CTYP_CORE)
1703 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1704 if (filter_smartcard_device_list_announce(rdpdr, s))
1707 case PAKID_CORE_DEVICELIST_REMOVE:
1708 if (filter_smartcard_device_list_remove(rdpdr, s))
1711 case PAKID_CORE_DEVICE_IOREQUEST:
1712 if (filter_smartcard_device_io_request(rdpdr, s))
1716 case PAKID_CORE_SERVER_ANNOUNCE:
1717 case PAKID_CORE_CLIENTID_CONFIRM:
1718 case PAKID_CORE_CLIENT_NAME:
1719 case PAKID_CORE_DEVICE_REPLY:
1720 case PAKID_CORE_SERVER_CAPABILITY:
1721 case PAKID_CORE_CLIENT_CAPABILITY:
1722 case PAKID_CORE_USER_LOGGEDON:
1723 WLog_Print(rdpdr->log, WLOG_WARN,
"Filtering client -> server message [%s | %s]",
1724 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1732 Stream_SetPosition(s, pos);
1737WINPR_ATTR_MALLOC(Stream_Free, 1)
1739static
void* stream_copy(const
void* obj)
1742 wStream* dst = Stream_New(
nullptr, Stream_Capacity(src));
1745 memcpy(Stream_Buffer(dst), Stream_ConstBuffer(src), Stream_Capacity(dst));
1746 Stream_SetLength(dst, Stream_Length(src));
1747 Stream_SetPosition(dst, Stream_GetPosition(src));
1751static void stream_free(
void* obj)
1754 Stream_Free(s, TRUE);
1758static const char* pf_channel_rdpdr_client_context(
void* arg)
1760 pClientContext* pc = arg;
1764 return "pc->pdata=null";
1765 return pc->pdata->session_id;
1768BOOL pf_channel_rdpdr_client_new(pClientContext* pc)
1771 pf_channel_client_context* rdpdr =
nullptr;
1774 WINPR_ASSERT(pc->interceptContextMap);
1776 rdpdr = calloc(1,
sizeof(pf_channel_client_context));
1779 rdpdr->log = WLog_Get(RTAG);
1780 WINPR_ASSERT(rdpdr->log);
1782 WLog_SetContext(rdpdr->log, pf_channel_rdpdr_client_context, pc);
1783 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_client_context_free))
1786 rdpdr->maxMajorVersion = RDPDR_VERSION_MAJOR;
1787 rdpdr->maxMinorVersion = RDPDR_VERSION_MINOR_RDP10X;
1788 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
1790 rdpdr->queue = Queue_New(TRUE, 0, 0);
1793 obj = Queue_Object(rdpdr->queue);
1797 if (!HashTable_Insert(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1802 pf_channel_rdpdr_client_context_free(&rdpdr->common.base);
1806void pf_channel_rdpdr_client_free(pClientContext* pc)
1809 WINPR_ASSERT(pc->interceptContextMap);
1810 HashTable_Remove(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1815 pf_channel_server_context* entry = (pf_channel_server_context*)base;
1819 (void)WTSVirtualChannelClose(entry->handle);
1820 pf_channel_rdpdr_common_context_free(&entry->common);
1821 ArrayList_Free(entry->blockedDevices);
1826static const char* pf_channel_rdpdr_server_context(
void* arg)
1828 pServerContext* ps = arg;
1832 return "ps->pdata=null";
1833 return ps->pdata->session_id;
1836BOOL pf_channel_rdpdr_server_new(pServerContext* ps)
1838 pf_channel_server_context* rdpdr =
nullptr;
1839 PULONG pSessionId =
nullptr;
1840 DWORD BytesReturned = 0;
1843 WINPR_ASSERT(ps->interceptContextMap);
1845 rdpdr = calloc(1,
sizeof(pf_channel_server_context));
1848 rdpdr->log = WLog_Get(RTAG);
1849 WINPR_ASSERT(rdpdr->log);
1850 WLog_SetContext(rdpdr->log, pf_channel_rdpdr_server_context, ps);
1852 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_server_context_free))
1854 rdpdr->state = STATE_SERVER_INITIAL;
1856 rdpdr->blockedDevices = ArrayList_New(FALSE);
1857 if (!rdpdr->blockedDevices)
1860 rdpdr->SessionId = WTS_CURRENT_SESSION;
1861 if (WTSQuerySessionInformationA(ps->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*)&pSessionId,
1864 rdpdr->SessionId = (DWORD)*pSessionId;
1865 WTSFreeMemory(pSessionId);
1868 rdpdr->handle = WTSVirtualChannelOpenEx(rdpdr->SessionId, RDPDR_SVC_CHANNEL_NAME, 0);
1869 if (rdpdr->handle ==
nullptr)
1871 if (!HashTable_Insert(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1877 pf_channel_rdpdr_server_context_free(&rdpdr->common.base);
1881void pf_channel_rdpdr_server_free(pServerContext* ps)
1884 WINPR_ASSERT(ps->interceptContextMap);
1885 HashTable_Remove(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1889static pf_channel_server_context* get_channel(pServerContext* ps, BOOL send)
1891 pf_channel_server_context* rdpdr =
nullptr;
1893 WINPR_ASSERT(ps->interceptContextMap);
1895 rdpdr = HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1898 SERVER_RXTX_LOG(send, WLog_Get(RTAG), WLOG_ERROR,
1899 "Channel %s missing context in interceptContextMap",
1900 RDPDR_SVC_CHANNEL_NAME);
1907BOOL pf_channel_rdpdr_server_handle(pServerContext* ps, UINT16 channelId,
const char* channel_name,
1908 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1911 pClientContext* pc =
nullptr;
1912 pf_channel_server_context* rdpdr = get_channel(ps, FALSE);
1916 WINPR_ASSERT(ps->pdata);
1919 s = rdpdr->common.buffer;
1921 if (flags & CHANNEL_FLAG_FIRST)
1922 Stream_SetPosition(s, 0);
1924 if (!Stream_EnsureRemainingCapacity(s, xsize))
1926 Stream_Write(s, xdata, xsize);
1928 if ((flags & CHANNEL_FLAG_LAST) == 0)
1931 Stream_SealLength(s);
1932 Stream_SetPosition(s, 0);
1934 if (Stream_Length(s) != totalSize)
1936 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
1937 "Received invalid %s channel data (client -> proxy), expected %" PRIuz
1938 "bytes, got %" PRIuz,
1939 channel_name, totalSize, Stream_Length(s));
1943 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_rx);
1944 switch (rdpdr->state)
1946 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
1947 if (rdpdr_process_client_announce_reply(rdpdr, s) != CHANNEL_RC_OK)
1949 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST;
1951 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
1952 if (rdpdr_process_client_name_request(rdpdr, s, pc) != CHANNEL_RC_OK)
1954 if (rdpdr_send_server_capability_request(rdpdr) != CHANNEL_RC_OK)
1956 if (rdpdr_send_server_clientid_confirm(rdpdr) != CHANNEL_RC_OK)
1958 rdpdr->state = STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE;
1960 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
1961 if (rdpdr_process_client_capability_response(rdpdr, s) != CHANNEL_RC_OK)
1963 rdpdr->state = STATE_SERVER_CHANNEL_RUNNING;
1965 case STATE_SERVER_CHANNEL_RUNNING:
1966#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1967 if (!pf_channel_smartcard_client_emulate(pc) ||
1968 !filter_smartcard_device_list_announce_request(rdpdr, s))
1970 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
1974 return pf_channel_smartcard_server_handle(ps, s);
1976 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
1981 case STATE_SERVER_INITIAL:
1982 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
"Invalid state %s",
1983 rdpdr_server_state_to_string(rdpdr->state));
1990BOOL pf_channel_rdpdr_server_announce(pServerContext* ps)
1992 pf_channel_server_context* rdpdr = get_channel(ps, TRUE);
1996 WINPR_ASSERT(rdpdr->state == STATE_SERVER_INITIAL);
1997 if (rdpdr_server_send_announce_request(rdpdr) != CHANNEL_RC_OK)
1999 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY;
2003BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
2005 pf_channel_client_context* rdpdr =
nullptr;
2008 WINPR_ASSERT(pc->pdata);
2009 WINPR_ASSERT(pc->interceptContextMap);
2011 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
2015 Queue_Clear(rdpdr->queue);
2017 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
2023static PfChannelResult pf_rdpdr_back_data(proxyData* pdata,
2024 const pServerStaticChannelContext* channel,
2025 const BYTE* xdata,
size_t xsize, UINT32 flags,
2028 WINPR_ASSERT(pdata);
2029 WINPR_ASSERT(channel);
2031 if (!pf_channel_rdpdr_client_handle(pdata->pc,
2032 WINPR_ASSERTING_INT_CAST(UINT16, channel->back_channel_id),
2033 channel->channel_name, xdata, xsize, flags, totalSize))
2034 return PF_CHANNEL_RESULT_ERROR;
2036#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2037 if (pf_channel_smartcard_client_emulate(pdata->pc))
2038 return PF_CHANNEL_RESULT_DROP;
2040 return PF_CHANNEL_RESULT_DROP;
2044static PfChannelResult pf_rdpdr_front_data(proxyData* pdata,
2045 const pServerStaticChannelContext* channel,
2046 const BYTE* xdata,
size_t xsize, UINT32 flags,
2049 WINPR_ASSERT(pdata);
2050 WINPR_ASSERT(channel);
2052 if (!pf_channel_rdpdr_server_handle(pdata->ps,
2053 WINPR_ASSERTING_INT_CAST(UINT16, channel->front_channel_id),
2054 channel->channel_name, xdata, xsize, flags, totalSize))
2055 return PF_CHANNEL_RESULT_ERROR;
2057#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2058 if (pf_channel_smartcard_client_emulate(pdata->pc))
2059 return PF_CHANNEL_RESULT_DROP;
2061 return PF_CHANNEL_RESULT_DROP;
2064BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
2066 channel->onBackData = pf_rdpdr_back_data;
2067 channel->onFrontData = pf_rdpdr_front_data;
2069 if (!pf_channel_rdpdr_server_new(ps))
2071 if (!pf_channel_rdpdr_server_announce(ps))
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
OBJECT_NEW_FN fnObjectNew