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];
61} pf_channel_common_context;
65 STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST = 0x01,
66 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST = 0x02,
67 STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM = 0x04,
68 STATE_CLIENT_CHANNEL_RUNNING = 0x10
69} pf_channel_client_state;
73 pf_channel_common_context common;
74 pf_channel_client_state state;
76 UINT16 maxMajorVersion;
77 UINT16 maxMinorVersion;
80} pf_channel_client_context;
85 STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY,
86 STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST,
87 STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE,
88 STATE_SERVER_CHANNEL_RUNNING
89} pf_channel_server_state;
93 pf_channel_common_context common;
94 pf_channel_server_state state;
97 wArrayList* blockedDevices;
99} pf_channel_server_context;
101#define proxy_client "[proxy<-->client]"
102#define proxy_server "[proxy<-->server]"
104#define proxy_client_rx proxy_client " receive"
105#define proxy_client_tx proxy_client " send"
106#define proxy_server_rx proxy_server " receive"
107#define proxy_server_tx proxy_server " send"
109#define SERVER_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_rx fmt, ##__VA_ARGS__)
110#define CLIENT_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_rx fmt, ##__VA_ARGS__)
111#define SERVER_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_tx fmt, ##__VA_ARGS__)
112#define CLIENT_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_tx fmt, ##__VA_ARGS__)
113#define RX_LOG(srv, lvl, fmt, ...) \
118 SERVER_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
122 CLIENT_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
126#define SERVER_RXTX_LOG(send, log, lvl, fmt, ...) \
131 SERVER_TX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
135 SERVER_RX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
139#define Stream_CheckAndLogRequiredLengthSrv(log, s, len) \
140 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
141 proxy_client_rx " %s(%s:%" PRIuz ")", __func__, \
142 __FILE__, (size_t)__LINE__)
143#define Stream_CheckAndLogRequiredLengthClient(log, s, len) \
144 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
145 proxy_server_rx " %s(%s:%" PRIuz ")", __func__, \
146 __FILE__, (size_t)__LINE__)
147#define Stream_CheckAndLogRequiredLengthRx(srv, log, s, len) \
148 Stream_CheckAndLogRequiredLengthRx_(srv, log, s, len, 1, __func__, __FILE__, __LINE__)
150static BOOL Stream_CheckAndLogRequiredLengthRx_(BOOL srv, wLog* log,
wStream* s,
size_t nmemb,
151 size_t size,
const char* fkt,
const char* file,
155 srv ? proxy_server_rx
" %s(%s:%" PRIuz
")" : proxy_client_rx
" %s(%s:%" PRIuz
")";
157 return Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, fmt, fkt, file,
162static const char* rdpdr_server_state_to_string(pf_channel_server_state state)
166 case STATE_SERVER_INITIAL:
167 return "STATE_SERVER_INITIAL";
168 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
169 return "STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY";
170 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
171 return "STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST";
172 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
173 return "STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE";
174 case STATE_SERVER_CHANNEL_RUNNING:
175 return "STATE_SERVER_CHANNEL_RUNNING";
177 return "STATE_SERVER_UNKNOWN";
182static const char* rdpdr_client_state_to_string(pf_channel_client_state state)
186 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
187 return "STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST";
188 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
189 return "STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST";
190 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
191 return "STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM";
192 case STATE_CLIENT_CHANNEL_RUNNING:
193 return "STATE_CLIENT_CHANNEL_RUNNING";
195 return "STATE_CLIENT_UNKNOWN";
200static wStream* rdpdr_get_send_buffer(pf_channel_common_context* rdpdr, UINT16 component,
201 UINT16 PacketID,
size_t capacity)
204 WINPR_ASSERT(rdpdr->s);
205 Stream_ResetPosition(rdpdr->s);
207 if (!Stream_EnsureCapacity(rdpdr->s, capacity + 4))
209 Stream_Write_UINT16(rdpdr->s, component);
210 Stream_Write_UINT16(rdpdr->s, PacketID);
215static wStream* rdpdr_client_get_send_buffer(pf_channel_client_context* rdpdr, UINT16 component,
216 UINT16 PacketID,
size_t capacity)
219 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
223static wStream* rdpdr_server_get_send_buffer(pf_channel_server_context* rdpdr, UINT16 component,
224 UINT16 PacketID,
size_t capacity)
227 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
231static UINT rdpdr_client_send(wLog* log, pClientContext* pc,
wStream* s)
233 UINT16 channelId = 0;
238 WINPR_ASSERT(pc->cctx.context.instance);
242 CLIENT_TX_LOG(log, WLOG_WARN,
"Ignoring channel %s message, not connected!",
243 RDPDR_SVC_CHANNEL_NAME);
244 return CHANNEL_RC_OK;
247 channelId = freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
250 if ((channelId == 0) || (channelId == UINT16_MAX))
251 return ERROR_INTERNAL_ERROR;
253 Stream_SealLength(s);
254 rdpdr_dump_send_packet(log, WLOG_TRACE, s, proxy_server_tx);
255 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
256 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
257 Stream_Buffer(s), Stream_Length(s)))
258 return ERROR_EVT_CHANNEL_NOT_FOUND;
259 return CHANNEL_RC_OK;
263static UINT rdpdr_seal_send_free_request(pf_channel_server_context* context,
wStream* s)
268 WINPR_ASSERT(context);
269 WINPR_ASSERT(context->handle);
272 Stream_SealLength(s);
273 len = Stream_Length(s);
274 WINPR_ASSERT(len <= UINT32_MAX);
276 rdpdr_dump_send_packet(context->log, WLOG_TRACE, s, proxy_client_tx);
277 status = WTSVirtualChannelWrite(context->handle, Stream_BufferAs(s,
char), (ULONG)len,
nullptr);
278 return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
282static BOOL rdpdr_process_server_header(BOOL server, wLog* log,
wStream* s, UINT16 component,
283 UINT16 PacketId,
size_t expect)
285 UINT16 rpacketid = 0;
286 UINT16 rcomponent = 0;
289 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, 4))
291 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: expected length 4, got %" PRIuz,
292 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
293 Stream_GetRemainingLength(s));
297 Stream_Read_UINT16(s, rcomponent);
298 Stream_Read_UINT16(s, rpacketid);
300 if (rcomponent != component)
302 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got component %s",
303 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
304 rdpdr_component_string(rcomponent));
308 if (rpacketid != PacketId)
310 RX_LOG(server, log, WLOG_WARN,
"RDPDR_HEADER[%s | %s]: got PacketID %s",
311 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
312 rdpdr_packetid_string(rpacketid));
316 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, expect))
318 RX_LOG(server, log, WLOG_WARN,
319 "RDPDR_HEADER[%s | %s] not enough data, expected %" PRIuz
", "
321 rdpdr_component_string(component), rdpdr_packetid_string(PacketId), expect,
322 Stream_GetRemainingLength(s));
323 return ERROR_INVALID_DATA;
330static BOOL rdpdr_check_version(BOOL server, wLog* log, UINT16 versionMajor, UINT16 versionMinor,
331 UINT16 component, UINT16 PacketId)
333 if (versionMajor != RDPDR_VERSION_MAJOR)
335 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] expected MajorVersion %d, got %" PRIu16,
336 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
337 RDPDR_VERSION_MAJOR, versionMajor);
340 switch (versionMinor)
342 case RDPDR_VERSION_MINOR_RDP50:
343 case RDPDR_VERSION_MINOR_RDP51:
344 case RDPDR_VERSION_MINOR_RDP52:
345 case RDPDR_VERSION_MINOR_RDP6X:
346 case RDPDR_VERSION_MINOR_RDP10X:
350 RX_LOG(server, log, WLOG_WARN,
"[%s | %s] unsupported MinorVersion %" PRIu16,
351 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
360static UINT rdpdr_process_server_announce_request(pf_channel_client_context* rdpdr,
wStream* s)
362 const UINT16 component = RDPDR_CTYP_CORE;
363 const UINT16 packetid = PAKID_CORE_SERVER_ANNOUNCE;
367 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, component, packetid, 8))
368 return ERROR_INVALID_DATA;
370 Stream_Read_UINT16(s, rdpdr->common.versionMajor);
371 Stream_Read_UINT16(s, rdpdr->common.versionMinor);
373 if (!rdpdr_check_version(FALSE, rdpdr->log, rdpdr->common.versionMajor,
374 rdpdr->common.versionMinor, component, packetid))
375 return ERROR_INVALID_DATA;
378 if (rdpdr->common.versionMajor > rdpdr->maxMajorVersion)
380 rdpdr->common.versionMajor = rdpdr->maxMajorVersion;
381 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
383 else if (rdpdr->common.versionMinor > rdpdr->maxMinorVersion)
384 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
386 Stream_Read_UINT32(s, rdpdr->common.clientID);
387 return CHANNEL_RC_OK;
391static UINT rdpdr_server_send_announce_request(pf_channel_server_context* context)
394 rdpdr_server_get_send_buffer(context, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_ANNOUNCE, 8);
396 return CHANNEL_RC_NO_MEMORY;
398 Stream_Write_UINT16(s, context->common.versionMajor);
399 Stream_Write_UINT16(s, context->common.versionMinor);
400 Stream_Write_UINT32(s, context->common.clientID);
401 return rdpdr_seal_send_free_request(context, s);
405static UINT rdpdr_process_client_announce_reply(pf_channel_server_context* rdpdr,
wStream* s)
407 const UINT16 component = RDPDR_CTYP_CORE;
408 const UINT16 packetid = PAKID_CORE_CLIENTID_CONFIRM;
409 UINT16 versionMajor = 0;
410 UINT16 versionMinor = 0;
416 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
417 return ERROR_INVALID_DATA;
419 Stream_Read_UINT16(s, versionMajor);
420 Stream_Read_UINT16(s, versionMinor);
422 if (!rdpdr_check_version(TRUE, rdpdr->log, versionMajor, versionMinor, component, packetid))
423 return ERROR_INVALID_DATA;
425 if ((rdpdr->common.versionMajor != versionMajor) ||
426 (rdpdr->common.versionMinor != versionMinor))
429 rdpdr->log, WLOG_WARN,
430 "[%s | %s] downgrading version from %" PRIu16
".%" PRIu16
" to %" PRIu16
".%" PRIu16,
431 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
432 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor, versionMinor);
433 rdpdr->common.versionMajor = versionMajor;
434 rdpdr->common.versionMinor = versionMinor;
436 Stream_Read_UINT32(s, clientID);
437 if (rdpdr->common.clientID != clientID)
439 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
440 "[%s | %s] changing clientID 0x%08" PRIu32
" to 0x%08" PRIu32,
441 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
442 rdpdr->common.clientID, clientID);
443 rdpdr->common.clientID = clientID;
446 return CHANNEL_RC_OK;
450static UINT rdpdr_send_client_announce_reply(pClientContext* pc, pf_channel_client_context* rdpdr)
453 rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
455 return CHANNEL_RC_NO_MEMORY;
457 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
458 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
459 Stream_Write_UINT32(s, rdpdr->common.clientID);
460 return rdpdr_client_send(rdpdr->log, pc, s);
464static UINT rdpdr_process_client_name_request(pf_channel_server_context* rdpdr,
wStream* s,
467 UINT32 unicodeFlag = 0;
474 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
476 return ERROR_INVALID_DATA;
478 Stream_Read_UINT32(s, unicodeFlag);
479 rdpdr->common.computerNameUnicode = ((unicodeFlag & 1) != 0);
481 Stream_Read_UINT32(s, codePage);
482 WINPR_UNUSED(codePage);
483 Stream_Read_UINT32(s, rdpdr->common.computerNameLen);
484 if (!Stream_CheckAndLogRequiredLengthSrv(rdpdr->log, s, rdpdr->common.computerNameLen))
487 rdpdr->log, WLOG_WARN,
"[%s | %s]: missing data, got %" PRIuz
", expected %" PRIu32,
488 rdpdr_component_string(RDPDR_CTYP_CORE), rdpdr_packetid_string(PAKID_CORE_CLIENT_NAME),
489 Stream_GetRemainingLength(s), rdpdr->common.computerNameLen);
490 return ERROR_INVALID_DATA;
492 void* tmp = realloc(rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
494 return CHANNEL_RC_NO_MEMORY;
495 rdpdr->common.computerName.v = tmp;
497 Stream_Read(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
499 pc->computerNameLen = rdpdr->common.computerNameLen;
500 pc->computerNameUnicode = rdpdr->common.computerNameUnicode;
501 tmp = realloc(pc->computerName.v, pc->computerNameLen);
503 return CHANNEL_RC_NO_MEMORY;
504 pc->computerName.v = tmp;
505 memcpy(pc->computerName.v, rdpdr->common.computerName.v, pc->computerNameLen);
507 return CHANNEL_RC_OK;
511static UINT rdpdr_send_client_name_request(pClientContext* pc, pf_channel_client_context* rdpdr)
519 void* tmp = realloc(rdpdr->common.computerName.v, pc->computerNameLen);
521 return CHANNEL_RC_NO_MEMORY;
522 rdpdr->common.computerName.v = tmp;
523 rdpdr->common.computerNameLen = pc->computerNameLen;
524 rdpdr->common.computerNameUnicode = pc->computerNameUnicode;
525 memcpy(rdpdr->common.computerName.v, pc->computerName.v, pc->computerNameLen);
527 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
528 12U + rdpdr->common.computerNameLen);
530 return CHANNEL_RC_NO_MEMORY;
532 Stream_Write_UINT32(s, rdpdr->common.computerNameUnicode
535 Stream_Write_UINT32(s, 0);
536 Stream_Write_UINT32(s, rdpdr->common.computerNameLen);
537 Stream_Write(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
538 return rdpdr_client_send(rdpdr->log, pc, s);
541#define rdpdr_ignore_capset(srv, log, s, header) \
542 rdpdr_ignore_capset_((srv), (log), (s), header, __func__)
544static UINT rdpdr_ignore_capset_(WINPR_ATTR_UNUSED BOOL srv, WINPR_ATTR_UNUSED wLog* log,
546 WINPR_ATTR_UNUSED
const char* fkt)
549 WINPR_ASSERT(header);
551 Stream_Seek(s, header->CapabilityLength);
552 return CHANNEL_RC_OK;
556static UINT rdpdr_client_process_general_capset(pf_channel_client_context* rdpdr,
wStream* s,
560 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
564static UINT rdpdr_process_printer_capset(pf_channel_client_context* rdpdr,
wStream* s,
568 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
572static UINT rdpdr_process_port_capset(pf_channel_client_context* rdpdr,
wStream* s,
576 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
580static UINT rdpdr_process_drive_capset(pf_channel_client_context* rdpdr,
wStream* s,
584 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
588static UINT rdpdr_process_smartcard_capset(pf_channel_client_context* rdpdr,
wStream* s,
592 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
596static UINT rdpdr_process_server_core_capability_request(pf_channel_client_context* rdpdr,
599 UINT status = CHANNEL_RC_OK;
600 UINT16 numCapabilities = 0;
604 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
605 PAKID_CORE_SERVER_CAPABILITY, 4))
606 return ERROR_INVALID_DATA;
608 Stream_Read_UINT16(s, numCapabilities);
611 for (UINT16 i = 0; i < numCapabilities; i++)
614 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
615 if (error != CHANNEL_RC_OK)
618 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
620 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
621 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
623 WLog_Print(rdpdr->log, WLOG_TRACE,
624 "capability %s got version %" PRIu32
", will use version %" PRIu32,
625 rdpdr_cap_type_string(header.CapabilityType), header.Version,
626 rdpdr->common.capabilityVersions[header.CapabilityType]);
629 switch (header.CapabilityType)
631 case CAP_GENERAL_TYPE:
632 status = rdpdr_client_process_general_capset(rdpdr, s, &header);
635 case CAP_PRINTER_TYPE:
636 status = rdpdr_process_printer_capset(rdpdr, s, &header);
640 status = rdpdr_process_port_capset(rdpdr, s, &header);
644 status = rdpdr_process_drive_capset(rdpdr, s, &header);
647 case CAP_SMARTCARD_TYPE:
648 status = rdpdr_process_smartcard_capset(rdpdr, s, &header);
652 WLog_Print(rdpdr->log, WLOG_WARN,
653 "unknown capability 0x%04" PRIx16
", length %" PRIu16
654 ", version %" PRIu32,
655 header.CapabilityType, header.CapabilityLength, header.Version);
656 Stream_Seek(s, header.CapabilityLength);
660 if (status != CHANNEL_RC_OK)
664 return CHANNEL_RC_OK;
668static BOOL rdpdr_write_general_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
674 rdpdr->capabilityVersions[CAP_GENERAL_TYPE] };
675 if (rdpdr_write_capset_header(log, s, &header) != CHANNEL_RC_OK)
677 Stream_Write_UINT32(s, 0);
678 Stream_Write_UINT32(s, 0);
679 Stream_Write_UINT16(s, rdpdr->versionMajor);
680 Stream_Write_UINT16(s, rdpdr->versionMinor);
681 Stream_Write_UINT32(s, 0x0000FFFF);
682 Stream_Write_UINT32(s, 0);
683 Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU |
684 RDPDR_USER_LOGGEDON_PDU);
685 Stream_Write_UINT32(s, ENABLE_ASYNCIO);
686 Stream_Write_UINT32(s, 0);
687 Stream_Write_UINT32(s, rdpdr->SpecialDeviceCount);
693static BOOL rdpdr_write_printer_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
699 rdpdr->capabilityVersions[CAP_PRINTER_TYPE] };
700 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
704static BOOL rdpdr_write_port_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
710 rdpdr->capabilityVersions[CAP_PORT_TYPE] };
711 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
715static BOOL rdpdr_write_drive_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
721 rdpdr->capabilityVersions[CAP_DRIVE_TYPE] };
722 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
726static BOOL rdpdr_write_smartcard_capset(wLog* log, pf_channel_common_context* rdpdr,
wStream* s)
732 rdpdr->capabilityVersions[CAP_SMARTCARD_TYPE] };
733 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
737static UINT rdpdr_send_server_capability_request(pf_channel_server_context* rdpdr)
740 rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_CAPABILITY, 8);
742 return CHANNEL_RC_NO_MEMORY;
743 Stream_Write_UINT16(s, 5);
744 Stream_Write_UINT16(s, 0);
745 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
746 return CHANNEL_RC_NO_MEMORY;
747 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
748 return CHANNEL_RC_NO_MEMORY;
749 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
750 return CHANNEL_RC_NO_MEMORY;
751 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
752 return CHANNEL_RC_NO_MEMORY;
753 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
754 return CHANNEL_RC_NO_MEMORY;
755 return rdpdr_seal_send_free_request(rdpdr, s);
759static UINT rdpdr_process_client_capability_response(pf_channel_server_context* rdpdr,
wStream* s)
761 const UINT16 component = RDPDR_CTYP_CORE;
762 const UINT16 packetid = PAKID_CORE_CLIENT_CAPABILITY;
763 UINT status = CHANNEL_RC_OK;
764 UINT16 numCapabilities = 0;
767 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 4))
768 return ERROR_INVALID_DATA;
770 Stream_Read_UINT16(s, numCapabilities);
771 Stream_Seek_UINT16(s);
773 for (UINT16 x = 0; x < numCapabilities; x++)
776 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
777 if (error != CHANNEL_RC_OK)
779 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
781 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
782 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
784 WLog_Print(rdpdr->log, WLOG_TRACE,
785 "capability %s got version %" PRIu32
", will use version %" PRIu32,
786 rdpdr_cap_type_string(header.CapabilityType), header.Version,
787 rdpdr->common.capabilityVersions[header.CapabilityType]);
790 switch (header.CapabilityType)
792 case CAP_GENERAL_TYPE:
793 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
796 case CAP_PRINTER_TYPE:
797 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
801 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
805 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
808 case CAP_SMARTCARD_TYPE:
809 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
813 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
814 "[%s | %s] invalid capability type 0x%04" PRIx16,
815 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
816 header.CapabilityType);
817 status = ERROR_INVALID_DATA;
821 if (status != CHANNEL_RC_OK)
829static UINT rdpdr_send_client_capability_response(pClientContext* pc,
830 pf_channel_client_context* rdpdr)
835 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_CAPABILITY, 4);
837 return CHANNEL_RC_NO_MEMORY;
839 Stream_Write_UINT16(s, 5);
840 Stream_Write_UINT16(s, 0);
841 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
842 return CHANNEL_RC_NO_MEMORY;
843 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
844 return CHANNEL_RC_NO_MEMORY;
845 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
846 return CHANNEL_RC_NO_MEMORY;
847 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
848 return CHANNEL_RC_NO_MEMORY;
849 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
850 return CHANNEL_RC_NO_MEMORY;
851 return rdpdr_client_send(rdpdr->log, pc, s);
855static UINT rdpdr_send_server_clientid_confirm(pf_channel_server_context* rdpdr)
859 s = rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
861 return CHANNEL_RC_NO_MEMORY;
862 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
863 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
864 Stream_Write_UINT32(s, rdpdr->common.clientID);
865 return rdpdr_seal_send_free_request(rdpdr, s);
869static UINT rdpdr_process_server_clientid_confirm(pf_channel_client_context* rdpdr,
wStream* s)
871 UINT16 versionMajor = 0;
872 UINT16 versionMinor = 0;
878 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
879 PAKID_CORE_CLIENTID_CONFIRM, 8))
880 return ERROR_INVALID_DATA;
882 Stream_Read_UINT16(s, versionMajor);
883 Stream_Read_UINT16(s, versionMinor);
884 if (!rdpdr_check_version(FALSE, rdpdr->log, versionMajor, versionMinor, RDPDR_CTYP_CORE,
885 PAKID_CORE_CLIENTID_CONFIRM))
886 return ERROR_INVALID_DATA;
888 Stream_Read_UINT32(s, clientID);
890 if ((versionMajor != rdpdr->common.versionMajor) ||
891 (versionMinor != rdpdr->common.versionMinor))
893 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
894 "[%s | %s] Version mismatch, sent %" PRIu16
".%" PRIu16
895 ", downgraded to %" PRIu16
".%" PRIu16,
896 rdpdr_component_string(RDPDR_CTYP_CORE),
897 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM),
898 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor,
900 rdpdr->common.versionMajor = versionMajor;
901 rdpdr->common.versionMinor = versionMinor;
904 if (clientID != rdpdr->common.clientID)
906 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
907 "[%s | %s] clientID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
908 rdpdr_component_string(RDPDR_CTYP_CORE),
909 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM), rdpdr->common.clientID,
911 rdpdr->common.clientID = clientID;
914 return CHANNEL_RC_OK;
919rdpdr_process_server_capability_request_or_clientid_confirm(pf_channel_client_context* rdpdr,
922 const UINT32 mask = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM |
923 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
924 const UINT16 rcomponent = RDPDR_CTYP_CORE;
925 UINT16 component = 0;
931 if ((rdpdr->flags & mask) == mask)
933 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"already past this state, abort!");
937 if (!Stream_CheckAndLogRequiredLengthClient(rdpdr->log, s, 4))
940 Stream_Read_UINT16(s, component);
941 if (rcomponent != component)
943 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got component %s, expected %s",
944 rdpdr_component_string(component), rdpdr_component_string(rcomponent));
947 Stream_Read_UINT16(s, packetid);
952 case PAKID_CORE_SERVER_CAPABILITY:
953 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST)
955 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
956 rdpdr_packetid_string(packetid));
959 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
960 return rdpdr_process_server_core_capability_request(rdpdr, s) == CHANNEL_RC_OK;
961 case PAKID_CORE_CLIENTID_CONFIRM:
963 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM)
965 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
"got duplicate packetid %s",
966 rdpdr_packetid_string(packetid));
969 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
970 return rdpdr_process_server_clientid_confirm(rdpdr, s) == CHANNEL_RC_OK;
974#if defined(WITH_PROXY_EMULATE_SMARTCARD)
976static UINT rdpdr_send_emulated_scard_device_list_announce_request(pClientContext* pc,
977 pf_channel_client_context* rdpdr)
981 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_ANNOUNCE, 24);
983 return CHANNEL_RC_NO_MEMORY;
985 Stream_Write_UINT32(s, 1);
986 Stream_Write_UINT32(s, RDPDR_DTYP_SMARTCARD);
989 Stream_Write(s,
"SCARD\0\0\0", 8);
990 Stream_Write_UINT32(s, 6);
991 Stream_Write(s,
"SCARD\0", 6);
993 return rdpdr_client_send(rdpdr->log, pc, s);
997static UINT rdpdr_send_emulated_scard_device_remove(pClientContext* pc,
998 pf_channel_client_context* rdpdr)
1002 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_REMOVE, 24);
1004 return CHANNEL_RC_NO_MEMORY;
1006 Stream_Write_UINT32(s, 1);
1007 Stream_Write_UINT32(
1008 s, SCARD_DEVICE_ID);
1010 return rdpdr_client_send(rdpdr->log, pc, s);
1014static UINT rdpdr_process_server_device_announce_response(pf_channel_client_context* rdpdr,
1017 const UINT16 component = RDPDR_CTYP_CORE;
1018 const UINT16 packetid = PAKID_CORE_DEVICE_REPLY;
1019 UINT32 deviceID = 0;
1020 UINT32 resultCode = 0;
1022 WINPR_ASSERT(rdpdr);
1025 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
1026 return ERROR_INVALID_DATA;
1028 Stream_Read_UINT32(s, deviceID);
1029 Stream_Read_UINT32(s, resultCode);
1031 if (deviceID != SCARD_DEVICE_ID)
1033 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1034 "[%s | %s] deviceID mismatch, sent 0x%08" PRIx32
", changed to 0x%08" PRIx32,
1035 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1036 SCARD_DEVICE_ID, deviceID);
1038 else if (resultCode != 0)
1040 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1041 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32,
1042 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1046 CLIENT_RX_LOG(rdpdr->log, WLOG_DEBUG,
1047 "[%s | %s] deviceID 0x%08" PRIx32
" resultCode=0x%08" PRIx32
1048 " -> emulated smartcard redirected!",
1049 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1052 return CHANNEL_RC_OK;
1057static BOOL pf_channel_rdpdr_rewrite_device_list_to(
wStream* s, UINT32 fromVersion,
1061 if (fromVersion == toVersion)
1064 const size_t cap = Stream_GetRemainingLength(s);
1065 wStream* clone = Stream_New(
nullptr, cap);
1070 const size_t pos = Stream_GetPosition(s);
1071 Stream_Copy(s, clone, cap);
1072 Stream_SealLength(clone);
1074 Stream_ResetPosition(clone);
1075 if (!Stream_SetPosition(s, pos))
1080 if (!Stream_SafeSeek(s, 4))
1085 if (Stream_GetRemainingLength(clone) < 4)
1087 Stream_Read_UINT32(clone, count);
1089 for (UINT32 x = 0; x < count; x++)
1092 const size_t charCount = ARRAYSIZE(device.PreferredDosName);
1093 if (Stream_GetRemainingLength(clone) < 20)
1096 Stream_Read_UINT32(clone, device.DeviceType);
1097 Stream_Read_UINT32(clone, device.DeviceId);
1098 Stream_Read(clone, device.PreferredDosName, charCount);
1099 Stream_Read_UINT32(clone, device.DeviceDataLength);
1100 device.DeviceData = Stream_Pointer(clone);
1101 if (!Stream_SafeSeek(clone, device.DeviceDataLength))
1104 if (!Stream_EnsureRemainingCapacity(s, 20))
1106 Stream_Write_UINT32(s, device.DeviceType);
1107 Stream_Write_UINT32(s, device.DeviceId);
1108 Stream_Write(s, device.PreferredDosName, charCount);
1110 if (device.DeviceType == RDPDR_DTYP_FILESYSTEM)
1112 if (toVersion == DRIVE_CAPABILITY_VERSION_01)
1113 Stream_Write_UINT32(s, 0);
1116 const SSIZE_T devNameWLen = ConvertUtf8NToWChar(
1117 device.PreferredDosName, ARRAYSIZE(device.PreferredDosName),
nullptr, 0);
1118 if (devNameWLen < 0)
1120 const size_t datalen =
1121 WINPR_ASSERTING_INT_CAST(
size_t, devNameWLen) *
sizeof(WCHAR);
1122 if (!Stream_EnsureRemainingCapacity(s, datalen +
sizeof(UINT32)))
1124 Stream_Write_UINT32(s, WINPR_ASSERTING_INT_CAST(uint32_t, datalen));
1126 const SSIZE_T rcw = Stream_Write_UTF16_String_From_UTF8(
1127 s, charCount, device.PreferredDosName, charCount - 1, TRUE);
1134 Stream_Write_UINT32(s, device.DeviceDataLength);
1135 if (!Stream_EnsureRemainingCapacity(s, device.DeviceDataLength))
1137 Stream_Write(s, device.DeviceData, device.DeviceDataLength);
1142 Stream_SealLength(s);
1146 Stream_Free(clone, TRUE);
1151static BOOL pf_channel_rdpdr_rewrite_device_list(pf_channel_client_context* rdpdr,
1152 pServerContext* ps,
wStream* s, BOOL toServer)
1154 WINPR_ASSERT(rdpdr);
1157 const size_t pos = Stream_GetPosition(s);
1158 UINT16 component = 0;
1159 UINT16 packetid = 0;
1160 Stream_ResetPosition(s);
1162 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1165 Stream_Read_UINT16(s, component);
1166 Stream_Read_UINT16(s, packetid);
1167 if ((component != RDPDR_CTYP_CORE) || (packetid != PAKID_CORE_DEVICELIST_ANNOUNCE))
1168 return Stream_SetPosition(s, pos);
1170 const pf_channel_server_context* srv =
1171 HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1174 WLog_Print(rdpdr->log, WLOG_ERROR,
"No channel %s in intercep map", RDPDR_SVC_CHANNEL_NAME);
1178 UINT32 from = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1179 UINT32 to = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1182 from = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1183 to = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1185 if (!pf_channel_rdpdr_rewrite_device_list_to(s, from, to))
1188 return Stream_SetPosition(s, pos);
1192static BOOL pf_channel_rdpdr_client_send_to_server(pf_channel_client_context* rdpdr,
1193 pServerContext* ps,
wStream* s)
1195 WINPR_ASSERT(rdpdr);
1198 UINT16 server_channel_id = WTSChannelGetId(ps->context.peer, RDPDR_SVC_CHANNEL_NAME);
1203 if (server_channel_id == 0)
1206 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, TRUE))
1208 size_t len = Stream_Length(s);
1209 if (!Stream_SetPosition(s, len))
1210 return ERROR_INVALID_DATA;
1211 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_tx);
1212 WINPR_ASSERT(ps->context.peer);
1213 WINPR_ASSERT(ps->context.peer->SendChannelData);
1214 return ps->context.peer->SendChannelData(ps->context.peer, server_channel_id,
1215 Stream_Buffer(s), len);
1221static BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr);
1223#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1225static BOOL rdpdr_process_server_loggedon_request(pServerContext* ps, pClientContext* pc,
1226 pf_channel_client_context* rdpdr,
wStream* s,
1227 UINT16 component, UINT16 packetid)
1229 WINPR_ASSERT(rdpdr);
1230 WLog_Print(rdpdr->log, WLOG_DEBUG,
"[%s | %s]", rdpdr_component_string(component),
1231 rdpdr_packetid_string(packetid));
1232 if (rdpdr_send_emulated_scard_device_remove(pc, rdpdr) != CHANNEL_RC_OK)
1234 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) != CHANNEL_RC_OK)
1236 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1240static BOOL filter_smartcard_io_requests(pf_channel_client_context* rdpdr,
wStream* s,
1244 UINT16 component = 0;
1245 UINT16 packetid = 0;
1246 UINT32 deviceID = 0;
1249 WINPR_ASSERT(rdpdr);
1250 WINPR_ASSERT(pPacketid);
1252 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1255 pos = Stream_GetPosition(s);
1256 Stream_Read_UINT16(s, component);
1257 Stream_Read_UINT16(s, packetid);
1259 if (Stream_GetRemainingLength(s) >= 4)
1260 Stream_Read_UINT32(s, deviceID);
1262 WLog_Print(rdpdr->log, WLOG_DEBUG,
"got: [%s | %s]: [0x%08" PRIx32
"]",
1263 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID);
1265 if (component != RDPDR_CTYP_CORE)
1270 case PAKID_CORE_SERVER_ANNOUNCE:
1271 case PAKID_CORE_CLIENTID_CONFIRM:
1272 case PAKID_CORE_CLIENT_NAME:
1273 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1274 case PAKID_CORE_DEVICELIST_REMOVE:
1275 case PAKID_CORE_SERVER_CAPABILITY:
1276 case PAKID_CORE_CLIENT_CAPABILITY:
1277 WLog_Print(rdpdr->log, WLOG_WARN,
"Filtering client -> server message [%s | %s]",
1278 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1279 *pPacketid = packetid;
1281 case PAKID_CORE_USER_LOGGEDON:
1282 *pPacketid = packetid;
1284 case PAKID_CORE_DEVICE_REPLY:
1285 case PAKID_CORE_DEVICE_IOREQUEST:
1286 if (deviceID != SCARD_DEVICE_ID)
1288 *pPacketid = packetid;
1291 if (deviceID != SCARD_DEVICE_ID)
1293 WLog_Print(rdpdr->log, WLOG_WARN,
1294 "Got [%s | %s] for deviceID 0x%08" PRIx32
", TODO: Not handled!",
1295 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1303 if (!Stream_SetPosition(s, pos))
1309BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr)
1312 WINPR_ASSERT(rdpdr);
1314 if (rdpdr->state != STATE_CLIENT_CHANNEL_RUNNING)
1316 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
"Client RDPDR channel not ready, dropping packet!");
1320 const UINT16 channelId =
1321 freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
1322 if ((channelId == 0) || (channelId == UINT16_MAX))
1324 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
1325 "Client RDPDR channel not available, dropping packet!");
1329 Queue_Lock(rdpdr->queue);
1330 while (Queue_Count(rdpdr->queue) > 0)
1332 wStream* s = Queue_Dequeue(rdpdr->queue);
1336 size_t len = Stream_Length(s);
1337 if (!Stream_SetPosition(s, len))
1339 Stream_Free(s, TRUE);
1343 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_tx
" (queue) ");
1344 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
1345 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
1346 Stream_Buffer(s), len))
1348 CLIENT_TX_LOG(rdpdr->log, WLOG_ERROR,
"xxxxxx TODO: Failed to send data!");
1350 Stream_Free(s, TRUE);
1352 Queue_Unlock(rdpdr->queue);
1357static BOOL rdpdr_handle_server_announce_request(pClientContext* pc,
1358 pf_channel_client_context* rdpdr,
wStream* s)
1361 WINPR_ASSERT(rdpdr);
1364 if (rdpdr_process_server_announce_request(rdpdr, s) != CHANNEL_RC_OK)
1366 if (rdpdr_send_client_announce_reply(pc, rdpdr) != CHANNEL_RC_OK)
1368 if (rdpdr_send_client_name_request(pc, rdpdr) != CHANNEL_RC_OK)
1370 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1374BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId,
const char* channel_name,
1375 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1377#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1378 UINT16 packetid = 0;
1382 WINPR_ASSERT(pc->pdata);
1383 WINPR_ASSERT(pc->interceptContextMap);
1384 WINPR_ASSERT(channel_name);
1385 WINPR_ASSERT(xdata);
1387 pServerContext* ps = proxy_data_get_server_context(pc->pdata);
1389 pf_channel_client_context* rdpdr =
1390 HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1393 CLIENT_RX_LOG(WLog_Get(RTAG), WLOG_ERROR,
1394 "Channel %s [0x%04" PRIx16
"] missing context in interceptContextMap",
1395 channel_name, channelId);
1399 wStream* s = rdpdr->common.buffer;
1400 if (flags & CHANNEL_FLAG_FIRST)
1402 Stream_ResetPosition(s);
1403 rdpdr->common.totalLength = totalSize;
1406 if (!Stream_EnsureRemainingCapacity(s, xsize))
1408 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1409 "Channel %s [0x%04" PRIx16
"] not enough memory [need %" PRIuz
"]",
1410 channel_name, channelId, xsize);
1413 Stream_Write(s, xdata, xsize);
1415 if ((Stream_GetPosition(s) > totalSize) || (totalSize != rdpdr->common.totalLength))
1417 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1418 "Channel %s [0x%04" PRIx16
"] total size mismatch [got %" PRIuz
1419 ", expected %" PRIuz
"]",
1420 channel_name, channelId, totalSize, rdpdr->common.totalLength);
1424 if ((flags & CHANNEL_FLAG_LAST) == 0)
1427 Stream_SealLength(s);
1428 Stream_ResetPosition(s);
1429 rdpdr->common.totalLength = 0;
1430 if (Stream_Length(s) != totalSize)
1432 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1433 "Received invalid %s channel data (server -> proxy), expected %" PRIuz
1434 "bytes, got %" PRIuz,
1435 channel_name, totalSize, Stream_Length(s));
1439 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_rx);
1440 switch (rdpdr->state)
1442 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
1443 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1446 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
1447 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1449 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
1451 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
1452 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1454 if (rdpdr_send_client_capability_response(pc, rdpdr) != CHANNEL_RC_OK)
1456#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1457 if (pf_channel_smartcard_client_emulate(pc))
1459 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) !=
1462 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1467 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1468 if (!pf_channel_send_client_queue(pc, rdpdr))
1473 case STATE_CLIENT_CHANNEL_RUNNING:
1474#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1475 if (!pf_channel_smartcard_client_emulate(pc) ||
1476 !filter_smartcard_io_requests(rdpdr, s, &packetid))
1477 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1482 case PAKID_CORE_USER_LOGGEDON:
1483 return rdpdr_process_server_loggedon_request(ps, pc, rdpdr, s,
1484 RDPDR_CTYP_CORE, packetid);
1485 case PAKID_CORE_DEVICE_IOREQUEST:
1487 wStream* out = rdpdr_client_get_send_buffer(
1488 rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOCOMPLETION, 0);
1491 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
1492 PAKID_CORE_DEVICE_IOREQUEST, 20))
1495 if (!pf_channel_smartcard_client_handle(rdpdr->log, pc, s, out,
1500 case PAKID_CORE_SERVER_ANNOUNCE:
1501 pf_channel_rdpdr_client_reset(pc);
1502 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1505 case PAKID_CORE_SERVER_CAPABILITY:
1506 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1508 return pf_channel_rdpdr_client_handle(pc, channelId, channel_name, xdata,
1509 xsize, flags, totalSize);
1510 case PAKID_CORE_DEVICE_REPLY:
1514 rdpdr->log, WLOG_ERROR,
1515 "Channel %s [0x%04" PRIx16
1516 "] we´ve reached an impossible state %s! [%s] aliens invaded!",
1517 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state),
1518 rdpdr_packetid_string(packetid));
1524 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1527 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1528 "Channel %s [0x%04" PRIx16
1529 "] we´ve reached an impossible state %s! aliens invaded!",
1530 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state));
1537static void pf_channel_rdpdr_common_context_free(pf_channel_common_context* common)
1541 free(common->computerName.v);
1542 Stream_Free(common->s, TRUE);
1543 Stream_Free(common->buffer, TRUE);
1548 pf_channel_client_context* entry = (pf_channel_client_context*)base;
1552 pf_channel_rdpdr_common_context_free(&entry->common);
1553 Queue_Free(entry->queue);
1554 WLog_Discard(entry->log);
1559static BOOL pf_channel_rdpdr_common_context_new(pf_channel_common_context* common,
1564 common->base.free = fkt;
1565 common->s = Stream_New(
nullptr, 1024);
1568 common->buffer = Stream_New(
nullptr, 1024);
1569 if (!common->buffer)
1571 common->computerNameUnicode = 1;
1572 common->computerName.v =
nullptr;
1573 common->versionMajor = RDPDR_VERSION_MAJOR;
1574 common->versionMinor = RDPDR_VERSION_MINOR_RDP10X;
1575 common->clientID = SCARD_DEVICE_ID;
1577 const UINT32 versions[] = { 0,
1578 GENERAL_CAPABILITY_VERSION_02,
1579 PRINT_CAPABILITY_VERSION_01,
1580 PORT_CAPABILITY_VERSION_01,
1581 DRIVE_CAPABILITY_VERSION_02,
1582 SMARTCARD_CAPABILITY_VERSION_01 };
1584 memcpy(common->capabilityVersions, versions,
sizeof(common->capabilityVersions));
1589static BOOL pf_channel_rdpdr_client_pass_message(pServerContext* ps, pClientContext* pc,
1590 WINPR_ATTR_UNUSED UINT16 channelId,
1591 const char* channel_name,
wStream* s)
1593 pf_channel_client_context* rdpdr =
nullptr;
1598 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1601 WINPR_ASSERT(rdpdr->queue);
1603 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, FALSE))
1605 if (!Queue_Enqueue(rdpdr->queue, s))
1607 return pf_channel_send_client_queue(pc, rdpdr);
1610#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1612static BOOL filter_smartcard_device_list_remove(pf_channel_server_context* rdpdr,
wStream* s)
1617 WINPR_ASSERT(rdpdr);
1618 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1620 pos = Stream_GetPosition(s);
1621 Stream_Read_UINT32(s, count);
1626 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdpdr->log, s, count,
sizeof(UINT32)))
1629 for (UINT32 x = 0; x < count; x++)
1631 UINT32 deviceID = 0;
1632 BYTE* dst = Stream_Pointer(s);
1633 Stream_Read_UINT32(s, deviceID);
1634 if (deviceID == SCARD_DEVICE_ID)
1636 ArrayList_Remove(rdpdr->blockedDevices, (
void*)(
size_t)deviceID);
1643 memmove(dst, Stream_ConstPointer(s), (count - x - 1) *
sizeof(UINT32));
1646 if (Stream_SetPosition(s, pos))
1647 Stream_Write_UINT32(s, count);
1656static BOOL filter_smartcard_device_io_request(pf_channel_server_context* rdpdr,
wStream* s)
1658 UINT32 DeviceID = 0;
1659 WINPR_ASSERT(rdpdr);
1661 Stream_Read_UINT32(s, DeviceID);
1662 return ArrayList_Contains(rdpdr->blockedDevices, (
void*)(
size_t)DeviceID);
1666static BOOL filter_smartcard_device_list_announce(pf_channel_server_context* rdpdr,
wStream* s)
1670 WINPR_ASSERT(rdpdr);
1671 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s,
sizeof(UINT32)))
1673 const size_t pos = Stream_GetPosition(s);
1674 Stream_Read_UINT32(s, count);
1679 for (UINT32 x = 0; x < count; x++)
1681 UINT32 DeviceType = 0;
1682 UINT32 DeviceId = 0;
1683 char PreferredDosName[8];
1684 UINT32 DeviceDataLength = 0;
1685 BYTE* dst = Stream_Pointer(s);
1686 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 20))
1688 Stream_Read_UINT32(s, DeviceType);
1689 Stream_Read_UINT32(s, DeviceId);
1690 Stream_Read(s, PreferredDosName, ARRAYSIZE(PreferredDosName));
1691 Stream_Read_UINT32(s, DeviceDataLength);
1692 if (!Stream_SafeSeek(s, DeviceDataLength))
1694 if (DeviceType == RDPDR_DTYP_SMARTCARD)
1696 if (!ArrayList_Append(rdpdr->blockedDevices, (
void*)(
size_t)DeviceId))
1701 WLog_Print(rdpdr->log, WLOG_INFO,
"Filtering smartcard device 0x%08" PRIx32
"",
1704 memmove(dst, Stream_ConstPointer(s), Stream_GetRemainingLength(s));
1705 if (Stream_SetPosition(s, pos))
1706 Stream_Write_UINT32(s, count - 1);
1715static BOOL filter_smartcard_device_list_announce_request(pf_channel_server_context* rdpdr,
1720 UINT16 component = 0;
1721 UINT16 packetid = 0;
1723 WINPR_ASSERT(rdpdr);
1724 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8))
1727 pos = Stream_GetPosition(s);
1729 Stream_Read_UINT16(s, component);
1730 Stream_Read_UINT16(s, packetid);
1732 if (component != RDPDR_CTYP_CORE)
1737 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1738 if (filter_smartcard_device_list_announce(rdpdr, s))
1741 case PAKID_CORE_DEVICELIST_REMOVE:
1742 if (filter_smartcard_device_list_remove(rdpdr, s))
1745 case PAKID_CORE_DEVICE_IOREQUEST:
1746 if (filter_smartcard_device_io_request(rdpdr, s))
1750 case PAKID_CORE_SERVER_ANNOUNCE:
1751 case PAKID_CORE_CLIENTID_CONFIRM:
1752 case PAKID_CORE_CLIENT_NAME:
1753 case PAKID_CORE_DEVICE_REPLY:
1754 case PAKID_CORE_SERVER_CAPABILITY:
1755 case PAKID_CORE_CLIENT_CAPABILITY:
1756 case PAKID_CORE_USER_LOGGEDON:
1757 WLog_Print(rdpdr->log, WLOG_WARN,
"Filtering client -> server message [%s | %s]",
1758 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1766 if (!Stream_SetPosition(s, pos))
1772WINPR_ATTR_MALLOC(Stream_Free, 1)
1774static
void* stream_copy(const
void* obj)
1777 wStream* dst = Stream_New(
nullptr, Stream_Capacity(src));
1780 memcpy(Stream_Buffer(dst), Stream_ConstBuffer(src), Stream_Capacity(dst));
1781 if (!Stream_SetLength(dst, Stream_Length(src)))
1783 if (!Stream_SetPosition(dst, Stream_GetPosition(src)))
1787 Stream_Free(dst, TRUE);
1791static void stream_free(
void* obj)
1794 Stream_Free(s, TRUE);
1798static const char* pf_channel_rdpdr_client_context(
void* arg)
1800 pClientContext* pc = arg;
1804 return "pc->pdata=null";
1805 return pc->pdata->session_id;
1808BOOL pf_channel_rdpdr_client_new(pClientContext* pc)
1811 pf_channel_client_context* rdpdr =
nullptr;
1814 WINPR_ASSERT(pc->interceptContextMap);
1816 rdpdr = calloc(1,
sizeof(pf_channel_client_context));
1819 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1823 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_client_context, pc))
1826 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_client_context_free))
1829 rdpdr->maxMajorVersion = RDPDR_VERSION_MAJOR;
1830 rdpdr->maxMinorVersion = RDPDR_VERSION_MINOR_RDP10X;
1831 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
1833 rdpdr->queue = Queue_New(TRUE, 0, 0);
1836 obj = Queue_Object(rdpdr->queue);
1840 if (!HashTable_Insert(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1845 pf_channel_rdpdr_client_context_free(&rdpdr->common.base);
1849void pf_channel_rdpdr_client_free(pClientContext* pc)
1852 WINPR_ASSERT(pc->interceptContextMap);
1853 HashTable_Remove(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1858 pf_channel_server_context* entry = (pf_channel_server_context*)base;
1862 (void)WTSVirtualChannelClose(entry->handle);
1863 pf_channel_rdpdr_common_context_free(&entry->common);
1864 ArrayList_Free(entry->blockedDevices);
1865 WLog_Discard(entry->log);
1870static const char* pf_channel_rdpdr_server_context(
void* arg)
1872 pServerContext* ps = arg;
1876 return "ps->pdata=null";
1877 return ps->pdata->session_id;
1880BOOL pf_channel_rdpdr_server_new(pServerContext* ps)
1882 pf_channel_server_context* rdpdr =
nullptr;
1883 PULONG pSessionId =
nullptr;
1884 DWORD BytesReturned = 0;
1887 WINPR_ASSERT(ps->interceptContextMap);
1889 rdpdr = calloc(1,
sizeof(pf_channel_server_context));
1892 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1896 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_server_context, ps))
1899 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_server_context_free))
1901 rdpdr->state = STATE_SERVER_INITIAL;
1903 rdpdr->blockedDevices = ArrayList_New(FALSE);
1904 if (!rdpdr->blockedDevices)
1907 rdpdr->SessionId = WTS_CURRENT_SESSION;
1908 if (WTSQuerySessionInformationA(ps->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*)&pSessionId,
1911 rdpdr->SessionId = (DWORD)*pSessionId;
1912 WTSFreeMemory(pSessionId);
1915 rdpdr->handle = WTSVirtualChannelOpenEx(rdpdr->SessionId, RDPDR_SVC_CHANNEL_NAME, 0);
1916 if (rdpdr->handle ==
nullptr)
1918 if (!HashTable_Insert(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1924 pf_channel_rdpdr_server_context_free(&rdpdr->common.base);
1928void pf_channel_rdpdr_server_free(pServerContext* ps)
1931 WINPR_ASSERT(ps->interceptContextMap);
1932 HashTable_Remove(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1936static pf_channel_server_context* get_channel(pServerContext* ps, BOOL send)
1938 pf_channel_server_context* rdpdr =
nullptr;
1940 WINPR_ASSERT(ps->interceptContextMap);
1942 rdpdr = HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1945 SERVER_RXTX_LOG(send, WLog_Get(RTAG), WLOG_ERROR,
1946 "Channel %s missing context in interceptContextMap",
1947 RDPDR_SVC_CHANNEL_NAME);
1954BOOL pf_channel_rdpdr_server_handle(pServerContext* ps, UINT16 channelId,
const char* channel_name,
1955 const BYTE* xdata,
size_t xsize, UINT32 flags,
size_t totalSize)
1957 pf_channel_server_context* rdpdr = get_channel(ps, FALSE);
1961 WINPR_ASSERT(ps->pdata);
1962 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
1964 wStream* s = rdpdr->common.buffer;
1966 if (flags & CHANNEL_FLAG_FIRST)
1968 rdpdr->common.totalLength = totalSize;
1969 Stream_ResetPosition(s);
1972 if (!Stream_EnsureRemainingCapacity(s, xsize))
1974 Stream_Write(s, xdata, xsize);
1976 if ((Stream_GetPosition(s) > totalSize) || (totalSize != rdpdr->common.totalLength))
1979 if ((flags & CHANNEL_FLAG_LAST) == 0)
1982 Stream_SealLength(s);
1983 Stream_ResetPosition(s);
1984 rdpdr->common.totalLength = 0;
1986 if (Stream_Length(s) != totalSize)
1988 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
1989 "Received invalid %s channel data (client -> proxy), expected %" PRIuz
1990 "bytes, got %" PRIuz,
1991 channel_name, totalSize, Stream_Length(s));
1995 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_rx);
1996 switch (rdpdr->state)
1998 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
1999 if (rdpdr_process_client_announce_reply(rdpdr, s) != CHANNEL_RC_OK)
2001 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST;
2003 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
2004 if (rdpdr_process_client_name_request(rdpdr, s, pc) != CHANNEL_RC_OK)
2006 if (rdpdr_send_server_capability_request(rdpdr) != CHANNEL_RC_OK)
2008 if (rdpdr_send_server_clientid_confirm(rdpdr) != CHANNEL_RC_OK)
2010 rdpdr->state = STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE;
2012 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
2013 if (rdpdr_process_client_capability_response(rdpdr, s) != CHANNEL_RC_OK)
2015 rdpdr->state = STATE_SERVER_CHANNEL_RUNNING;
2017 case STATE_SERVER_CHANNEL_RUNNING:
2018#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2019 if (!pf_channel_smartcard_client_emulate(pc) ||
2020 !filter_smartcard_device_list_announce_request(rdpdr, s))
2022 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2026 return pf_channel_smartcard_server_handle(ps, s);
2028 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2033 case STATE_SERVER_INITIAL:
2034 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
"Invalid state %s",
2035 rdpdr_server_state_to_string(rdpdr->state));
2042BOOL pf_channel_rdpdr_server_announce(pServerContext* ps)
2044 pf_channel_server_context* rdpdr = get_channel(ps, TRUE);
2048 WINPR_ASSERT(rdpdr->state == STATE_SERVER_INITIAL);
2049 if (rdpdr_server_send_announce_request(rdpdr) != CHANNEL_RC_OK)
2051 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY;
2055BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
2057 pf_channel_client_context* rdpdr =
nullptr;
2060 WINPR_ASSERT(pc->pdata);
2061 WINPR_ASSERT(pc->interceptContextMap);
2063 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
2067 Queue_Clear(rdpdr->queue);
2069 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
2075static PfChannelResult pf_rdpdr_back_data(proxyData* pdata,
2076 const pServerStaticChannelContext* channel,
2077 const BYTE* xdata,
size_t xsize, UINT32 flags,
2080 WINPR_ASSERT(pdata);
2081 WINPR_ASSERT(channel);
2083 pClientContext* pc = proxy_data_get_client_context(pdata);
2084 if (!pf_channel_rdpdr_client_handle(pc,
2085 WINPR_ASSERTING_INT_CAST(UINT16, channel->back_channel_id),
2086 channel->channel_name, xdata, xsize, flags, totalSize))
2087 return PF_CHANNEL_RESULT_ERROR;
2089#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2090 if (pf_channel_smartcard_client_emulate((pClientContext*)pdata->pc))
2091 return PF_CHANNEL_RESULT_DROP;
2093 return PF_CHANNEL_RESULT_DROP;
2097static PfChannelResult pf_rdpdr_front_data(proxyData* pdata,
2098 const pServerStaticChannelContext* channel,
2099 const BYTE* xdata,
size_t xsize, UINT32 flags,
2102 WINPR_ASSERT(pdata);
2103 WINPR_ASSERT(channel);
2105 pServerContext* ps = proxy_data_get_server_context(pdata);
2106 if (!pf_channel_rdpdr_server_handle(ps,
2107 WINPR_ASSERTING_INT_CAST(UINT16, channel->front_channel_id),
2108 channel->channel_name, xdata, xsize, flags, totalSize))
2109 return PF_CHANNEL_RESULT_ERROR;
2111#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2112 if (pf_channel_smartcard_client_emulate((pClientContext*)pdata->pc))
2113 return PF_CHANNEL_RESULT_DROP;
2115 return PF_CHANNEL_RESULT_DROP;
2118BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
2120 channel->onBackData = pf_rdpdr_back_data;
2121 channel->onFrontData = pf_rdpdr_front_data;
2123 if (!pf_channel_rdpdr_server_new(ps))
2125 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