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 SSIZE_T devNameWLen = ConvertUtf8NToWChar(
1116 device.PreferredDosName, ARRAYSIZE(device.PreferredDosName), nullptr, 0);
1117 if (devNameWLen < 0)
1118 goto fail;
1119 const size_t datalen =
1120 WINPR_ASSERTING_INT_CAST(size_t, devNameWLen) * sizeof(WCHAR);
1121 if (!Stream_EnsureRemainingCapacity(s, datalen + sizeof(UINT32)))
1122 goto fail;
1123 Stream_Write_UINT32(s, WINPR_ASSERTING_INT_CAST(uint32_t, datalen));
1124
1125 const SSIZE_T rcw = Stream_Write_UTF16_String_From_UTF8(
1126 s, charCount, device.PreferredDosName, charCount - 1, TRUE);
1127 if (rcw < 0)
1128 goto fail;
1129 }
1130 }
1131 else
1132 {
1133 Stream_Write_UINT32(s, device.DeviceDataLength);
1134 if (!Stream_EnsureRemainingCapacity(s, device.DeviceDataLength))
1135 goto fail;
1136 Stream_Write(s, device.DeviceData, device.DeviceDataLength);
1137 }
1138 }
1139 }
1140
1141 Stream_SealLength(s);
1142 rc = TRUE;
1143
1144fail:
1145 Stream_Free(clone, TRUE);
1146 return rc;
1147}
1148
1149WINPR_ATTR_NODISCARD
1150static BOOL pf_channel_rdpdr_rewrite_device_list(pf_channel_client_context* rdpdr,
1151 pServerContext* ps, wStream* s, BOOL toServer)
1152{
1153 WINPR_ASSERT(rdpdr);
1154 WINPR_ASSERT(ps);
1155
1156 const size_t pos = Stream_GetPosition(s);
1157 UINT16 component = 0;
1158 UINT16 packetid = 0;
1159 Stream_ResetPosition(s);
1160
1161 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1162 return FALSE;
1163
1164 Stream_Read_UINT16(s, component);
1165 Stream_Read_UINT16(s, packetid);
1166 if ((component != RDPDR_CTYP_CORE) || (packetid != PAKID_CORE_DEVICELIST_ANNOUNCE))
1167 return Stream_SetPosition(s, pos);
1168
1169 const pf_channel_server_context* srv =
1170 HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1171 if (!srv)
1172 {
1173 WLog_Print(rdpdr->log, WLOG_ERROR, "No channel %s in intercep map", RDPDR_SVC_CHANNEL_NAME);
1174 return FALSE;
1175 }
1176
1177 UINT32 from = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1178 UINT32 to = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1179 if (toServer)
1180 {
1181 from = rdpdr->common.capabilityVersions[CAP_DRIVE_TYPE];
1182 to = srv->common.capabilityVersions[CAP_DRIVE_TYPE];
1183 }
1184 if (!pf_channel_rdpdr_rewrite_device_list_to(s, from, to))
1185 return FALSE;
1186
1187 return Stream_SetPosition(s, pos);
1188}
1189
1190WINPR_ATTR_NODISCARD
1191static BOOL pf_channel_rdpdr_client_send_to_server(pf_channel_client_context* rdpdr,
1192 pServerContext* ps, wStream* s)
1193{
1194 WINPR_ASSERT(rdpdr);
1195 if (ps)
1196 {
1197 UINT16 server_channel_id = WTSChannelGetId(ps->context.peer, RDPDR_SVC_CHANNEL_NAME);
1198
1199 /* Ignore messages for channels that can not be mapped.
1200 * The client might not have enabled support for this specific channel,
1201 * so just drop the message. */
1202 if (server_channel_id == 0)
1203 return TRUE;
1204
1205 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, TRUE))
1206 return FALSE;
1207 size_t len = Stream_Length(s);
1208 if (!Stream_SetPosition(s, len))
1209 return ERROR_INVALID_DATA;
1210 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_tx);
1211 WINPR_ASSERT(ps->context.peer);
1212 WINPR_ASSERT(ps->context.peer->SendChannelData);
1213 return ps->context.peer->SendChannelData(ps->context.peer, server_channel_id,
1214 Stream_Buffer(s), len);
1215 }
1216 return TRUE;
1217}
1218
1219WINPR_ATTR_NODISCARD
1220static BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr);
1221
1222#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1223WINPR_ATTR_NODISCARD
1224static BOOL rdpdr_process_server_loggedon_request(pServerContext* ps, pClientContext* pc,
1225 pf_channel_client_context* rdpdr, wStream* s,
1226 UINT16 component, UINT16 packetid)
1227{
1228 WINPR_ASSERT(rdpdr);
1229 WLog_Print(rdpdr->log, WLOG_DEBUG, "[%s | %s]", rdpdr_component_string(component),
1230 rdpdr_packetid_string(packetid));
1231 if (rdpdr_send_emulated_scard_device_remove(pc, rdpdr) != CHANNEL_RC_OK)
1232 return FALSE;
1233 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) != CHANNEL_RC_OK)
1234 return FALSE;
1235 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1236}
1237
1238WINPR_ATTR_NODISCARD
1239static BOOL filter_smartcard_io_requests(pf_channel_client_context* rdpdr, wStream* s,
1240 UINT16* pPacketid)
1241{
1242 BOOL rc = FALSE;
1243 UINT16 component = 0;
1244 UINT16 packetid = 0;
1245 UINT32 deviceID = 0;
1246 size_t pos = 0;
1247
1248 WINPR_ASSERT(rdpdr);
1249 WINPR_ASSERT(pPacketid);
1250
1251 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 4))
1252 return FALSE;
1253
1254 pos = Stream_GetPosition(s);
1255 Stream_Read_UINT16(s, component);
1256 Stream_Read_UINT16(s, packetid);
1257
1258 if (Stream_GetRemainingLength(s) >= 4)
1259 Stream_Read_UINT32(s, deviceID);
1260
1261 WLog_Print(rdpdr->log, WLOG_DEBUG, "got: [%s | %s]: [0x%08" PRIx32 "]",
1262 rdpdr_component_string(component), rdpdr_packetid_string(packetid), deviceID);
1263
1264 if (component != RDPDR_CTYP_CORE)
1265 goto fail;
1266
1267 switch (packetid)
1268 {
1269 case PAKID_CORE_SERVER_ANNOUNCE:
1270 case PAKID_CORE_CLIENTID_CONFIRM:
1271 case PAKID_CORE_CLIENT_NAME:
1272 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1273 case PAKID_CORE_DEVICELIST_REMOVE:
1274 case PAKID_CORE_SERVER_CAPABILITY:
1275 case PAKID_CORE_CLIENT_CAPABILITY:
1276 WLog_Print(rdpdr->log, WLOG_WARN, "Filtering client -> server message [%s | %s]",
1277 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1278 *pPacketid = packetid;
1279 break;
1280 case PAKID_CORE_USER_LOGGEDON:
1281 *pPacketid = packetid;
1282 break;
1283 case PAKID_CORE_DEVICE_REPLY:
1284 case PAKID_CORE_DEVICE_IOREQUEST:
1285 if (deviceID != SCARD_DEVICE_ID)
1286 goto fail;
1287 *pPacketid = packetid;
1288 break;
1289 default:
1290 if (deviceID != SCARD_DEVICE_ID)
1291 goto fail;
1292 WLog_Print(rdpdr->log, WLOG_WARN,
1293 "Got [%s | %s] for deviceID 0x%08" PRIx32 ", TODO: Not handled!",
1294 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
1295 deviceID);
1296 goto fail;
1297 }
1298
1299 rc = TRUE;
1300
1301fail:
1302 if (!Stream_SetPosition(s, pos))
1303 return FALSE;
1304 return rc;
1305}
1306#endif
1307
1308BOOL pf_channel_send_client_queue(pClientContext* pc, pf_channel_client_context* rdpdr)
1309{
1310 WINPR_ASSERT(pc);
1311 WINPR_ASSERT(rdpdr);
1312
1313 if (rdpdr->state != STATE_CLIENT_CHANNEL_RUNNING)
1314 {
1315 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN, "Client RDPDR channel not ready, dropping packet!");
1316 return TRUE;
1317 }
1318
1319 const UINT16 channelId =
1320 freerdp_channels_get_id_by_name(pc->cctx.context.instance, RDPDR_SVC_CHANNEL_NAME);
1321 if ((channelId == 0) || (channelId == UINT16_MAX))
1322 {
1323 CLIENT_TX_LOG(rdpdr->log, WLOG_WARN,
1324 "Client RDPDR channel not available, dropping packet!");
1325 return TRUE;
1326 }
1327
1328 Queue_Lock(rdpdr->queue);
1329 while (Queue_Count(rdpdr->queue) > 0)
1330 {
1331 wStream* s = Queue_Dequeue(rdpdr->queue);
1332 if (!s)
1333 continue;
1334
1335 size_t len = Stream_Length(s);
1336 if (!Stream_SetPosition(s, len))
1337 {
1338 Stream_Free(s, TRUE);
1339 continue;
1340 }
1341
1342 rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_tx " (queue) ");
1343 WINPR_ASSERT(pc->cctx.context.instance->SendChannelData);
1344 if (!pc->cctx.context.instance->SendChannelData(pc->cctx.context.instance, channelId,
1345 Stream_Buffer(s), len))
1346 {
1347 CLIENT_TX_LOG(rdpdr->log, WLOG_ERROR, "xxxxxx TODO: Failed to send data!");
1348 }
1349 Stream_Free(s, TRUE);
1350 }
1351 Queue_Unlock(rdpdr->queue);
1352 return TRUE;
1353}
1354
1355WINPR_ATTR_NODISCARD
1356static BOOL rdpdr_handle_server_announce_request(pClientContext* pc,
1357 pf_channel_client_context* rdpdr, wStream* s)
1358{
1359 WINPR_ASSERT(pc);
1360 WINPR_ASSERT(rdpdr);
1361 WINPR_ASSERT(s);
1362
1363 if (rdpdr_process_server_announce_request(rdpdr, s) != CHANNEL_RC_OK)
1364 return FALSE;
1365 if (rdpdr_send_client_announce_reply(pc, rdpdr) != CHANNEL_RC_OK)
1366 return FALSE;
1367 if (rdpdr_send_client_name_request(pc, rdpdr) != CHANNEL_RC_OK)
1368 return FALSE;
1369 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1370 return TRUE;
1371}
1372
1373BOOL pf_channel_rdpdr_client_handle(pClientContext* pc, UINT16 channelId, const char* channel_name,
1374 const BYTE* xdata, size_t xsize, UINT32 flags, size_t totalSize)
1375{
1376#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1377 UINT16 packetid = 0;
1378#endif
1379
1380 WINPR_ASSERT(pc);
1381 WINPR_ASSERT(pc->pdata);
1382 WINPR_ASSERT(pc->interceptContextMap);
1383 WINPR_ASSERT(channel_name);
1384 WINPR_ASSERT(xdata);
1385
1386 pServerContext* ps = proxy_data_get_server_context(pc->pdata);
1387
1388 pf_channel_client_context* rdpdr =
1389 HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1390 if (!rdpdr)
1391 {
1392 CLIENT_RX_LOG(WLog_Get(RTAG), WLOG_ERROR,
1393 "Channel %s [0x%04" PRIx16 "] missing context in interceptContextMap",
1394 channel_name, channelId);
1395 return FALSE;
1396 }
1397
1398 wStream* s = rdpdr->common.buffer;
1399 if (flags & CHANNEL_FLAG_FIRST)
1400 Stream_ResetPosition(s);
1401 if (!Stream_EnsureRemainingCapacity(s, xsize))
1402 {
1403 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1404 "Channel %s [0x%04" PRIx16 "] not enough memory [need %" PRIuz "]",
1405 channel_name, channelId, xsize);
1406 return FALSE;
1407 }
1408 Stream_Write(s, xdata, xsize);
1409 if ((flags & CHANNEL_FLAG_LAST) == 0)
1410 return TRUE;
1411
1412 Stream_SealLength(s);
1413 Stream_ResetPosition(s);
1414 if (Stream_Length(s) != totalSize)
1415 {
1416 CLIENT_RX_LOG(rdpdr->log, WLOG_WARN,
1417 "Received invalid %s channel data (server -> proxy), expected %" PRIuz
1418 "bytes, got %" PRIuz,
1419 channel_name, totalSize, Stream_Length(s));
1420 return FALSE;
1421 }
1422
1423 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_server_rx);
1424 switch (rdpdr->state)
1425 {
1426 case STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST:
1427 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1428 return FALSE;
1429 break;
1430 case STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST:
1431 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1432 return FALSE;
1433 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM;
1434 break;
1435 case STATE_CLIENT_EXPECT_SERVER_CLIENT_ID_CONFIRM:
1436 if (!rdpdr_process_server_capability_request_or_clientid_confirm(rdpdr, s))
1437 return FALSE;
1438 if (rdpdr_send_client_capability_response(pc, rdpdr) != CHANNEL_RC_OK)
1439 return FALSE;
1440#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1441 if (pf_channel_smartcard_client_emulate(pc))
1442 {
1443 if (rdpdr_send_emulated_scard_device_list_announce_request(pc, rdpdr) !=
1444 CHANNEL_RC_OK)
1445 return FALSE;
1446 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1447 }
1448 else
1449#endif
1450 {
1451 rdpdr->state = STATE_CLIENT_CHANNEL_RUNNING;
1452 if (!pf_channel_send_client_queue(pc, rdpdr))
1453 return FALSE;
1454 }
1455
1456 break;
1457 case STATE_CLIENT_CHANNEL_RUNNING:
1458#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1459 if (!pf_channel_smartcard_client_emulate(pc) ||
1460 !filter_smartcard_io_requests(rdpdr, s, &packetid))
1461 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1462 else
1463 {
1464 switch (packetid)
1465 {
1466 case PAKID_CORE_USER_LOGGEDON:
1467 return rdpdr_process_server_loggedon_request(ps, pc, rdpdr, s,
1468 RDPDR_CTYP_CORE, packetid);
1469 case PAKID_CORE_DEVICE_IOREQUEST:
1470 {
1471 wStream* out = rdpdr_client_get_send_buffer(
1472 rdpdr, RDPDR_CTYP_CORE, PAKID_CORE_DEVICE_IOCOMPLETION, 0);
1473 WINPR_ASSERT(out);
1474
1475 if (!rdpdr_process_server_header(FALSE, rdpdr->log, s, RDPDR_CTYP_CORE,
1476 PAKID_CORE_DEVICE_IOREQUEST, 20))
1477 return FALSE;
1478
1479 if (!pf_channel_smartcard_client_handle(rdpdr->log, pc, s, out,
1480 rdpdr_client_send))
1481 return FALSE;
1482 }
1483 break;
1484 case PAKID_CORE_SERVER_ANNOUNCE:
1485 pf_channel_rdpdr_client_reset(pc);
1486 if (!rdpdr_handle_server_announce_request(pc, rdpdr, s))
1487 return FALSE;
1488 break;
1489 case PAKID_CORE_SERVER_CAPABILITY:
1490 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_CORE_CAPABILITY_REQUEST;
1491 rdpdr->flags = 0;
1492 return pf_channel_rdpdr_client_handle(pc, channelId, channel_name, xdata,
1493 xsize, flags, totalSize);
1494 case PAKID_CORE_DEVICE_REPLY:
1495 break;
1496 default:
1497 CLIENT_RX_LOG(
1498 rdpdr->log, WLOG_ERROR,
1499 "Channel %s [0x%04" PRIx16
1500 "] we´ve reached an impossible state %s! [%s] aliens invaded!",
1501 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state),
1502 rdpdr_packetid_string(packetid));
1503 return FALSE;
1504 }
1505 }
1506 break;
1507#else
1508 return pf_channel_rdpdr_client_send_to_server(rdpdr, ps, s);
1509#endif
1510 default:
1511 CLIENT_RX_LOG(rdpdr->log, WLOG_ERROR,
1512 "Channel %s [0x%04" PRIx16
1513 "] we´ve reached an impossible state %s! aliens invaded!",
1514 channel_name, channelId, rdpdr_client_state_to_string(rdpdr->state));
1515 return FALSE;
1516 }
1517
1518 return TRUE;
1519}
1520
1521static void pf_channel_rdpdr_common_context_free(pf_channel_common_context* common)
1522{
1523 if (!common)
1524 return;
1525 free(common->computerName.v);
1526 Stream_Free(common->s, TRUE);
1527 Stream_Free(common->buffer, TRUE);
1528}
1529
1530static void pf_channel_rdpdr_client_context_free(InterceptContextMapEntry* base)
1531{
1532 pf_channel_client_context* entry = (pf_channel_client_context*)base;
1533 if (!entry)
1534 return;
1535
1536 pf_channel_rdpdr_common_context_free(&entry->common);
1537 Queue_Free(entry->queue);
1538 WLog_Discard(entry->log);
1539 free(entry);
1540}
1541
1542WINPR_ATTR_NODISCARD
1543static BOOL pf_channel_rdpdr_common_context_new(pf_channel_common_context* common,
1544 void (*fkt)(InterceptContextMapEntry*))
1545{
1546 if (!common)
1547 return FALSE;
1548 common->base.free = fkt;
1549 common->s = Stream_New(nullptr, 1024);
1550 if (!common->s)
1551 return FALSE;
1552 common->buffer = Stream_New(nullptr, 1024);
1553 if (!common->buffer)
1554 return FALSE;
1555 common->computerNameUnicode = 1;
1556 common->computerName.v = nullptr;
1557 common->versionMajor = RDPDR_VERSION_MAJOR;
1558 common->versionMinor = RDPDR_VERSION_MINOR_RDP10X;
1559 common->clientID = SCARD_DEVICE_ID;
1560
1561 const UINT32 versions[] = { 0,
1562 GENERAL_CAPABILITY_VERSION_02,
1563 PRINT_CAPABILITY_VERSION_01,
1564 PORT_CAPABILITY_VERSION_01,
1565 DRIVE_CAPABILITY_VERSION_02,
1566 SMARTCARD_CAPABILITY_VERSION_01 };
1567
1568 memcpy(common->capabilityVersions, versions, sizeof(common->capabilityVersions));
1569 return TRUE;
1570}
1571
1572WINPR_ATTR_NODISCARD
1573static BOOL pf_channel_rdpdr_client_pass_message(pServerContext* ps, pClientContext* pc,
1574 WINPR_ATTR_UNUSED UINT16 channelId,
1575 const char* channel_name, wStream* s)
1576{
1577 pf_channel_client_context* rdpdr = nullptr;
1578
1579 WINPR_ASSERT(ps);
1580 WINPR_ASSERT(pc);
1581
1582 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, channel_name);
1583 if (!rdpdr)
1584 return TRUE; /* Ignore data for channels not available on proxy -> server connection */
1585 WINPR_ASSERT(rdpdr->queue);
1586
1587 if (!pf_channel_rdpdr_rewrite_device_list(rdpdr, ps, s, FALSE))
1588 return FALSE;
1589 if (!Queue_Enqueue(rdpdr->queue, s))
1590 return FALSE;
1591 return pf_channel_send_client_queue(pc, rdpdr);
1592}
1593
1594#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1595WINPR_ATTR_NODISCARD
1596static BOOL filter_smartcard_device_list_remove(pf_channel_server_context* rdpdr, wStream* s)
1597{
1598 size_t pos = 0;
1599 UINT32 count = 0;
1600
1601 WINPR_ASSERT(rdpdr);
1602 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, sizeof(UINT32)))
1603 return TRUE;
1604 pos = Stream_GetPosition(s);
1605 Stream_Read_UINT32(s, count);
1606
1607 if (count == 0)
1608 return TRUE;
1609
1610 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdpdr->log, s, count, sizeof(UINT32)))
1611 return TRUE;
1612
1613 for (UINT32 x = 0; x < count; x++)
1614 {
1615 UINT32 deviceID = 0;
1616 BYTE* dst = Stream_Pointer(s);
1617 Stream_Read_UINT32(s, deviceID);
1618 if (deviceID == SCARD_DEVICE_ID)
1619 {
1620 ArrayList_Remove(rdpdr->blockedDevices, (void*)(size_t)deviceID);
1621
1622 /* This is the only device, filter it! */
1623 if (count == 1)
1624 return TRUE;
1625
1626 /* Remove this device from the list */
1627 memmove(dst, Stream_ConstPointer(s), (count - x - 1) * sizeof(UINT32));
1628
1629 count--;
1630 if (Stream_SetPosition(s, pos))
1631 Stream_Write_UINT32(s, count);
1632 return FALSE;
1633 }
1634 }
1635
1636 return FALSE;
1637}
1638
1639WINPR_ATTR_NODISCARD
1640static BOOL filter_smartcard_device_io_request(pf_channel_server_context* rdpdr, wStream* s)
1641{
1642 UINT32 DeviceID = 0;
1643 WINPR_ASSERT(rdpdr);
1644 WINPR_ASSERT(s);
1645 Stream_Read_UINT32(s, DeviceID);
1646 return ArrayList_Contains(rdpdr->blockedDevices, (void*)(size_t)DeviceID);
1647}
1648
1649WINPR_ATTR_NODISCARD
1650static BOOL filter_smartcard_device_list_announce(pf_channel_server_context* rdpdr, wStream* s)
1651{
1652 UINT32 count = 0;
1653
1654 WINPR_ASSERT(rdpdr);
1655 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, sizeof(UINT32)))
1656 return TRUE;
1657 const size_t pos = Stream_GetPosition(s);
1658 Stream_Read_UINT32(s, count);
1659
1660 if (count == 0)
1661 return TRUE;
1662
1663 for (UINT32 x = 0; x < count; x++)
1664 {
1665 UINT32 DeviceType = 0;
1666 UINT32 DeviceId = 0;
1667 char PreferredDosName[8];
1668 UINT32 DeviceDataLength = 0;
1669 BYTE* dst = Stream_Pointer(s);
1670 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 20))
1671 return TRUE;
1672 Stream_Read_UINT32(s, DeviceType);
1673 Stream_Read_UINT32(s, DeviceId);
1674 Stream_Read(s, PreferredDosName, ARRAYSIZE(PreferredDosName));
1675 Stream_Read_UINT32(s, DeviceDataLength);
1676 if (!Stream_SafeSeek(s, DeviceDataLength))
1677 return TRUE;
1678 if (DeviceType == RDPDR_DTYP_SMARTCARD)
1679 {
1680 if (!ArrayList_Append(rdpdr->blockedDevices, (void*)(size_t)DeviceId))
1681 return FALSE;
1682 if (count == 1)
1683 return TRUE;
1684
1685 WLog_Print(rdpdr->log, WLOG_INFO, "Filtering smartcard device 0x%08" PRIx32 "",
1686 DeviceId);
1687
1688 memmove(dst, Stream_ConstPointer(s), Stream_GetRemainingLength(s));
1689 if (Stream_SetPosition(s, pos))
1690 Stream_Write_UINT32(s, count - 1);
1691 return FALSE;
1692 }
1693 }
1694
1695 return FALSE;
1696}
1697
1698WINPR_ATTR_NODISCARD
1699static BOOL filter_smartcard_device_list_announce_request(pf_channel_server_context* rdpdr,
1700 wStream* s)
1701{
1702 BOOL rc = TRUE;
1703 size_t pos = 0;
1704 UINT16 component = 0;
1705 UINT16 packetid = 0;
1706
1707 WINPR_ASSERT(rdpdr);
1708 if (!Stream_CheckAndLogRequiredLengthWLog(rdpdr->log, s, 8))
1709 return FALSE;
1710
1711 pos = Stream_GetPosition(s);
1712
1713 Stream_Read_UINT16(s, component);
1714 Stream_Read_UINT16(s, packetid);
1715
1716 if (component != RDPDR_CTYP_CORE)
1717 goto fail;
1718
1719 switch (packetid)
1720 {
1721 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1722 if (filter_smartcard_device_list_announce(rdpdr, s))
1723 goto fail;
1724 break;
1725 case PAKID_CORE_DEVICELIST_REMOVE:
1726 if (filter_smartcard_device_list_remove(rdpdr, s))
1727 goto fail;
1728 break;
1729 case PAKID_CORE_DEVICE_IOREQUEST:
1730 if (filter_smartcard_device_io_request(rdpdr, s))
1731 goto fail;
1732 break;
1733
1734 case PAKID_CORE_SERVER_ANNOUNCE:
1735 case PAKID_CORE_CLIENTID_CONFIRM:
1736 case PAKID_CORE_CLIENT_NAME:
1737 case PAKID_CORE_DEVICE_REPLY:
1738 case PAKID_CORE_SERVER_CAPABILITY:
1739 case PAKID_CORE_CLIENT_CAPABILITY:
1740 case PAKID_CORE_USER_LOGGEDON:
1741 WLog_Print(rdpdr->log, WLOG_WARN, "Filtering client -> server message [%s | %s]",
1742 rdpdr_component_string(component), rdpdr_packetid_string(packetid));
1743 goto fail;
1744 default:
1745 break;
1746 }
1747
1748 rc = FALSE;
1749fail:
1750 if (!Stream_SetPosition(s, pos))
1751 return FALSE;
1752 return rc;
1753}
1754#endif
1755
1756WINPR_ATTR_MALLOC(Stream_Free, 1)
1757WINPR_ATTR_NODISCARD
1758static void* stream_copy(const void* obj)
1759{
1760 const wStream* src = obj;
1761 wStream* dst = Stream_New(nullptr, Stream_Capacity(src));
1762 if (!dst)
1763 return nullptr;
1764 memcpy(Stream_Buffer(dst), Stream_ConstBuffer(src), Stream_Capacity(dst));
1765 if (!Stream_SetLength(dst, Stream_Length(src)))
1766 goto fail;
1767 if (!Stream_SetPosition(dst, Stream_GetPosition(src)))
1768 goto fail;
1769 return dst;
1770fail:
1771 Stream_Free(dst, TRUE);
1772 return nullptr;
1773}
1774
1775static void stream_free(void* obj)
1776{
1777 wStream* s = obj;
1778 Stream_Free(s, TRUE);
1779}
1780
1781WINPR_ATTR_NODISCARD
1782static const char* pf_channel_rdpdr_client_context(void* arg)
1783{
1784 pClientContext* pc = arg;
1785 if (!pc)
1786 return "pc=null";
1787 if (!pc->pdata)
1788 return "pc->pdata=null";
1789 return pc->pdata->session_id;
1790}
1791
1792BOOL pf_channel_rdpdr_client_new(pClientContext* pc)
1793{
1794 wObject* obj = nullptr;
1795 pf_channel_client_context* rdpdr = nullptr;
1796
1797 WINPR_ASSERT(pc);
1798 WINPR_ASSERT(pc->interceptContextMap);
1799
1800 rdpdr = calloc(1, sizeof(pf_channel_client_context));
1801 if (!rdpdr)
1802 return FALSE;
1803 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1804 if (!rdpdr->log)
1805 goto fail;
1806
1807 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_client_context, pc))
1808 goto fail;
1809
1810 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_client_context_free))
1811 goto fail;
1812
1813 rdpdr->maxMajorVersion = RDPDR_VERSION_MAJOR;
1814 rdpdr->maxMinorVersion = RDPDR_VERSION_MINOR_RDP10X;
1815 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
1816
1817 rdpdr->queue = Queue_New(TRUE, 0, 0);
1818 if (!rdpdr->queue)
1819 goto fail;
1820 obj = Queue_Object(rdpdr->queue);
1821 WINPR_ASSERT(obj);
1822 obj->fnObjectNew = stream_copy;
1823 obj->fnObjectFree = stream_free;
1824 if (!HashTable_Insert(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1825 goto fail;
1826 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of rdpdr
1827 return TRUE;
1828fail:
1829 pf_channel_rdpdr_client_context_free(&rdpdr->common.base);
1830 return FALSE;
1831}
1832
1833void pf_channel_rdpdr_client_free(pClientContext* pc)
1834{
1835 WINPR_ASSERT(pc);
1836 WINPR_ASSERT(pc->interceptContextMap);
1837 HashTable_Remove(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1838}
1839
1840static void pf_channel_rdpdr_server_context_free(InterceptContextMapEntry* base)
1841{
1842 pf_channel_server_context* entry = (pf_channel_server_context*)base;
1843 if (!entry)
1844 return;
1845
1846 (void)WTSVirtualChannelClose(entry->handle);
1847 pf_channel_rdpdr_common_context_free(&entry->common);
1848 ArrayList_Free(entry->blockedDevices);
1849 WLog_Discard(entry->log);
1850 free(entry);
1851}
1852
1853WINPR_ATTR_NODISCARD
1854static const char* pf_channel_rdpdr_server_context(void* arg)
1855{
1856 pServerContext* ps = arg;
1857 if (!ps)
1858 return "ps=null";
1859 if (!ps->pdata)
1860 return "ps->pdata=null";
1861 return ps->pdata->session_id;
1862}
1863
1864BOOL pf_channel_rdpdr_server_new(pServerContext* ps)
1865{
1866 pf_channel_server_context* rdpdr = nullptr;
1867 PULONG pSessionId = nullptr;
1868 DWORD BytesReturned = 0;
1869
1870 WINPR_ASSERT(ps);
1871 WINPR_ASSERT(ps->interceptContextMap);
1872
1873 rdpdr = calloc(1, sizeof(pf_channel_server_context));
1874 if (!rdpdr)
1875 return FALSE;
1876 rdpdr->log = WLog_Create(RTAG, WLog_GetRoot());
1877 if (!rdpdr->log)
1878 goto fail;
1879
1880 if (!WLog_SetContext(rdpdr->log, pf_channel_rdpdr_server_context, ps))
1881 goto fail;
1882
1883 if (!pf_channel_rdpdr_common_context_new(&rdpdr->common, pf_channel_rdpdr_server_context_free))
1884 goto fail;
1885 rdpdr->state = STATE_SERVER_INITIAL;
1886
1887 rdpdr->blockedDevices = ArrayList_New(FALSE);
1888 if (!rdpdr->blockedDevices)
1889 goto fail;
1890
1891 rdpdr->SessionId = WTS_CURRENT_SESSION;
1892 if (WTSQuerySessionInformationA(ps->vcm, WTS_CURRENT_SESSION, WTSSessionId, (LPSTR*)&pSessionId,
1893 &BytesReturned))
1894 {
1895 rdpdr->SessionId = (DWORD)*pSessionId;
1896 WTSFreeMemory(pSessionId);
1897 }
1898
1899 rdpdr->handle = WTSVirtualChannelOpenEx(rdpdr->SessionId, RDPDR_SVC_CHANNEL_NAME, 0);
1900 if (rdpdr->handle == nullptr)
1901 goto fail;
1902 if (!HashTable_Insert(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME, rdpdr))
1903 goto fail;
1904
1905 // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): HashTable_Insert takes ownership of rdpdr
1906 return TRUE;
1907fail:
1908 pf_channel_rdpdr_server_context_free(&rdpdr->common.base);
1909 return FALSE;
1910}
1911
1912void pf_channel_rdpdr_server_free(pServerContext* ps)
1913{
1914 WINPR_ASSERT(ps);
1915 WINPR_ASSERT(ps->interceptContextMap);
1916 HashTable_Remove(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1917}
1918
1919WINPR_ATTR_NODISCARD
1920static pf_channel_server_context* get_channel(pServerContext* ps, BOOL send)
1921{
1922 pf_channel_server_context* rdpdr = nullptr;
1923 WINPR_ASSERT(ps);
1924 WINPR_ASSERT(ps->interceptContextMap);
1925
1926 rdpdr = HashTable_GetItemValue(ps->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
1927 if (!rdpdr)
1928 {
1929 SERVER_RXTX_LOG(send, WLog_Get(RTAG), WLOG_ERROR,
1930 "Channel %s missing context in interceptContextMap",
1931 RDPDR_SVC_CHANNEL_NAME);
1932 return nullptr;
1933 }
1934
1935 return rdpdr;
1936}
1937
1938BOOL pf_channel_rdpdr_server_handle(pServerContext* ps, UINT16 channelId, const char* channel_name,
1939 const BYTE* xdata, size_t xsize, UINT32 flags, size_t totalSize)
1940{
1941 pf_channel_server_context* rdpdr = get_channel(ps, FALSE);
1942 if (!rdpdr)
1943 return FALSE;
1944
1945 WINPR_ASSERT(ps->pdata);
1946 pClientContext* pc = proxy_data_get_client_context(ps->pdata);
1947
1948 wStream* s = rdpdr->common.buffer;
1949
1950 if (flags & CHANNEL_FLAG_FIRST)
1951 Stream_ResetPosition(s);
1952
1953 if (!Stream_EnsureRemainingCapacity(s, xsize))
1954 return FALSE;
1955 Stream_Write(s, xdata, xsize);
1956
1957 if ((flags & CHANNEL_FLAG_LAST) == 0)
1958 return TRUE;
1959
1960 Stream_SealLength(s);
1961 Stream_ResetPosition(s);
1962
1963 if (Stream_Length(s) != totalSize)
1964 {
1965 SERVER_RX_LOG(rdpdr->log, WLOG_WARN,
1966 "Received invalid %s channel data (client -> proxy), expected %" PRIuz
1967 "bytes, got %" PRIuz,
1968 channel_name, totalSize, Stream_Length(s));
1969 return FALSE;
1970 }
1971
1972 rdpdr_dump_received_packet(rdpdr->log, WLOG_TRACE, s, proxy_client_rx);
1973 switch (rdpdr->state)
1974 {
1975 case STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY:
1976 if (rdpdr_process_client_announce_reply(rdpdr, s) != CHANNEL_RC_OK)
1977 return FALSE;
1978 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST;
1979 break;
1980 case STATE_SERVER_EXPECT_CLIENT_NAME_REQUEST:
1981 if (rdpdr_process_client_name_request(rdpdr, s, pc) != CHANNEL_RC_OK)
1982 return FALSE;
1983 if (rdpdr_send_server_capability_request(rdpdr) != CHANNEL_RC_OK)
1984 return FALSE;
1985 if (rdpdr_send_server_clientid_confirm(rdpdr) != CHANNEL_RC_OK)
1986 return FALSE;
1987 rdpdr->state = STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE;
1988 break;
1989 case STATE_SERVER_EXPECT_EXPECT_CLIENT_CAPABILITY_RESPONE:
1990 if (rdpdr_process_client_capability_response(rdpdr, s) != CHANNEL_RC_OK)
1991 return FALSE;
1992 rdpdr->state = STATE_SERVER_CHANNEL_RUNNING;
1993 break;
1994 case STATE_SERVER_CHANNEL_RUNNING:
1995#if defined(WITH_PROXY_EMULATE_SMARTCARD)
1996 if (!pf_channel_smartcard_client_emulate(pc) ||
1997 !filter_smartcard_device_list_announce_request(rdpdr, s))
1998 {
1999 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2000 return FALSE;
2001 }
2002 else
2003 return pf_channel_smartcard_server_handle(ps, s);
2004#else
2005 if (!pf_channel_rdpdr_client_pass_message(ps, pc, channelId, channel_name, s))
2006 return FALSE;
2007#endif
2008 break;
2009 default:
2010 case STATE_SERVER_INITIAL:
2011 SERVER_RX_LOG(rdpdr->log, WLOG_WARN, "Invalid state %s",
2012 rdpdr_server_state_to_string(rdpdr->state));
2013 return FALSE;
2014 }
2015
2016 return TRUE;
2017}
2018
2019BOOL pf_channel_rdpdr_server_announce(pServerContext* ps)
2020{
2021 pf_channel_server_context* rdpdr = get_channel(ps, TRUE);
2022 if (!rdpdr)
2023 return FALSE;
2024
2025 WINPR_ASSERT(rdpdr->state == STATE_SERVER_INITIAL);
2026 if (rdpdr_server_send_announce_request(rdpdr) != CHANNEL_RC_OK)
2027 return FALSE;
2028 rdpdr->state = STATE_SERVER_EXPECT_CLIENT_ANNOUNCE_REPLY;
2029 return TRUE;
2030}
2031
2032BOOL pf_channel_rdpdr_client_reset(pClientContext* pc)
2033{
2034 pf_channel_client_context* rdpdr = nullptr;
2035
2036 WINPR_ASSERT(pc);
2037 WINPR_ASSERT(pc->pdata);
2038 WINPR_ASSERT(pc->interceptContextMap);
2039
2040 rdpdr = HashTable_GetItemValue(pc->interceptContextMap, RDPDR_SVC_CHANNEL_NAME);
2041 if (!rdpdr)
2042 return TRUE;
2043
2044 Queue_Clear(rdpdr->queue);
2045 rdpdr->flags = 0;
2046 rdpdr->state = STATE_CLIENT_EXPECT_SERVER_ANNOUNCE_REQUEST;
2047
2048 return TRUE;
2049}
2050
2051WINPR_ATTR_NODISCARD
2052static PfChannelResult pf_rdpdr_back_data(proxyData* pdata,
2053 const pServerStaticChannelContext* channel,
2054 const BYTE* xdata, size_t xsize, UINT32 flags,
2055 size_t totalSize)
2056{
2057 WINPR_ASSERT(pdata);
2058 WINPR_ASSERT(channel);
2059
2060 pClientContext* pc = proxy_data_get_client_context(pdata);
2061 if (!pf_channel_rdpdr_client_handle(pc,
2062 WINPR_ASSERTING_INT_CAST(UINT16, channel->back_channel_id),
2063 channel->channel_name, xdata, xsize, flags, totalSize))
2064 return PF_CHANNEL_RESULT_ERROR;
2065
2066#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2067 if (pf_channel_smartcard_client_emulate((pClientContext*)pdata->pc))
2068 return PF_CHANNEL_RESULT_DROP;
2069#endif
2070 return PF_CHANNEL_RESULT_DROP;
2071}
2072
2073WINPR_ATTR_NODISCARD
2074static PfChannelResult pf_rdpdr_front_data(proxyData* pdata,
2075 const pServerStaticChannelContext* channel,
2076 const BYTE* xdata, size_t xsize, UINT32 flags,
2077 size_t totalSize)
2078{
2079 WINPR_ASSERT(pdata);
2080 WINPR_ASSERT(channel);
2081
2082 pServerContext* ps = proxy_data_get_server_context(pdata);
2083 if (!pf_channel_rdpdr_server_handle(ps,
2084 WINPR_ASSERTING_INT_CAST(UINT16, channel->front_channel_id),
2085 channel->channel_name, xdata, xsize, flags, totalSize))
2086 return PF_CHANNEL_RESULT_ERROR;
2087
2088#if defined(WITH_PROXY_EMULATE_SMARTCARD)
2089 if (pf_channel_smartcard_client_emulate((pClientContext*)pdata->pc))
2090 return PF_CHANNEL_RESULT_DROP;
2091#endif
2092 return PF_CHANNEL_RESULT_DROP;
2093}
2094
2095BOOL pf_channel_setup_rdpdr(pServerContext* ps, pServerStaticChannelContext* channel)
2096{
2097 channel->onBackData = pf_rdpdr_back_data;
2098 channel->onFrontData = pf_rdpdr_front_data;
2099
2100 if (!pf_channel_rdpdr_server_new(ps))
2101 return FALSE;
2102 if (!pf_channel_rdpdr_server_announce(ps))
2103 return FALSE;
2104
2105 return TRUE;
2106}
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