FreeRDP
Loading...
Searching...
No Matches
pf_channel_rdpdr.c
1
21#include <freerdp/config.h>
22
23#include <winpr/assert.h>
24#include <winpr/cast.h>
25#include <winpr/string.h>
26#include <winpr/print.h>
27
28#include "../pf_client.h"
29#include "../pf_server.h"
30#include "pf_channel_rdpdr.h"
31#include "pf_channel_smartcard.h"
32
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>
37
38#define RTAG PROXY_TAG("channel.rdpdr")
39
40#define SCARD_DEVICE_ID UINT32_MAX
41
42typedef struct
43{
45 wStream* s;
46 wStream* buffer;
47 UINT16 versionMajor;
48 UINT16 versionMinor;
49 UINT32 clientID;
50 UINT32 computerNameLen;
51 BOOL computerNameUnicode;
52 union
53 {
54 WCHAR* wc;
55 char* c;
56 void* v;
57 } computerName;
58 UINT32 SpecialDeviceCount;
59 UINT32 capabilityVersions[6];
60} pf_channel_common_context;
61
62typedef enum
63{
64 STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST = 0x01,
65 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST = 0x02,
66 STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM = 0x04,
67 STATE_CLIENT_CHANNEL_RUNNING = 0x10
68} pf_channel_client_state;
69
70typedef struct
71{
72 pf_channel_common_context common;
73 pf_channel_client_state state;
74 UINT32 flags;
75 UINT16 maxMajorVersion;
76 UINT16 maxMinorVersion;
77 wQueue* queue;
78 wLog* log;
79} pf_channel_client_context;
80
81typedef enum
82{
83 STATE_SERVER_INITIAL,
84 STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY,
85 STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST,
86 STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE,
87 STATE_SERVER_CHANNEL_RUNNING
88} pf_channel_server_state;
89
90typedef struct
91{
92 pf_channel_common_context common;
93 pf_channel_server_state state;
94 DWORD SessionId;
95 HANDLE handle;
96 wArrayList* blockedDevices;
97 wLog* log;
98} pf_channel_server_context;
99
100#define proxy_client "[proxy<-->client]"
101#define proxy_server "[proxy<-->server]"
102
103#define proxy_client_rx proxy_client " receive"
104#define proxy_client_tx proxy_client " send"
105#define proxy_server_rx proxy_server " receive"
106#define proxy_server_tx proxy_server " send"
107
108#define SERVER_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_rx fmt, ##__VA_ARGS__)
109#define CLIENT_RX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_rx fmt, ##__VA_ARGS__)
110#define SERVER_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_client_tx fmt, ##__VA_ARGS__)
111#define CLIENT_TX_LOG(log, lvl, fmt, ...) WLog_Print(log, lvl, proxy_server_tx fmt, ##__VA_ARGS__)
112#define RX_LOG(srv, lvl, fmt, ...) \
113 do \
114 { \
115 if (srv) \
116 { \
117 SERVER_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
118 } \
119 else \
120 { \
121 CLIENT_RX_LOG(lvl, fmt, ##__VA_ARGS__); \
122 } \
123 } while (0)
124
125#define SERVER_RXTX_LOG(send, log, lvl, fmt, ...) \
126 do \
127 { \
128 if (send) \
129 { \
130 SERVER_TX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
131 } \
132 else \
133 { \
134 SERVER_RX_LOG(log, lvl, fmt, ##__VA_ARGS__); \
135 } \
136 } while (0)
137
138#define Stream_CheckAndLogRequiredLengthSrv(log, s, len) \
139 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
140 proxy_client_rx " %s(%s:%" PRIuz ")", __func__, \
141 __FILE__, (size_t)__LINE__)
142#define Stream_CheckAndLogRequiredLengthClient(log, s, len) \
143 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, len, 1, \
144 proxy_server_rx " %s(%s:%" PRIuz ")", __func__, \
145 __FILE__, (size_t)__LINE__)
146#define Stream_CheckAndLogRequiredLengthRx(srv, log, s, len) \
147 Stream_CheckAndLogRequiredLengthRx_(srv, log, s, len, 1, __func__, __FILE__, __LINE__)
148WINPR_ATTR_NODISCARD
149static BOOL Stream_CheckAndLogRequiredLengthRx_(BOOL srv, wLog* log, wStream* s, size_t nmemb,
150 size_t size, const char* fkt, const char* file,
151 size_t line)
152{
153 const char* fmt =
154 srv ? proxy_server_rx " %s(%s:%" PRIuz ")" : proxy_client_rx " %s(%s:%" PRIuz ")";
155
156 return Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, fmt, fkt, file,
157 line);
158}
159
160WINPR_ATTR_NODISCARD
161static const char* rdpdr_server_state_to_string(pf_channel_server_state state)
162{
163 switch (state)
164 {
165 case STATE_SERVER_INITIAL:
166 return "STATE_SERVER_INITIAL";
167 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
168 return "STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY";
169 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
170 return "STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST";
171 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
172 return "STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE";
173 case STATE_SERVER_CHANNEL_RUNNING:
174 return "STATE_SERVER_CHANNEL_RUNNING";
175 default:
176 return "STATE_SERVER_UNKNOWN";
177 }
178}
179
180WINPR_ATTR_NODISCARD
181static const char* rdpdr_client_state_to_string(pf_channel_client_state state)
182{
183 switch (state)
184 {
185 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
186 return "STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST";
187 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
188 return "STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST";
189 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
190 return "STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM";
191 case STATE_CLIENT_CHANNEL_RUNNING:
192 return "STATE_CLIENT_CHANNEL_RUNNING";
193 default:
194 return "STATE_CLIENT_UNKNOWN";
195 }
196}
197
198WINPR_ATTR_NODISCARD
199static wStream* rdpdr_get_send_buffer(pf_channel_common_context* rdpdr, UINT16 component,
200 UINT16 PacketID, size_t capacity)
201{
202 WINPR_ASSERT(rdpdr);
203 WINPR_ASSERT(rdpdr->s);
204 Stream_ResetPosition(rdpdr->s);
205
206 if (!Stream_EnsureCapacity(rdpdr->s, capacity + 4))
207 return nullptr;
208 Stream_Write_UINT16(rdpdr->s, component);
209 Stream_Write_UINT16(rdpdr->s, PacketID);
210 return rdpdr->s;
211}
212
213WINPR_ATTR_NODISCARD
214static wStream* rdpdr_client_get_send_buffer(pf_channel_client_context* rdpdr, UINT16 component,
215 UINT16 PacketID, size_t capacity)
216{
217 WINPR_ASSERT(rdpdr);
218 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
219}
220
221WINPR_ATTR_NODISCARD
222static wStream* rdpdr_server_get_send_buffer(pf_channel_server_context* rdpdr, UINT16 component,
223 UINT16 PacketID, size_t capacity)
224{
225 WINPR_ASSERT(rdpdr);
226 return rdpdr_get_send_buffer(&rdpdr->common, component, PacketID, capacity);
227}
228
229WINPR_ATTR_NODISCARD
230static UINT rdpdr_client_send(wLog* log, pClientContext* pc, wStream* s)
231{
232 UINT16 channelId = 0;
233
234 WINPR_ASSERT(log);
235 WINPR_ASSERT(pc);
236 WINPR_ASSERT(s);
237 WINPR_ASSERT(pc->cctx.context.instance);
238
239 if (!pc->connected)
240 {
241 CLIENT_TX_LOG(log, WLOG_WARN, "Ignoring channel %s message, not connected!",
242 RDPDR_SVC_CHANNEL_NAME);
243 return CHANNEL_RC_OK;
244 }
245
246 channelId = freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
247 /* Ignore unmappable channels. Might happen when the channel was already down and
248 * some delayed message is tried to be sent. */
249 if ((channelId == 0) || (channelId == UINT16_MAX))
250 return ERROR_INTERNAL_ERROR;
251
252 Stream_SealLength(s);
253 rdpdr_dump_send_packet(log, WLOG_TRACE, s, proxy_server_tx);
254 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
255 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
256 Stream_Buffer(s), Stream_Length(s)))
257 return ERROR_EVT_CHANNEL_NOT_FOUND;
258 return CHANNEL_RC_OK;
259}
260
261WINPR_ATTR_NODISCARD
262static UINT rdpdr_seal_send_free_request(pf_channel_server_context* context, wStream* s)
263{
264 BOOL status = 0;
265 size_t len = 0;
266
267 WINPR_ASSERT(context);
268 WINPR_ASSERT(context->handle);
269 WINPR_ASSERT(s);
270
271 Stream_SealLength(s);
272 len = Stream_Length(s);
273 WINPR_ASSERT(len <= UINT32_MAX);
274
275 rdpdr_dump_send_packet(context->log, WLOG_TRACE, s, proxy_client_tx);
276 status = WTSVirtualChannelWrite(context->handle, Stream_BufferAs(s, char), (ULONG)len, nullptr);
277 return (status) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
278}
279
280WINPR_ATTR_NODISCARD
281static BOOL rdpdr_process_server_header(BOOL server, wLog* log, wStream* s, UINT16 component,
282 UINT16 PacketId, size_t expect)
283{
284 UINT16 rpacketid = 0;
285 UINT16 rcomponent = 0;
286
287 WINPR_ASSERT(s);
288 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, 4))
289 {
290 RX_LOG(server, log, WLOG_WARN, "RDPDR_HEADER[%s | %s]: expected length 4, got %" PRIuz,
291 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
292 Stream_GetRemainingLength(s));
293 return FALSE;
294 }
295
296 Stream_Read_UINT16(s, rcomponent);
297 Stream_Read_UINT16(s, rpacketid);
298
299 if (rcomponent != component)
300 {
301 RX_LOG(server, log, WLOG_WARN, "RDPDR_HEADER[%s | %s]: got component %s",
302 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
303 rdpdr_component_string(rcomponent));
304 return FALSE;
305 }
306
307 if (rpacketid != PacketId)
308 {
309 RX_LOG(server, log, WLOG_WARN, "RDPDR_HEADER[%s | %s]: got PacketID %s",
310 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
311 rdpdr_packetid_string(rpacketid));
312 return FALSE;
313 }
314
315 if (!Stream_CheckAndLogRequiredLengthRx(server, log, s, expect))
316 {
317 RX_LOG(server, log, WLOG_WARN,
318 "RDPDR_HEADER[%s | %s] not enough data, expected %" PRIuz ", "
319 "got %" PRIuz,
320 rdpdr_component_string(component), rdpdr_packetid_string(PacketId), expect,
321 Stream_GetRemainingLength(s));
322 return ERROR_INVALID_DATA;
323 }
324
325 return TRUE;
326}
327
328WINPR_ATTR_NODISCARD
329static BOOL rdpdr_check_version(BOOL server, wLog* log, UINT16 versionMajor, UINT16 versionMinor,
330 UINT16 component, UINT16 PacketId)
331{
332 if (versionMajor != RDPDR_VERSION_MAJOR)
333 {
334 RX_LOG(server, log, WLOG_WARN, "[%s | %s] expected MajorVersion %d, got %" PRIu16,
335 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
336 RDPDR_VERSION_MAJOR, versionMajor);
337 return FALSE;
338 }
339 switch (versionMinor)
340 {
341 case RDPDR_VERSION_MINOR_RDP50:
342 case RDPDR_VERSION_MINOR_RDP51:
343 case RDPDR_VERSION_MINOR_RDP52:
344 case RDPDR_VERSION_MINOR_RDP6X:
345 case RDPDR_VERSION_MINOR_RDP10X:
346 break;
347 default:
348 {
349 RX_LOG(server, log, WLOG_WARN, "[%s | %s] unsupported MinorVersion %" PRIu16,
350 rdpdr_component_string(component), rdpdr_packetid_string(PacketId),
351 versionMinor);
352 return FALSE;
353 }
354 }
355 return TRUE;
356}
357
358WINPR_ATTR_NODISCARD
359static UINT rdpdr_process_server_announce_request(pf_channel_client_context* rdpdr, wStream* s)
360{
361 const UINT16 component = RDPDR_CTYP_CORE;
362 const UINT16 packetid = PAKID_CORE_SERVER_ANNOUNCE;
363 WINPR_ASSERT(rdpdr);
364 WINPR_ASSERT(s);
365
366 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, component, packetid, 8))
367 return ERROR_INVALID_DATA;
368
369 Stream_Read_UINT16(s, rdpdr->common.versionMajor);
370 Stream_Read_UINT16(s, rdpdr->common.versionMinor);
371
372 if (!rdpdr_check_version(FALSE, rdpdr->log, rdpdr->common.versionMajor,
373 rdpdr->common.versionMinor, component, packetid))
374 return ERROR_INVALID_DATA;
375
376 /* Limit maximum channel protocol version to the one set by proxy server */
377 if (rdpdr->common.versionMajor > rdpdr->maxMajorVersion)
378 {
379 rdpdr->common.versionMajor = rdpdr->maxMajorVersion;
380 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
381 }
382 else if (rdpdr->common.versionMinor > rdpdr->maxMinorVersion)
383 rdpdr->common.versionMinor = rdpdr->maxMinorVersion;
384
385 Stream_Read_UINT32(s, rdpdr->common.clientID);
386 return CHANNEL_RC_OK;
387}
388
389WINPR_ATTR_NODISCARD
390static UINT rdpdr_server_send_announce_request(pf_channel_server_context* context)
391{
392 wStream* s =
393 rdpdr_server_get_send_buffer(context, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_ANNOUNCE, 8);
394 if (!s)
395 return CHANNEL_RC_NO_MEMORY;
396
397 Stream_Write_UINT16(s, context->common.versionMajor); /* VersionMajor (2 bytes) */
398 Stream_Write_UINT16(s, context->common.versionMinor); /* VersionMinor (2 bytes) */
399 Stream_Write_UINT32(s, context->common.clientID); /* ClientId (4 bytes) */
400 return rdpdr_seal_send_free_request(context, s);
401}
402
403WINPR_ATTR_NODISCARD
404static UINT rdpdr_process_client_announce_reply(pf_channel_server_context* rdpdr, wStream* s)
405{
406 const UINT16 component = RDPDR_CTYP_CORE;
407 const UINT16 packetid = PAKID_CORE_CLIENTID_CONFIRM;
408 UINT16 versionMajor = 0;
409 UINT16 versionMinor = 0;
410 UINT32 clientID = 0;
411
412 WINPR_ASSERT(rdpdr);
413 WINPR_ASSERT(s);
414
415 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
416 return ERROR_INVALID_DATA;
417
418 Stream_Read_UINT16(s, versionMajor);
419 Stream_Read_UINT16(s, versionMinor);
420
421 if (!rdpdr_check_version(TRUE, rdpdr->log, versionMajor, versionMinor, component, packetid))
422 return ERROR_INVALID_DATA;
423
424 if ((rdpdr->common.versionMajor != versionMajor) ||
425 (rdpdr->common.versionMinor != versionMinor))
426 {
427 SERVER_RX_LOG(
428 rdpdr->log, WLOG_WARN,
429 "[%s | %s] downgrading version from %" PRIu16 ".%" PRIu16 " to %" PRIu16 ".%" PRIu16,
430 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
431 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor, versionMinor);
432 rdpdr->common.versionMajor = versionMajor;
433 rdpdr->common.versionMinor = versionMinor;
434 }
435 Stream_Read_UINT32(s, clientID);
436 if (rdpdr->common.clientID != clientID)
437 {
438 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
439 "[%s | %s] changing clientID 0x%08" PRIu32 " to 0x%08" PRIu32,
440 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
441 rdpdr->common.clientID, clientID);
442 rdpdr->common.clientID = clientID;
443 }
444
445 return CHANNEL_RC_OK;
446}
447
448WINPR_ATTR_NODISCARD
449static UINT rdpdr_send_client_announce_reply(pClientContext* pc, pf_channel_client_context* rdpdr)
450{
451 wStream* s =
452 rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
453 if (!s)
454 return CHANNEL_RC_NO_MEMORY;
455
456 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
457 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
458 Stream_Write_UINT32(s, rdpdr->common.clientID);
459 return rdpdr_client_send(rdpdr->log, pc, s);
460}
461
462WINPR_ATTR_NODISCARD
463static UINT rdpdr_process_client_name_request(pf_channel_server_context* rdpdr, wStream* s,
464 pClientContext* pc)
465{
466 UINT32 unicodeFlag = 0;
467 UINT32 codePage = 0;
468
469 WINPR_ASSERT(rdpdr);
470 WINPR_ASSERT(s);
471 WINPR_ASSERT(pc);
472
473 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
474 12))
475 return ERROR_INVALID_DATA;
476
477 Stream_Read_UINT32(s, unicodeFlag);
478 rdpdr->common.computerNameUnicode = ((unicodeFlag & 1) != 0);
479
480 Stream_Read_UINT32(s, codePage);
481 WINPR_UNUSED(codePage); /* Field is ignored */
482 Stream_Read_UINT32(s, rdpdr->common.computerNameLen);
483 if (!Stream_CheckAndLogRequiredLengthSrv(rdpdr->log, s, rdpdr->common.computerNameLen))
484 {
485 SERVER_RX_LOG(
486 rdpdr->log, WLOG_WARN, "[%s | %s]: missing data, got %" PRIuz ", expected %" PRIu32,
487 rdpdr_component_string(RDPDR_CTYP_CORE), rdpdr_packetid_string(PAKID_CORE_CLIENT_NAME),
488 Stream_GetRemainingLength(s), rdpdr->common.computerNameLen);
489 return ERROR_INVALID_DATA;
490 }
491 void* tmp = realloc(rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
492 if (!tmp)
493 return CHANNEL_RC_NO_MEMORY;
494 rdpdr->common.computerName.v = tmp;
495
496 Stream_Read(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
497
498 pc->computerNameLen = rdpdr->common.computerNameLen;
499 pc->computerNameUnicode = rdpdr->common.computerNameUnicode;
500 tmp = realloc(pc->computerName.v, pc->computerNameLen);
501 if (!tmp)
502 return CHANNEL_RC_NO_MEMORY;
503 pc->computerName.v = tmp;
504 memcpy(pc->computerName.v, rdpdr->common.computerName.v, pc->computerNameLen);
505
506 return CHANNEL_RC_OK;
507}
508
509WINPR_ATTR_NODISCARD
510static UINT rdpdr_send_client_name_request(pClientContext* pc, pf_channel_client_context* rdpdr)
511{
512 wStream* s = nullptr;
513
514 WINPR_ASSERT(rdpdr);
515 WINPR_ASSERT(pc);
516
517 {
518 void* tmp = realloc(rdpdr->common.computerName.v, pc->computerNameLen);
519 if (!tmp)
520 return CHANNEL_RC_NO_MEMORY;
521 rdpdr->common.computerName.v = tmp;
522 rdpdr->common.computerNameLen = pc->computerNameLen;
523 rdpdr->common.computerNameUnicode = pc->computerNameUnicode;
524 memcpy(rdpdr->common.computerName.v, pc->computerName.v, pc->computerNameLen);
525 }
526 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_NAME,
527 12U + rdpdr->common.computerNameLen);
528 if (!s)
529 return CHANNEL_RC_NO_MEMORY;
530
531 Stream_Write_UINT32(s, rdpdr->common.computerNameUnicode
532 ? 1
533 : 0); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
534 Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
535 Stream_Write_UINT32(s, rdpdr->common.computerNameLen);
536 Stream_Write(s, rdpdr->common.computerName.v, rdpdr->common.computerNameLen);
537 return rdpdr_client_send(rdpdr->log, pc, s);
538}
539
540#define rdpdr_ignore_capset(srv, log, s, header) \
541 rdpdr_ignore_capset_((srv), (log), (s), header, __func__)
542WINPR_ATTR_NODISCARD
543static UINT rdpdr_ignore_capset_(WINPR_ATTR_UNUSED BOOL srv, WINPR_ATTR_UNUSED wLog* log,
544 wStream* s, const RDPDR_CAPABILITY_HEADER* header,
545 WINPR_ATTR_UNUSED const char* fkt)
546{
547 WINPR_ASSERT(s);
548 WINPR_ASSERT(header);
549
550 Stream_Seek(s, header->CapabilityLength);
551 return CHANNEL_RC_OK;
552}
553
554WINPR_ATTR_NODISCARD
555static UINT rdpdr_client_process_general_capset(pf_channel_client_context* rdpdr, wStream* s,
556 const RDPDR_CAPABILITY_HEADER* header)
557{
558 WINPR_UNUSED(rdpdr);
559 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
560}
561
562WINPR_ATTR_NODISCARD
563static UINT rdpdr_process_printer_capset(pf_channel_client_context* rdpdr, wStream* s,
564 const RDPDR_CAPABILITY_HEADER* header)
565{
566 WINPR_UNUSED(rdpdr);
567 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
568}
569
570WINPR_ATTR_NODISCARD
571static UINT rdpdr_process_port_capset(pf_channel_client_context* rdpdr, wStream* s,
572 const RDPDR_CAPABILITY_HEADER* header)
573{
574 WINPR_UNUSED(rdpdr);
575 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
576}
577
578WINPR_ATTR_NODISCARD
579static UINT rdpdr_process_drive_capset(pf_channel_client_context* rdpdr, wStream* s,
580 const RDPDR_CAPABILITY_HEADER* header)
581{
582 WINPR_UNUSED(rdpdr);
583 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
584}
585
586WINPR_ATTR_NODISCARD
587static UINT rdpdr_process_smartcard_capset(pf_channel_client_context* rdpdr, wStream* s,
588 const RDPDR_CAPABILITY_HEADER* header)
589{
590 WINPR_UNUSED(rdpdr);
591 return rdpdr_ignore_capset(FALSE, rdpdr->log, s, header);
592}
593
594WINPR_ATTR_NODISCARD
595static UINT rdpdr_process_server_core_capability_request(pf_channel_client_context* rdpdr,
596 wStream* s)
597{
598 UINT status = CHANNEL_RC_OK;
599 UINT16 numCapabilities = 0;
600
601 WINPR_ASSERT(rdpdr);
602
603 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
604 PAKID_CORE_SERVER_CAPABILITY, 4))
605 return ERROR_INVALID_DATA;
606
607 Stream_Read_UINT16(s, numCapabilities);
608 Stream_Seek(s, 2); /* pad (2 bytes) */
609
610 for (UINT16 i = 0; i < numCapabilities; i++)
611 {
612 RDPDR_CAPABILITY_HEADER header = WINPR_C_ARRAY_INIT;
613 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
614 if (error != CHANNEL_RC_OK)
615 return error;
616
617 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
618 {
619 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
620 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
621
622 WLog_Print(rdpdr->log, WLOG_TRACE,
623 "capability %s got version %" PRIu32 ", will use version %" PRIu32,
624 rdpdr_cap_type_string(header.CapabilityType), header.Version,
625 rdpdr->common.capabilityVersions[header.CapabilityType]);
626 }
627
628 switch (header.CapabilityType)
629 {
630 case CAP_GENERAL_TYPE:
631 status = rdpdr_client_process_general_capset(rdpdr, s, &header);
632 break;
633
634 case CAP_PRINTER_TYPE:
635 status = rdpdr_process_printer_capset(rdpdr, s, &header);
636 break;
637
638 case CAP_PORT_TYPE:
639 status = rdpdr_process_port_capset(rdpdr, s, &header);
640 break;
641
642 case CAP_DRIVE_TYPE:
643 status = rdpdr_process_drive_capset(rdpdr, s, &header);
644 break;
645
646 case CAP_SMARTCARD_TYPE:
647 status = rdpdr_process_smartcard_capset(rdpdr, s, &header);
648 break;
649
650 default:
651 WLog_Print(rdpdr->log, WLOG_WARN,
652 "unknown capability 0x%04" PRIx16 ", length %" PRIu16
653 ", version %" PRIu32,
654 header.CapabilityType, header.CapabilityLength, header.Version);
655 Stream_Seek(s, header.CapabilityLength);
656 break;
657 }
658
659 if (status != CHANNEL_RC_OK)
660 return status;
661 }
662
663 return CHANNEL_RC_OK;
664}
665
666WINPR_ATTR_NODISCARD
667static BOOL rdpdr_write_general_capset(wLog* log, pf_channel_common_context* rdpdr, wStream* s)
668{
669 WINPR_ASSERT(rdpdr);
670 WINPR_ASSERT(s);
671
672 const RDPDR_CAPABILITY_HEADER header = { CAP_GENERAL_TYPE, 44,
673 rdpdr->capabilityVersions[CAP_GENERAL_TYPE] };
674 if (rdpdr_write_capset_header(log, s, &header) != CHANNEL_RC_OK)
675 return FALSE;
676 Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */
677 Stream_Write_UINT32(s, 0); /* osVersion, should be ignored */
678 Stream_Write_UINT16(s, rdpdr->versionMajor); /* protocolMajorVersion, must be set to 1 */
679 Stream_Write_UINT16(s, rdpdr->versionMinor); /* protocolMinorVersion */
680 Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */
681 Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */
682 Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU |
683 RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
684 Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */
685 Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */
686 Stream_Write_UINT32(s, rdpdr->SpecialDeviceCount); /* SpecialTypeDeviceCap, number of special
687 devices to be redirected before logon */
688 return TRUE;
689}
690
691WINPR_ATTR_NODISCARD
692static BOOL rdpdr_write_printer_capset(wLog* log, pf_channel_common_context* rdpdr, wStream* s)
693{
694 WINPR_ASSERT(rdpdr);
695 WINPR_ASSERT(s);
696
697 const RDPDR_CAPABILITY_HEADER header = { CAP_PRINTER_TYPE, 8,
698 rdpdr->capabilityVersions[CAP_PRINTER_TYPE] };
699 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
700}
701
702WINPR_ATTR_NODISCARD
703static BOOL rdpdr_write_port_capset(wLog* log, pf_channel_common_context* rdpdr, wStream* s)
704{
705 WINPR_ASSERT(rdpdr);
706 WINPR_ASSERT(s);
707
708 const RDPDR_CAPABILITY_HEADER header = { CAP_PORT_TYPE, 8,
709 rdpdr->capabilityVersions[CAP_PORT_TYPE] };
710 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
711}
712
713WINPR_ATTR_NODISCARD
714static BOOL rdpdr_write_drive_capset(wLog* log, pf_channel_common_context* rdpdr, wStream* s)
715{
716 WINPR_ASSERT(rdpdr);
717 WINPR_ASSERT(s);
718
719 const RDPDR_CAPABILITY_HEADER header = { CAP_DRIVE_TYPE, 8,
720 rdpdr->capabilityVersions[CAP_DRIVE_TYPE] };
721 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
722}
723
724WINPR_ATTR_NODISCARD
725static BOOL rdpdr_write_smartcard_capset(wLog* log, pf_channel_common_context* rdpdr, wStream* s)
726{
727 WINPR_ASSERT(rdpdr);
728 WINPR_ASSERT(s);
729
730 const RDPDR_CAPABILITY_HEADER header = { CAP_SMARTCARD_TYPE, 8,
731 rdpdr->capabilityVersions[CAP_SMARTCARD_TYPE] };
732 return (rdpdr_write_capset_header(log, s, &header) == CHANNEL_RC_OK);
733}
734
735WINPR_ATTR_NODISCARD
736static UINT rdpdr_send_server_capability_request(pf_channel_server_context* rdpdr)
737{
738 wStream* s =
739 rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_SERVER_CAPABILITY, 8);
740 if (!s)
741 return CHANNEL_RC_NO_MEMORY;
742 Stream_Write_UINT16(s, 5); /* numCapabilities */
743 Stream_Write_UINT16(s, 0); /* pad */
744 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
745 return CHANNEL_RC_NO_MEMORY;
746 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
747 return CHANNEL_RC_NO_MEMORY;
748 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
749 return CHANNEL_RC_NO_MEMORY;
750 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
751 return CHANNEL_RC_NO_MEMORY;
752 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
753 return CHANNEL_RC_NO_MEMORY;
754 return rdpdr_seal_send_free_request(rdpdr, s);
755}
756
757WINPR_ATTR_NODISCARD
758static UINT rdpdr_process_client_capability_response(pf_channel_server_context* rdpdr, wStream* s)
759{
760 const UINT16 component = RDPDR_CTYP_CORE;
761 const UINT16 packetid = PAKID_CORE_CLIENT_CAPABILITY;
762 UINT status = CHANNEL_RC_OK;
763 UINT16 numCapabilities = 0;
764 WINPR_ASSERT(rdpdr);
765
766 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 4))
767 return ERROR_INVALID_DATA;
768
769 Stream_Read_UINT16(s, numCapabilities);
770 Stream_Seek_UINT16(s); /* padding */
771
772 for (UINT16 x = 0; x < numCapabilities; x++)
773 {
774 RDPDR_CAPABILITY_HEADER header = WINPR_C_ARRAY_INIT;
775 UINT error = rdpdr_read_capset_header(rdpdr->log, s, &header);
776 if (error != CHANNEL_RC_OK)
777 return error;
778 if (header.CapabilityType < ARRAYSIZE(rdpdr->common.capabilityVersions))
779 {
780 if (rdpdr->common.capabilityVersions[header.CapabilityType] > header.Version)
781 rdpdr->common.capabilityVersions[header.CapabilityType] = header.Version;
782
783 WLog_Print(rdpdr->log, WLOG_TRACE,
784 "capability %s got version %" PRIu32 ", will use version %" PRIu32,
785 rdpdr_cap_type_string(header.CapabilityType), header.Version,
786 rdpdr->common.capabilityVersions[header.CapabilityType]);
787 }
788
789 switch (header.CapabilityType)
790 {
791 case CAP_GENERAL_TYPE:
792 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
793 break;
794
795 case CAP_PRINTER_TYPE:
796 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
797 break;
798
799 case CAP_PORT_TYPE:
800 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
801 break;
802
803 case CAP_DRIVE_TYPE:
804 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
805 break;
806
807 case CAP_SMARTCARD_TYPE:
808 status = rdpdr_ignore_capset(TRUE, rdpdr->log, s, &header);
809 break;
810
811 default:
812 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
813 "[%s | %s] invalid capability type 0x%04" PRIx16,
814 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
815 header.CapabilityType);
816 status = ERROR_INVALID_DATA;
817 break;
818 }
819
820 if (status != CHANNEL_RC_OK)
821 break;
822 }
823
824 return status;
825}
826
827WINPR_ATTR_NODISCARD
828static UINT rdpdr_send_client_capability_response(pClientContext* pc,
829 pf_channel_client_context* rdpdr)
830{
831 wStream* s = nullptr;
832
833 WINPR_ASSERT(rdpdr);
834 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENT_CAPABILITY, 4);
835 if (!s)
836 return CHANNEL_RC_NO_MEMORY;
837
838 Stream_Write_UINT16(s, 5); /* numCapabilities */
839 Stream_Write_UINT16(s, 0); /* pad */
840 if (!rdpdr_write_general_capset(rdpdr->log, &rdpdr->common, s))
841 return CHANNEL_RC_NO_MEMORY;
842 if (!rdpdr_write_printer_capset(rdpdr->log, &rdpdr->common, s))
843 return CHANNEL_RC_NO_MEMORY;
844 if (!rdpdr_write_port_capset(rdpdr->log, &rdpdr->common, s))
845 return CHANNEL_RC_NO_MEMORY;
846 if (!rdpdr_write_drive_capset(rdpdr->log, &rdpdr->common, s))
847 return CHANNEL_RC_NO_MEMORY;
848 if (!rdpdr_write_smartcard_capset(rdpdr->log, &rdpdr->common, s))
849 return CHANNEL_RC_NO_MEMORY;
850 return rdpdr_client_send(rdpdr->log, pc, s);
851}
852
853WINPR_ATTR_NODISCARD
854static UINT rdpdr_send_server_clientid_confirm(pf_channel_server_context* rdpdr)
855{
856 wStream* s = nullptr;
857
858 s = rdpdr_server_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_CLIENTID_CONFIRM, 8);
859 if (!s)
860 return CHANNEL_RC_NO_MEMORY;
861 Stream_Write_UINT16(s, rdpdr->common.versionMajor);
862 Stream_Write_UINT16(s, rdpdr->common.versionMinor);
863 Stream_Write_UINT32(s, rdpdr->common.clientID);
864 return rdpdr_seal_send_free_request(rdpdr, s);
865}
866
867WINPR_ATTR_NODISCARD
868static UINT rdpdr_process_server_clientid_confirm(pf_channel_client_context* rdpdr, wStream* s)
869{
870 UINT16 versionMajor = 0;
871 UINT16 versionMinor = 0;
872 UINT32 clientID = 0;
873
874 WINPR_ASSERT(rdpdr);
875 WINPR_ASSERT(s);
876
877 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
878 PAKID_CORE_CLIENTID_CONFIRM, 8))
879 return ERROR_INVALID_DATA;
880
881 Stream_Read_UINT16(s, versionMajor);
882 Stream_Read_UINT16(s, versionMinor);
883 if (!rdpdr_check_version(FALSE, rdpdr->log, versionMajor, versionMinor, RDPDR_CTYP_CORE,
884 PAKID_CORE_CLIENTID_CONFIRM))
885 return ERROR_INVALID_DATA;
886
887 Stream_Read_UINT32(s, clientID);
888
889 if ((versionMajor != rdpdr->common.versionMajor) ||
890 (versionMinor != rdpdr->common.versionMinor))
891 {
892 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
893 "[%s | %s] Version mismatch, sent %" PRIu16 ".%" PRIu16
894 ", downgraded to %" PRIu16 ".%" PRIu16,
895 rdpdr_component_string(RDPDR_CTYP_CORE),
896 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM),
897 rdpdr->common.versionMajor, rdpdr->common.versionMinor, versionMajor,
898 versionMinor);
899 rdpdr->common.versionMajor = versionMajor;
900 rdpdr->common.versionMinor = versionMinor;
901 }
902
903 if (clientID != rdpdr->common.clientID)
904 {
905 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
906 "[%s | %s] clientID mismatch, sent 0x%08" PRIx32 ", changed to 0x%08" PRIx32,
907 rdpdr_component_string(RDPDR_CTYP_CORE),
908 rdpdr_packetid_string(PAKID_CORE_CLIENTID_CONFIRM), rdpdr->common.clientID,
909 clientID);
910 rdpdr->common.clientID = clientID;
911 }
912
913 return CHANNEL_RC_OK;
914}
915
916WINPR_ATTR_NODISCARD
917static BOOL
918rdpdr_process_server_capability_request_or_clientid_confirm(pf_channel_client_context* rdpdr,
919 wStream* s)
920{
921 const UINT32 mask = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM |
922 STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
923 const UINT16 rcomponent = RDPDR_CTYP_CORE;
924 UINT16 component = 0;
925 UINT16 packetid = 0;
926
927 WINPR_ASSERT(rdpdr);
928 WINPR_ASSERT(s);
929
930 if ((rdpdr->flags & mask) == mask)
931 {
932 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN, "already past this state, abort!");
933 return FALSE;
934 }
935
936 if (!Stream_CheckAndLogRequiredLengthClient(rdpdr->log, s, 4))
937 return FALSE;
938
939 Stream_Read_UINT16(s, component);
940 if (rcomponent != component)
941 {
942 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN, "got component %s, expected %s",
943 rdpdr_component_string(component), rdpdr_component_string(rcomponent));
944 return FALSE;
945 }
946 Stream_Read_UINT16(s, packetid);
947 Stream_Rewind(s, 4);
948
949 switch (packetid)
950 {
951 case PAKID_CORE_SERVER_CAPABILITY:
952 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST)
953 {
954 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN, "got duplicate packetid %s",
955 rdpdr_packetid_string(packetid));
956 return FALSE;
957 }
958 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
959 return rdpdr_process_server_core_capability_request(rdpdr, s) == CHANNEL_RC_OK;
960 case PAKID_CORE_CLIENTID_CONFIRM:
961 default:
962 if (rdpdr->flags & STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM)
963 {
964 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN, "got duplicate packetid %s",
965 rdpdr_packetid_string(packetid));
966 return FALSE;
967 }
968 rdpdr->flags |= STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
969 return rdpdr_process_server_clientid_confirm(rdpdr, s) == CHANNEL_RC_OK;
970 }
971}
972
973#if defined(WITH_PROXY_EMULATE_SMARTCARD)
974WINPR_ATTR_NODISCARD
975static UINT rdpdr_send_emulated_scard_device_list_announce_request(pClientContext* pc,
976 pf_channel_client_context* rdpdr)
977{
978 wStream* s = nullptr;
979
980 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_ANNOUNCE, 24);
981 if (!s)
982 return CHANNEL_RC_NO_MEMORY;
983
984 Stream_Write_UINT32(s, 1); /* deviceCount -> our emulated smartcard only */
985 Stream_Write_UINT32(s, RDPDR_DTYP_SMARTCARD); /* deviceType */
986 Stream_Write_UINT32(
987 s, SCARD_DEVICE_ID); /* deviceID -> reserve highest value for the emulated smartcard */
988 Stream_Write(s, "SCARD\0\0\0", 8);
989 Stream_Write_UINT32(s, 6);
990 Stream_Write(s, "SCARD\0", 6);
991
992 return rdpdr_client_send(rdpdr->log, pc, s);
993}
994
995WINPR_ATTR_NODISCARD
996static UINT rdpdr_send_emulated_scard_device_remove(pClientContext* pc,
997 pf_channel_client_context* rdpdr)
998{
999 wStream* s = nullptr;
1000
1001 s = rdpdr_client_get_send_buffer(rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICELIST_REMOVE, 24);
1002 if (!s)
1003 return CHANNEL_RC_NO_MEMORY;
1004
1005 Stream_Write_UINT32(s, 1); /* deviceCount -> our emulated smartcard only */
1006 Stream_Write_UINT32(
1007 s, SCARD_DEVICE_ID); /* deviceID -> reserve highest value for the emulated smartcard */
1008
1009 return rdpdr_client_send(rdpdr->log, pc, s);
1010}
1011
1012WINPR_ATTR_NODISCARD
1013static UINT rdpdr_process_server_device_announce_response(pf_channel_client_context* rdpdr,
1014 wStream* s)
1015{
1016 const UINT16 component = RDPDR_CTYP_CORE;
1017 const UINT16 packetid = PAKID_CORE_DEVICE_REPLY;
1018 UINT32 deviceID = 0;
1019 UINT32 resultCode = 0;
1020
1021 WINPR_ASSERT(rdpdr);
1022 WINPR_ASSERT(s);
1023
1024 if (!rdpdr_process_server_header(TRUE, rdpdr->log, s, component, packetid, 8))
1025 return ERROR_INVALID_DATA;
1026
1027 Stream_Read_UINT32(s, deviceID);
1028 Stream_Read_UINT32(s, resultCode);
1029
1030 if (deviceID != SCARD_DEVICE_ID)
1031 {
1032 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1033 "[%s | %s] deviceID mismatch, sent 0x%08" PRIx32 ", changed to 0x%08" PRIx32,
1034 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1035 SCARD_DEVICE_ID, deviceID);
1036 }
1037 else if (resultCode != 0)
1038 {
1039 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1040 "[%s | %s] deviceID 0x%08" PRIx32 " resultCode=0x%08" PRIx32,
1041 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1042 resultCode);
1043 }
1044 else
1045 CLIENT_RX_LOG(rdpdr->log, WLOG_DEBUG,
1046 "[%s | %s] deviceID 0x%08" PRIx32 " resultCode=0x%08" PRIx32
1047 " -> emulated smartcard redirected!",
1048 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID,
1049 resultCode);
1050
1051 return CHANNEL_RC_OK;
1052}
1053#endif
1054
1055WINPR_ATTR_NODISCARD
1056static BOOL pf_channel_rdpdr_rewrite_device_list_to(wStream* s, UINT32 fromVersion,
1057 UINT32 toVersion)
1058{
1059 BOOL rc = FALSE;
1060 if (fromVersion == toVersion)
1061 return TRUE;
1062
1063 const size_t cap = Stream_GetRemainingLength(s);
1064 wStream* clone = Stream_New(nullptr, cap);
1065 if (!clone)
1066 goto fail;
1067
1068 {
1069 const size_t pos = Stream_GetPosition(s);
1070 Stream_Copy(s, clone, cap);
1071 Stream_SealLength(clone);
1072
1073 Stream_ResetPosition(clone);
1074 if (!Stream_SetPosition(s, pos))
1075 goto fail;
1076 }
1077
1078 /* Skip device count */
1079 if (!Stream_SafeSeek(s, 4))
1080 goto fail;
1081
1082 {
1083 UINT32 count = 0;
1084 if (Stream_GetRemainingLength(clone) < 4)
1085 goto fail;
1086 Stream_Read_UINT32(clone, count);
1087
1088 for (UINT32 x = 0; x < count; x++)
1089 {
1090 RdpdrDevice device = WINPR_C_ARRAY_INIT;
1091 const size_t charCount = ARRAYSIZE(device.PreferredDosName);
1092 if (Stream_GetRemainingLength(clone) < 20)
1093 goto fail;
1094
1095 Stream_Read_UINT32(clone, device.DeviceType); /* DeviceType (4 bytes) */
1096 Stream_Read_UINT32(clone, device.DeviceId); /* DeviceId (4 bytes) */
1097 Stream_Read(clone, device.PreferredDosName, charCount); /* PreferredDosName (8 bytes) */
1098 Stream_Read_UINT32(clone, device.DeviceDataLength); /* DeviceDataLength (4 bytes) */
1099 device.DeviceData = Stream_Pointer(clone);
1100 if (!Stream_SafeSeek(clone, device.DeviceDataLength))
1101 goto fail;
1102
1103 if (!Stream_EnsureRemainingCapacity(s, 20))
1104 goto fail;
1105 Stream_Write_UINT32(s, device.DeviceType);
1106 Stream_Write_UINT32(s, device.DeviceId);
1107 Stream_Write(s, device.PreferredDosName, charCount);
1108
1109 if (device.DeviceType == RDPDR_DTYP_FILESYSTEM)
1110 {
1111 if (toVersion == DRIVE_CAPABILITY_VERSION_01)
1112 Stream_Write_UINT32(s, 0); /* No unicode name */
1113 else
1114 {
1115 const size_t datalen = charCount * sizeof(WCHAR);
1116 if (!Stream_EnsureRemainingCapacity(s, datalen + sizeof(UINT32)))
1117 goto fail;
1118 Stream_Write_UINT32(s, WINPR_ASSERTING_INT_CAST(uint32_t, datalen));
1119
1120 const SSIZE_T rcw = Stream_Write_UTF16_String_From_UTF8(
1121 s, charCount, device.PreferredDosName, charCount - 1, TRUE);
1122 if (rcw < 0)
1123 goto fail;
1124 }
1125 }
1126 else
1127 {
1128 Stream_Write_UINT32(s, device.DeviceDataLength);
1129 if (!Stream_EnsureRemainingCapacity(s, device.DeviceDataLength))
1130 goto fail;
1131 Stream_Write(s, device.DeviceData, device.DeviceDataLength);
1132 }
1133 }
1134 }
1135
1136 Stream_SealLength(s);
1137 rc = TRUE;
1138
1139fail:
1140 Stream_Free(clone, TRUE);
1141 return rc;
1142}
1143
1144WINPR_ATTR_NODISCARD
1145static BOOL pf_channel_rdpdr_rewrite_device_list(pf_channel_client_context* rdpdr,
1146 pServerContext* ps, wStream* s, BOOL toServer)
1147{
1148 WINPR_ASSERT(rdpdr);
1149 WINPR_ASSERT(ps);
1150
1151 const size_t pos = Stream_GetPosition(s);
1152 UINT16 component = 0;
1153 UINT16 packetid = 0;
1154 Stream_ResetPosition(s);
1155
1156 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1157 return FALSE;
1158
1159 Stream_Read_UINT16(s, component);
1160 Stream_Read_UINT16(s, packetid);
1161 if ((component != RDPDR_CTYP_CORE) || (packetid != PAKID_CORE_DEVICELIST_ANNOUNCE))
1162 return Stream_SetPosition(s, pos);
1163
1164 const pf_channel_server_context* srv =
1165 HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1166 if (!srv)
1167 {
1168 WLog_Print(rdpdr->log, WLOG_ERROR, "No channel %s in intercep map", RDPDR_SVC_CHANNEL_NAME);
1169 return FALSE;
1170 }
1171
1172 UINT32 from = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1173 UINT32 to = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1174 if (toServer)
1175 {
1176 from = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1177 to = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1178 }
1179 if (!pf_channel_rdpdr_rewrite_device_list_to(s, from, to))
1180 return FALSE;
1181
1182 return Stream_SetPosition(s, pos);
1183}
1184
1185WINPR_ATTR_NODISCARD
1186static BOOL pf_channel_rdpdr_client_send_to_server(pf_channel_client_context* rdpdr,
1187 pServerContext* ps, wStream* s)
1188{
1189 WINPR_ASSERT(rdpdr);
1190 if (ps)
1191 {
1192 UINT16 server_channel_id = WTSChannelGetId(ps->context.peer, RDPDR_SVC_CHANNEL_NAME);
1193
1194 /* Ignore messages for channels that can not be mapped.
1195 * The client might not have enabled support for this specific channel,
1196 * so just drop the message. */
1197 if (server_channel_id == 0)
1198 return TRUE;
1199
1200 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, TRUE))
1201 return FALSE;
1202 size_t len = Stream_Length(s);
1203 if (!Stream_SetPosition(s, len))
1204 return ERROR_INVALID_DATA;
1205 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_tx);
1206 WINPR_ASSERT(ps->context.peer);
1207 WINPR_ASSERT(ps->context.peer->SendChannelData);
1208 return ps->context.peer->SendChannelData(ps->context.peer, server_channel_id,
1209 Stream_Buffer(s), len);
1210 }
1211 return TRUE;
1212}
1213
1214WINPR_ATTR_NODISCARD
1215static BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr);
1216
1217#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1218WINPR_ATTR_NODISCARD
1219static BOOL rdpdr_process_server_loggedon_request(pServerContext* ps, pClientContext* pc,
1220 pf_channel_client_context* rdpdr, wStream* s,
1221 UINT16 component, UINT16 packetid)
1222{
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)
1227 return FALSE;
1228 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) != CHANNEL_RC_OK)
1229 return FALSE;
1230 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1231}
1232
1233WINPR_ATTR_NODISCARD
1234static BOOL filter_smartcard_io_requests(pf_channel_client_context* rdpdr, wStream* s,
1235 UINT16* pPacketid)
1236{
1237 BOOL rc = FALSE;
1238 UINT16 component = 0;
1239 UINT16 packetid = 0;
1240 UINT32 deviceID = 0;
1241 size_t pos = 0;
1242
1243 WINPR_ASSERT(rdpdr);
1244 WINPR_ASSERT(pPacketid);
1245
1246 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1247 return FALSE;
1248
1249 pos = Stream_GetPosition(s);
1250 Stream_Read_UINT16(s, component);
1251 Stream_Read_UINT16(s, packetid);
1252
1253 if (Stream_GetRemainingLength(s) >= 4)
1254 Stream_Read_UINT32(s, deviceID);
1255
1256 WLog_Print(rdpdr->log, WLOG_DEBUG, "got: [%s | %s]: [0x%08" PRIx32 "]",
1257 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID);
1258
1259 if (component != RDPDR_CTYP_CORE)
1260 goto fail;
1261
1262 switch (packetid)
1263 {
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;
1274 break;
1275 case PAKID_CORE_USER_LOGGEDON:
1276 *pPacketid = packetid;
1277 break;
1278 case PAKID_CORE_DEVICE_REPLY:
1279 case PAKID_CORE_DEVICE_IOREQUEST:
1280 if (deviceID != SCARD_DEVICE_ID)
1281 goto fail;
1282 *pPacketid = packetid;
1283 break;
1284 default:
1285 if (deviceID != SCARD_DEVICE_ID)
1286 goto fail;
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),
1290 deviceID);
1291 goto fail;
1292 }
1293
1294 rc = TRUE;
1295
1296fail:
1297 if (!Stream_SetPosition(s, pos))
1298 return FALSE;
1299 return rc;
1300}
1301#endif
1302
1303BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr)
1304{
1305 WINPR_ASSERT(pc);
1306 WINPR_ASSERT(rdpdr);
1307
1308 if (rdpdr->state != STATE_CLIENT_CHANNEL_RUNNING)
1309 {
1310 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN, "Client RDPDR channel not ready, dropping packet!");
1311 return TRUE;
1312 }
1313
1314 const UINT16 channelId =
1315 freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
1316 if ((channelId == 0) || (channelId == UINT16_MAX))
1317 {
1318 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
1319 "Client RDPDR channel not available, dropping packet!");
1320 return TRUE;
1321 }
1322
1323 Queue_Lock(rdpdr->queue);
1324 while (Queue_Count(rdpdr->queue) > 0)
1325 {
1326 wStream* s = Queue_Dequeue(rdpdr->queue);
1327 if (!s)
1328 continue;
1329
1330 size_t len = Stream_Length(s);
1331 if (!Stream_SetPosition(s, len))
1332 {
1333 Stream_Free(s, TRUE);
1334 continue;
1335 }
1336
1337 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_tx " (queue) ");
1338 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
1339 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
1340 Stream_Buffer(s), len))
1341 {
1342 CLIENT_TX_LOG(rdpdr->log, WLOG_ERROR, "xxxxxx TODO: Failed to send data!");
1343 }
1344 Stream_Free(s, TRUE);
1345 }
1346 Queue_Unlock(rdpdr->queue);
1347 return TRUE;
1348}
1349
1350WINPR_ATTR_NODISCARD
1351static BOOL rdpdr_handle_server_announce_request(pClientContext* pc,
1352 pf_channel_client_context* rdpdr, wStream* s)
1353{
1354 WINPR_ASSERT(pc);
1355 WINPR_ASSERT(rdpdr);
1356 WINPR_ASSERT(s);
1357
1358 if (rdpdr_process_server_announce_request(rdpdr, s) != CHANNEL_RC_OK)
1359 return FALSE;
1360 if (rdpdr_send_client_announce_reply(pc, rdpdr) != CHANNEL_RC_OK)
1361 return FALSE;
1362 if (rdpdr_send_client_name_request(pc, rdpdr) != CHANNEL_RC_OK)
1363 return FALSE;
1364 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1365 return TRUE;
1366}
1367
1368BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId, const char* channel_name,
1369 const BYTE* xdata, size_t xsize, UINT32 flags, size_t totalSize)
1370{
1371#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1372 UINT16 packetid = 0;
1373#endif
1374
1375 WINPR_ASSERT(pc);
1376 WINPR_ASSERT(pc->pdata);
1377 WINPR_ASSERT(pc->interceptContextMap);
1378 WINPR_ASSERT(channel_name);
1379 WINPR_ASSERT(xdata);
1380
1381 pServerContext* ps = proxy_data_get_server_context(pc->pdata);
1382
1383 pf_channel_client_context* rdpdr =
1384 HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1385 if (!rdpdr)
1386 {
1387 CLIENT_RX_LOG(WLog_Get(RTAG), WLOG_ERROR,
1388 "Channel %s [0x%04" PRIx16 "] missing context in interceptContextMap",
1389 channel_name, channelId);
1390 return FALSE;
1391 }
1392
1393 wStream* s = rdpdr->common.buffer;
1394 if (flags & CHANNEL_FLAG_FIRST)
1395 Stream_ResetPosition(s);
1396 if (!Stream_EnsureRemainingCapacity(s, xsize))
1397 {
1398 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1399 "Channel %s [0x%04" PRIx16 "] not enough memory [need %" PRIuz "]",
1400 channel_name, channelId, xsize);
1401 return FALSE;
1402 }
1403 Stream_Write(s, xdata, xsize);
1404 if ((flags & CHANNEL_FLAG_LAST) == 0)
1405 return TRUE;
1406
1407 Stream_SealLength(s);
1408 Stream_ResetPosition(s);
1409 if (Stream_Length(s) != totalSize)
1410 {
1411 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1412 "Received invalid %s channel data (server -> proxy), expected %" PRIuz
1413 "bytes, got %" PRIuz,
1414 channel_name, totalSize, Stream_Length(s));
1415 return FALSE;
1416 }
1417
1418 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_rx);
1419 switch (rdpdr->state)
1420 {
1421 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
1422 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1423 return FALSE;
1424 break;
1425 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
1426 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1427 return FALSE;
1428 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
1429 break;
1430 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
1431 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1432 return FALSE;
1433 if (rdpdr_send_client_capability_response(pc, rdpdr) != CHANNEL_RC_OK)
1434 return FALSE;
1435#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1436 if (pf_channel_smartcard_client_emulate(pc))
1437 {
1438 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) !=
1439 CHANNEL_RC_OK)
1440 return FALSE;
1441 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1442 }
1443 else
1444#endif
1445 {
1446 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1447 if (!pf_channel_send_client_queue(pc, rdpdr))
1448 return FALSE;
1449 }
1450
1451 break;
1452 case STATE_CLIENT_CHANNEL_RUNNING:
1453#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1454 if (!pf_channel_smartcard_client_emulate(pc) ||
1455 !filter_smartcard_io_requests(rdpdr, s, &packetid))
1456 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1457 else
1458 {
1459 switch (packetid)
1460 {
1461 case PAKID_CORE_USER_LOGGEDON:
1462 return rdpdr_process_server_loggedon_request(ps, pc, rdpdr, s,
1463 RDPDR_CTYP_CORE, packetid);
1464 case PAKID_CORE_DEVICE_IOREQUEST:
1465 {
1466 wStream* out = rdpdr_client_get_send_buffer(
1467 rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOCOMPLETION, 0);
1468 WINPR_ASSERT(out);
1469
1470 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
1471 PAKID_CORE_DEVICE_IOREQUEST, 20))
1472 return FALSE;
1473
1474 if (!pf_channel_smartcard_client_handle(rdpdr->log, pc, s, out,
1475 rdpdr_client_send))
1476 return FALSE;
1477 }
1478 break;
1479 case PAKID_CORE_SERVER_ANNOUNCE:
1480 pf_channel_rdpdr_client_reset(pc);
1481 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1482 return FALSE;
1483 break;
1484 case PAKID_CORE_SERVER_CAPABILITY:
1485 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1486 rdpdr->flags = 0;
1487 return pf_channel_rdpdr_client_handle(pc, channelId, channel_name, xdata,
1488 xsize, flags, totalSize);
1489 case PAKID_CORE_DEVICE_REPLY:
1490 break;
1491 default:
1492 CLIENT_RX_LOG(
1493 rdpdr->log, WLOG_ERROR,
1494 "Channel %s [0x%04" PRIx16
1495 "] we´ve reached an impossible state %s! [%s] aliens invaded!",
1496 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state),
1497 rdpdr_packetid_string(packetid));
1498 return FALSE;
1499 }
1500 }
1501 break;
1502#else
1503 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1504#endif
1505 default:
1506 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1507 "Channel %s [0x%04" PRIx16
1508 "] we´ve reached an impossible state %s! aliens invaded!",
1509 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state));
1510 return FALSE;
1511 }
1512
1513 return TRUE;
1514}
1515
1516static void pf_channel_rdpdr_common_context_free(pf_channel_common_context* common)
1517{
1518 if (!common)
1519 return;
1520 free(common->computerName.v);
1521 Stream_Free(common->s, TRUE);
1522 Stream_Free(common->buffer, TRUE);
1523}
1524
1525static void pf_channel_rdpdr_client_context_free(InterceptContextMapEntry* base)
1526{
1527 pf_channel_client_context* entry = (pf_channel_client_context*)base;
1528 if (!entry)
1529 return;
1530
1531 pf_channel_rdpdr_common_context_free(&entry->common);
1532 Queue_Free(entry->queue);
1533 WLog_Discard(entry->log);
1534 free(entry);
1535}
1536
1537WINPR_ATTR_NODISCARD
1538static BOOL pf_channel_rdpdr_common_context_new(pf_channel_common_context* common,
1539 void (*fkt)(InterceptContextMapEntry*))
1540{
1541 if (!common)
1542 return FALSE;
1543 common->base.free = fkt;
1544 common->s = Stream_New(nullptr, 1024);
1545 if (!common->s)
1546 return FALSE;
1547 common->buffer = Stream_New(nullptr, 1024);
1548 if (!common->buffer)
1549 return FALSE;
1550 common->computerNameUnicode = 1;
1551 common->computerName.v = nullptr;
1552 common->versionMajor = RDPDR_VERSION_MAJOR;
1553 common->versionMinor = RDPDR_VERSION_MINOR_RDP10X;
1554 common->clientID = SCARD_DEVICE_ID;
1555
1556 const UINT32 versions[] = { 0,
1557 GENERAL_CAPABILITY_VERSION_02,
1558 PRINT_CAPABILITY_VERSION_01,
1559 PORT_CAPABILITY_VERSION_01,
1560 DRIVE_CAPABILITY_VERSION_02,
1561 SMARTCARD_CAPABILITY_VERSION_01 };
1562
1563 memcpy(common->capabilityVersions, versions, sizeof(common->capabilityVersions));
1564 return TRUE;
1565}
1566
1567WINPR_ATTR_NODISCARD
1568static BOOL pf_channel_rdpdr_client_pass_message(pServerContext* ps, pClientContext* pc,
1569 WINPR_ATTR_UNUSED UINT16 channelId,
1570 const char* channel_name, wStream* s)
1571{
1572 pf_channel_client_context* rdpdr = nullptr;
1573
1574 WINPR_ASSERT(ps);
1575 WINPR_ASSERT(pc);
1576
1577 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1578 if (!rdpdr)
1579 return TRUE; /* Ignore data for channels not available on proxy -> server connection */
1580 WINPR_ASSERT(rdpdr->queue);
1581
1582 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, FALSE))
1583 return FALSE;
1584 if (!Queue_Enqueue(rdpdr->queue, s))
1585 return FALSE;
1586 return pf_channel_send_client_queue(pc, rdpdr);
1587}
1588
1589#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1590WINPR_ATTR_NODISCARD
1591static BOOL filter_smartcard_device_list_remove(pf_channel_server_context* rdpdr, wStream* s)
1592{
1593 size_t pos = 0;
1594 UINT32 count = 0;
1595
1596 WINPR_ASSERT(rdpdr);
1597 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, sizeof(UINT32)))
1598 return TRUE;
1599 pos = Stream_GetPosition(s);
1600 Stream_Read_UINT32(s, count);
1601
1602 if (count == 0)
1603 return TRUE;
1604
1605 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdpdr->log, s, count, sizeof(UINT32)))
1606 return TRUE;
1607
1608 for (UINT32 x = 0; x < count; x++)
1609 {
1610 UINT32 deviceID = 0;
1611 BYTE* dst = Stream_Pointer(s);
1612 Stream_Read_UINT32(s, deviceID);
1613 if (deviceID == SCARD_DEVICE_ID)
1614 {
1615 ArrayList_Remove(rdpdr->blockedDevices, (void*)(size_t)deviceID);
1616
1617 /* This is the only device, filter it! */
1618 if (count == 1)
1619 return TRUE;
1620
1621 /* Remove this device from the list */
1622 memmove(dst, Stream_ConstPointer(s), (count - x - 1) * sizeof(UINT32));
1623
1624 count--;
1625 if (Stream_SetPosition(s, pos))
1626 Stream_Write_UINT32(s, count);
1627 return FALSE;
1628 }
1629 }
1630
1631 return FALSE;
1632}
1633
1634WINPR_ATTR_NODISCARD
1635static BOOL filter_smartcard_device_io_request(pf_channel_server_context* rdpdr, wStream* s)
1636{
1637 UINT32 DeviceID = 0;
1638 WINPR_ASSERT(rdpdr);
1639 WINPR_ASSERT(s);
1640 Stream_Read_UINT32(s, DeviceID);
1641 return ArrayList_Contains(rdpdr->blockedDevices, (void*)(size_t)DeviceID);
1642}
1643
1644WINPR_ATTR_NODISCARD
1645static BOOL filter_smartcard_device_list_announce(pf_channel_server_context* rdpdr, wStream* s)
1646{
1647 UINT32 count = 0;
1648
1649 WINPR_ASSERT(rdpdr);
1650 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, sizeof(UINT32)))
1651 return TRUE;
1652 const size_t pos = Stream_GetPosition(s);
1653 Stream_Read_UINT32(s, count);
1654
1655 if (count == 0)
1656 return TRUE;
1657
1658 for (UINT32 x = 0; x < count; x++)
1659 {
1660 UINT32 DeviceType = 0;
1661 UINT32 DeviceId = 0;
1662 char PreferredDosName[8];
1663 UINT32 DeviceDataLength = 0;
1664 BYTE* dst = Stream_Pointer(s);
1665 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 20))
1666 return TRUE;
1667 Stream_Read_UINT32(s, DeviceType);
1668 Stream_Read_UINT32(s, DeviceId);
1669 Stream_Read(s, PreferredDosName, ARRAYSIZE(PreferredDosName));
1670 Stream_Read_UINT32(s, DeviceDataLength);
1671 if (!Stream_SafeSeek(s, DeviceDataLength))
1672 return TRUE;
1673 if (DeviceType == RDPDR_DTYP_SMARTCARD)
1674 {
1675 if (!ArrayList_Append(rdpdr->blockedDevices, (void*)(size_t)DeviceId))
1676 return FALSE;
1677 if (count == 1)
1678 return TRUE;
1679
1680 WLog_Print(rdpdr->log, WLOG_INFO, "Filtering smartcard device 0x%08" PRIx32 "",
1681 DeviceId);
1682
1683 memmove(dst, Stream_ConstPointer(s), Stream_GetRemainingLength(s));
1684 if (Stream_SetPosition(s, pos))
1685 Stream_Write_UINT32(s, count - 1);
1686 return FALSE;
1687 }
1688 }
1689
1690 return FALSE;
1691}
1692
1693WINPR_ATTR_NODISCARD
1694static BOOL filter_smartcard_device_list_announce_request(pf_channel_server_context* rdpdr,
1695 wStream* s)
1696{
1697 BOOL rc = TRUE;
1698 size_t pos = 0;
1699 UINT16 component = 0;
1700 UINT16 packetid = 0;
1701
1702 WINPR_ASSERT(rdpdr);
1703 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8))
1704 return FALSE;
1705
1706 pos = Stream_GetPosition(s);
1707
1708 Stream_Read_UINT16(s, component);
1709 Stream_Read_UINT16(s, packetid);
1710
1711 if (component != RDPDR_CTYP_CORE)
1712 goto fail;
1713
1714 switch (packetid)
1715 {
1716 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1717 if (filter_smartcard_device_list_announce(rdpdr, s))
1718 goto fail;
1719 break;
1720 case PAKID_CORE_DEVICELIST_REMOVE:
1721 if (filter_smartcard_device_list_remove(rdpdr, s))
1722 goto fail;
1723 break;
1724 case PAKID_CORE_DEVICE_IOREQUEST:
1725 if (filter_smartcard_device_io_request(rdpdr, s))
1726 goto fail;
1727 break;
1728
1729 case PAKID_CORE_SERVER_ANNOUNCE:
1730 case PAKID_CORE_CLIENTID_CONFIRM:
1731 case PAKID_CORE_CLIENT_NAME:
1732 case PAKID_CORE_DEVICE_REPLY:
1733 case PAKID_CORE_SERVER_CAPABILITY:
1734 case PAKID_CORE_CLIENT_CAPABILITY:
1735 case PAKID_CORE_USER_LOGGEDON:
1736 WLog_Print(rdpdr->log, WLOG_WARN, "Filtering client -> server message [%s | %s]",
1737 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1738 goto fail;
1739 default:
1740 break;
1741 }
1742
1743 rc = FALSE;
1744fail:
1745 if (!Stream_SetPosition(s, pos))
1746 return FALSE;
1747 return rc;
1748}
1749#endif
1750
1751WINPR_ATTR_MALLOC(Stream_Free, 1)
1752WINPR_ATTR_NODISCARD
1753static void* stream_copy(const void* obj)
1754{
1755 const wStream* src = obj;
1756 wStream* dst = Stream_New(nullptr, Stream_Capacity(src));
1757 if (!dst)
1758 return nullptr;
1759 memcpy(Stream_Buffer(dst), Stream_ConstBuffer(src), Stream_Capacity(dst));
1760 if (!Stream_SetLength(dst, Stream_Length(src)))
1761 goto fail;
1762 if (!Stream_SetPosition(dst, Stream_GetPosition(src)))
1763 goto fail;
1764 return dst;
1765fail:
1766 Stream_Free(dst, TRUE);
1767 return nullptr;
1768}
1769
1770static void stream_free(void* obj)
1771{
1772 wStream* s = obj;
1773 Stream_Free(s, TRUE);
1774}
1775
1776WINPR_ATTR_NODISCARD
1777static const char* pf_channel_rdpdr_client_context(void* arg)
1778{
1779 pClientContext* pc = arg;
1780 if (!pc)
1781 return "pc=null";
1782 if (!pc->pdata)
1783 return "pc->pdata=null";
1784 return pc->pdata->session_id;
1785}
1786
1787BOOL pf_channel_rdpdr_client_new(pClientContext* pc)
1788{
1789 wObject* obj = nullptr;
1790 pf_channel_client_context* rdpdr = nullptr;
1791
1792 WINPR_ASSERT(pc);
1793 WINPR_ASSERT(pc->interceptContextMap);
1794
1795 rdpdr = calloc(1, sizeof(pf_channel_client_context));
1796 if (!rdpdr)
1797 return FALSE;
1798 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1799 if (!rdpdr->log)
1800 goto fail;
1801
1802 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_client_context, pc))
1803 goto fail;
1804
1805 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_client_context_free))
1806 goto fail;
1807
1808 rdpdr->maxMajorVersion = RDPDR_VERSION_MAJOR;
1809 rdpdr->maxMinorVersion = RDPDR_VERSION_MINOR_RDP10X;
1810 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
1811
1812 rdpdr->queue = Queue_New(TRUE, 0, 0);
1813 if (!rdpdr->queue)
1814 goto fail;
1815 obj = Queue_Object(rdpdr->queue);
1816 WINPR_ASSERT(obj);
1817 obj->fnObjectNew = stream_copy;
1818 obj->fnObjectFree = stream_free;
1819 if (!HashTable_Insert(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1820 goto fail;
1821 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of rdpdr
1822 return TRUE;
1823fail:
1824 pf_channel_rdpdr_client_context_free(&rdpdr->common.base);
1825 return FALSE;
1826}
1827
1828void pf_channel_rdpdr_client_free(pClientContext* pc)
1829{
1830 WINPR_ASSERT(pc);
1831 WINPR_ASSERT(pc->interceptContextMap);
1832 HashTable_Remove(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1833}
1834
1835static void pf_channel_rdpdr_server_context_free(InterceptContextMapEntry* base)
1836{
1837 pf_channel_server_context* entry = (pf_channel_server_context*)base;
1838 if (!entry)
1839 return;
1840
1841 (void)WTSVirtualChannelClose(entry->handle);
1842 pf_channel_rdpdr_common_context_free(&entry->common);
1843 ArrayList_Free(entry->blockedDevices);
1844 WLog_Discard(entry->log);
1845 free(entry);
1846}
1847
1848WINPR_ATTR_NODISCARD
1849static const char* pf_channel_rdpdr_server_context(void* arg)
1850{
1851 pServerContext* ps = arg;
1852 if (!ps)
1853 return "ps=null";
1854 if (!ps->pdata)
1855 return "ps->pdata=null";
1856 return ps->pdata->session_id;
1857}
1858
1859BOOL pf_channel_rdpdr_server_new(pServerContext* ps)
1860{
1861 pf_channel_server_context* rdpdr = nullptr;
1862 PULONG pSessionId = nullptr;
1863 DWORD BytesReturned = 0;
1864
1865 WINPR_ASSERT(ps);
1866 WINPR_ASSERT(ps->interceptContextMap);
1867
1868 rdpdr = calloc(1, sizeof(pf_channel_server_context));
1869 if (!rdpdr)
1870 return FALSE;
1871 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1872 if (!rdpdr->log)
1873 goto fail;
1874
1875 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_server_context, ps))
1876 goto fail;
1877
1878 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_server_context_free))
1879 goto fail;
1880 rdpdr->state = STATE_SERVER_INITIAL;
1881
1882 rdpdr->blockedDevices = ArrayList_New(FALSE);
1883 if (!rdpdr->blockedDevices)
1884 goto fail;
1885
1886 rdpdr->SessionId = WTS_CURRENT_SESSION;
1887 if (WTSQuerySessionInformationA(ps->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*)&pSessionId,
1888 &BytesReturned))
1889 {
1890 rdpdr->SessionId = (DWORD)*pSessionId;
1891 WTSFreeMemory(pSessionId);
1892 }
1893
1894 rdpdr->handle = WTSVirtualChannelOpenEx(rdpdr->SessionId, RDPDR_SVC_CHANNEL_NAME, 0);
1895 if (rdpdr->handle == nullptr)
1896 goto fail;
1897 if (!HashTable_Insert(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1898 goto fail;
1899
1900 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of rdpdr
1901 return TRUE;
1902fail:
1903 pf_channel_rdpdr_server_context_free(&rdpdr->common.base);
1904 return FALSE;
1905}
1906
1907void pf_channel_rdpdr_server_free(pServerContext* ps)
1908{
1909 WINPR_ASSERT(ps);
1910 WINPR_ASSERT(ps->interceptContextMap);
1911 HashTable_Remove(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1912}
1913
1914WINPR_ATTR_NODISCARD
1915static pf_channel_server_context* get_channel(pServerContext* ps, BOOL send)
1916{
1917 pf_channel_server_context* rdpdr = nullptr;
1918 WINPR_ASSERT(ps);
1919 WINPR_ASSERT(ps->interceptContextMap);
1920
1921 rdpdr = HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1922 if (!rdpdr)
1923 {
1924 SERVER_RXTX_LOG(send, WLog_Get(RTAG), WLOG_ERROR,
1925 "Channel %s missing context in interceptContextMap",
1926 RDPDR_SVC_CHANNEL_NAME);
1927 return nullptr;
1928 }
1929
1930 return rdpdr;
1931}
1932
1933BOOL pf_channel_rdpdr_server_handle(pServerContext* ps, UINT16 channelId, const char* channel_name,
1934 const BYTE* xdata, size_t xsize, UINT32 flags, size_t totalSize)
1935{
1936 pf_channel_server_context* rdpdr = get_channel(ps, FALSE);
1937 if (!rdpdr)
1938 return FALSE;
1939
1940 WINPR_ASSERT(ps->pdata);
1941 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
1942
1943 wStream* s = rdpdr->common.buffer;
1944
1945 if (flags & CHANNEL_FLAG_FIRST)
1946 Stream_ResetPosition(s);
1947
1948 if (!Stream_EnsureRemainingCapacity(s, xsize))
1949 return FALSE;
1950 Stream_Write(s, xdata, xsize);
1951
1952 if ((flags & CHANNEL_FLAG_LAST) == 0)
1953 return TRUE;
1954
1955 Stream_SealLength(s);
1956 Stream_ResetPosition(s);
1957
1958 if (Stream_Length(s) != totalSize)
1959 {
1960 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
1961 "Received invalid %s channel data (client -> proxy), expected %" PRIuz
1962 "bytes, got %" PRIuz,
1963 channel_name, totalSize, Stream_Length(s));
1964 return FALSE;
1965 }
1966
1967 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_rx);
1968 switch (rdpdr->state)
1969 {
1970 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
1971 if (rdpdr_process_client_announce_reply(rdpdr, s) != CHANNEL_RC_OK)
1972 return FALSE;
1973 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST;
1974 break;
1975 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
1976 if (rdpdr_process_client_name_request(rdpdr, s, pc) != CHANNEL_RC_OK)
1977 return FALSE;
1978 if (rdpdr_send_server_capability_request(rdpdr) != CHANNEL_RC_OK)
1979 return FALSE;
1980 if (rdpdr_send_server_clientid_confirm(rdpdr) != CHANNEL_RC_OK)
1981 return FALSE;
1982 rdpdr->state = STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE;
1983 break;
1984 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
1985 if (rdpdr_process_client_capability_response(rdpdr, s) != CHANNEL_RC_OK)
1986 return FALSE;
1987 rdpdr->state = STATE_SERVER_CHANNEL_RUNNING;
1988 break;
1989 case STATE_SERVER_CHANNEL_RUNNING:
1990#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1991 if (!pf_channel_smartcard_client_emulate(pc) ||
1992 !filter_smartcard_device_list_announce_request(rdpdr, s))
1993 {
1994 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
1995 return FALSE;
1996 }
1997 else
1998 return pf_channel_smartcard_server_handle(ps, s);
1999#else
2000 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2001 return FALSE;
2002#endif
2003 break;
2004 default:
2005 case STATE_SERVER_INITIAL:
2006 SERVER_RX_LOG(rdpdr->log, WLOG_WARN, "Invalid state %s",
2007 rdpdr_server_state_to_string(rdpdr->state));
2008 return FALSE;
2009 }
2010
2011 return TRUE;
2012}
2013
2014BOOL pf_channel_rdpdr_server_announce(pServerContext* ps)
2015{
2016 pf_channel_server_context* rdpdr = get_channel(ps, TRUE);
2017 if (!rdpdr)
2018 return FALSE;
2019
2020 WINPR_ASSERT(rdpdr->state == STATE_SERVER_INITIAL);
2021 if (rdpdr_server_send_announce_request(rdpdr) != CHANNEL_RC_OK)
2022 return FALSE;
2023 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY;
2024 return TRUE;
2025}
2026
2027BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
2028{
2029 pf_channel_client_context* rdpdr = nullptr;
2030
2031 WINPR_ASSERT(pc);
2032 WINPR_ASSERT(pc->pdata);
2033 WINPR_ASSERT(pc->interceptContextMap);
2034
2035 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
2036 if (!rdpdr)
2037 return TRUE;
2038
2039 Queue_Clear(rdpdr->queue);
2040 rdpdr->flags = 0;
2041 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
2042
2043 return TRUE;
2044}
2045
2046WINPR_ATTR_NODISCARD
2047static PfChannelResult pf_rdpdr_back_data(proxyData* pdata,
2048 const pServerStaticChannelContext* channel,
2049 const BYTE* xdata, size_t xsize, UINT32 flags,
2050 size_t totalSize)
2051{
2052 WINPR_ASSERT(pdata);
2053 WINPR_ASSERT(channel);
2054
2055 pClientContext* pc = proxy_data_get_client_context(pdata);
2056 if (!pf_channel_rdpdr_client_handle(pc,
2057 WINPR_ASSERTING_INT_CAST(UINT16, channel->back_channel_id),
2058 channel->channel_name, xdata, xsize, flags, totalSize))
2059 return PF_CHANNEL_RESULT_ERROR;
2060
2061#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2062 if (pf_channel_smartcard_client_emulate(pdata->pc))
2063 return PF_CHANNEL_RESULT_DROP;
2064#endif
2065 return PF_CHANNEL_RESULT_DROP;
2066}
2067
2068WINPR_ATTR_NODISCARD
2069static PfChannelResult pf_rdpdr_front_data(proxyData* pdata,
2070 const pServerStaticChannelContext* channel,
2071 const BYTE* xdata, size_t xsize, UINT32 flags,
2072 size_t totalSize)
2073{
2074 WINPR_ASSERT(pdata);
2075 WINPR_ASSERT(channel);
2076
2077 pServerContext* ps = proxy_data_get_server_context(pdata);
2078 if (!pf_channel_rdpdr_server_handle(ps,
2079 WINPR_ASSERTING_INT_CAST(UINT16, channel->front_channel_id),
2080 channel->channel_name, xdata, xsize, flags, totalSize))
2081 return PF_CHANNEL_RESULT_ERROR;
2082
2083#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2084 if (pf_channel_smartcard_client_emulate(pdata->pc))
2085 return PF_CHANNEL_RESULT_DROP;
2086#endif
2087 return PF_CHANNEL_RESULT_DROP;
2088}
2089
2090BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
2091{
2092 channel->onBackData = pf_rdpdr_back_data;
2093 channel->onFrontData = pf_rdpdr_front_data;
2094
2095 if (!pf_channel_rdpdr_server_new(ps))
2096 return FALSE;
2097 if (!pf_channel_rdpdr_server_announce(ps))
2098 return FALSE;
2099
2100 return TRUE;
2101}
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew
Definition collections.h:54