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