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