FreeRDP
gcc.c
1 
24 #include <freerdp/config.h>
25 
26 #include "settings.h"
27 
28 #include <winpr/crt.h>
29 #include <winpr/crypto.h>
30 #include <winpr/assert.h>
31 #include <winpr/cast.h>
32 
33 #include <freerdp/log.h>
34 #include <freerdp/utils/string.h>
35 #include <freerdp/crypto/certificate.h>
36 
37 #include "utils.h"
38 #include "gcc.h"
39 #include "nego.h"
40 
41 #include "../crypto/certificate.h"
42 
43 #define TAG FREERDP_TAG("core.gcc")
44 
45 typedef enum
46 {
47  HIGH_COLOR_4BPP = 0x04,
48  HIGH_COLOR_8BPP = 0x08,
49  HIGH_COLOR_15BPP = 0x0F,
50  HIGH_COLOR_16BPP = 0x10,
51  HIGH_COLOR_24BPP = 0x18,
52 } HIGH_COLOR_DEPTH;
53 
54 static const char* HighColorToString(HIGH_COLOR_DEPTH color)
55 {
56  switch (color)
57  {
58  case HIGH_COLOR_4BPP:
59  return "HIGH_COLOR_4BPP";
60  case HIGH_COLOR_8BPP:
61  return "HIGH_COLOR_8BPP";
62  case HIGH_COLOR_15BPP:
63  return "HIGH_COLOR_15BPP";
64  case HIGH_COLOR_16BPP:
65  return "HIGH_COLOR_16BPP";
66  case HIGH_COLOR_24BPP:
67  return "HIGH_COLOR_24BPP";
68  default:
69  return "HIGH_COLOR_UNKNOWN";
70  }
71 }
72 
73 static HIGH_COLOR_DEPTH ColorDepthToHighColor(UINT32 bpp)
74 {
75  switch (bpp)
76  {
77  case 4:
78  return HIGH_COLOR_4BPP;
79  case 8:
80  return HIGH_COLOR_8BPP;
81  case 15:
82  return HIGH_COLOR_15BPP;
83  case 16:
84  return HIGH_COLOR_16BPP;
85  default:
86  return HIGH_COLOR_24BPP;
87  }
88 }
89 
90 static char* gcc_block_type_string(UINT16 type, char* buffer, size_t size);
91 static BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs);
92 static BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs);
93 static BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, UINT16 length);
94 static BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, UINT16 length);
95 static BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length);
96 static BOOL gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length);
97 
98 static BOOL gcc_write_client_core_data(wStream* s, const rdpMcs* mcs);
99 static BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs);
100 static BOOL gcc_write_server_core_data(wStream* s, rdpMcs* mcs);
101 static BOOL gcc_read_client_security_data(wStream* s, rdpMcs* mcs);
102 static BOOL gcc_write_client_security_data(wStream* s, const rdpMcs* mcs);
103 static BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs);
104 static BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs);
105 static BOOL gcc_read_client_network_data(wStream* s, rdpMcs* mcs);
106 static BOOL gcc_write_client_network_data(wStream* s, const rdpMcs* mcs);
107 static BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs);
108 static BOOL gcc_write_server_network_data(wStream* s, const rdpMcs* mcs);
109 static BOOL gcc_write_client_cluster_data(wStream* s, const rdpMcs* mcs);
110 static BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs);
111 static BOOL gcc_write_client_monitor_data(wStream* s, const rdpMcs* mcs);
112 static BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs);
113 static BOOL gcc_write_client_monitor_extended_data(wStream* s, const rdpMcs* mcs);
114 static BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs);
115 static BOOL gcc_write_client_message_channel_data(wStream* s, const rdpMcs* mcs);
116 static BOOL gcc_read_server_message_channel_data(wStream* s, rdpMcs* mcs);
117 static BOOL gcc_write_server_message_channel_data(wStream* s, const rdpMcs* mcs);
118 static BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs);
119 static BOOL gcc_write_client_multitransport_channel_data(wStream* s, const rdpMcs* mcs);
120 static BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpMcs* mcs);
121 static BOOL gcc_write_server_multitransport_channel_data(wStream* s, const rdpMcs* mcs);
122 
123 static rdpSettings* mcs_get_settings(rdpMcs* mcs)
124 {
125  WINPR_ASSERT(mcs);
126 
127  rdpContext* context = transport_get_context(mcs->transport);
128  WINPR_ASSERT(context);
129 
130  return context->settings;
131 }
132 
133 static const rdpSettings* mcs_get_const_settings(const rdpMcs* mcs)
134 {
135  WINPR_ASSERT(mcs);
136 
137  const rdpContext* context = transport_get_context(mcs->transport);
138  WINPR_ASSERT(context);
139 
140  return context->settings;
141 }
142 
143 static char* rdp_early_server_caps_string(UINT32 flags, char* buffer, size_t size)
144 {
145  char msg[32] = { 0 };
146  const UINT32 mask = RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
147  RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
148  const UINT32 unknown = flags & (~mask);
149 
150  if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
151  winpr_str_append("RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1", buffer, size, "|");
152  if (flags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
153  winpr_str_append("RNS_UD_SC_DYNAMIC_DST_SUPPORTED", buffer, size, "|");
154  if (flags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
155  winpr_str_append("RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2", buffer, size, "|");
156  if (flags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
157  winpr_str_append("RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED", buffer, size, "|");
158 
159  if (unknown != 0)
160  {
161  (void)_snprintf(msg, sizeof(msg), "RNS_UD_SC_UNKNOWN[0x%08" PRIx32 "]", unknown);
162  winpr_str_append(msg, buffer, size, "|");
163  }
164  (void)_snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", flags);
165  winpr_str_append(msg, buffer, size, "|");
166  return buffer;
167 }
168 
169 static const char* rdp_early_client_caps_string(UINT32 flags, char* buffer, size_t size)
170 {
171  char msg[32] = { 0 };
172  const UINT32 mask = RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
173  RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
174  RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
175  RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU |
176  RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
177  RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
178  RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
179  const UINT32 unknown = flags & (~mask);
180 
181  if (flags & RNS_UD_CS_SUPPORT_ERRINFO_PDU)
182  winpr_str_append("RNS_UD_CS_SUPPORT_ERRINFO_PDU", buffer, size, "|");
183  if (flags & RNS_UD_CS_WANT_32BPP_SESSION)
184  winpr_str_append("RNS_UD_CS_WANT_32BPP_SESSION", buffer, size, "|");
185  if (flags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU)
186  winpr_str_append("RNS_UD_CS_SUPPORT_STATUSINFO_PDU", buffer, size, "|");
187  if (flags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS)
188  winpr_str_append("RNS_UD_CS_STRONG_ASYMMETRIC_KEYS", buffer, size, "|");
189  if (flags & RNS_UD_CS_RELATIVE_MOUSE_INPUT)
190  winpr_str_append("RNS_UD_CS_RELATIVE_MOUSE_INPUT", buffer, size, "|");
191  if (flags & RNS_UD_CS_VALID_CONNECTION_TYPE)
192  winpr_str_append("RNS_UD_CS_VALID_CONNECTION_TYPE", buffer, size, "|");
193  if (flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU)
194  winpr_str_append("RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU", buffer, size, "|");
195  if (flags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT)
196  winpr_str_append("RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT", buffer, size, "|");
197  if (flags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL)
198  winpr_str_append("RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL", buffer, size, "|");
199  if (flags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE)
200  winpr_str_append("RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE", buffer, size, "|");
201  if (flags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU)
202  winpr_str_append("RNS_UD_CS_SUPPORT_HEARTBEAT_PDU", buffer, size, "|");
203  if (flags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN)
204  winpr_str_append("RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN", buffer, size, "|");
205 
206  if (unknown != 0)
207  {
208  (void)_snprintf(msg, sizeof(msg), "RNS_UD_CS_UNKNOWN[0x%08" PRIx32 "]", unknown);
209  winpr_str_append(msg, buffer, size, "|");
210  }
211  (void)_snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", flags);
212  winpr_str_append(msg, buffer, size, "|");
213  return buffer;
214 }
215 
216 static DWORD rdp_version_common(DWORD serverVersion, DWORD clientVersion)
217 {
218  DWORD version = MIN(serverVersion, clientVersion);
219 
220  switch (version)
221  {
222  case RDP_VERSION_4:
223  case RDP_VERSION_5_PLUS:
224  case RDP_VERSION_10_0:
225  case RDP_VERSION_10_1:
226  case RDP_VERSION_10_2:
227  case RDP_VERSION_10_3:
228  case RDP_VERSION_10_4:
229  case RDP_VERSION_10_5:
230  case RDP_VERSION_10_6:
231  case RDP_VERSION_10_7:
232  case RDP_VERSION_10_8:
233  case RDP_VERSION_10_9:
234  case RDP_VERSION_10_10:
235  case RDP_VERSION_10_11:
236  case RDP_VERSION_10_12:
237  return version;
238 
239  default:
240  WLog_ERR(TAG, "Invalid client [%" PRId32 "] and server [%" PRId32 "] versions",
241  serverVersion, clientVersion);
242  return version;
243  }
244 }
245 
340 /*
341  * OID = 0.0.20.124.0.1
342  * { itu-t(0) recommendation(0) t(20) t124(124) version(0) 1 }
343  * v.1 of ITU-T Recommendation T.124 (Feb 1998): "Generic Conference Control"
344  */
345 static const BYTE t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
346 
347 static const BYTE h221_cs_key[4] = "Duca";
348 static const BYTE h221_sc_key[4] = "McDn";
349 
360 BOOL gcc_read_conference_create_request(wStream* s, rdpMcs* mcs)
361 {
362  UINT16 length = 0;
363  BYTE choice = 0;
364  BYTE number = 0;
365  BYTE selection = 0;
366 
367  WINPR_ASSERT(s);
368  WINPR_ASSERT(mcs);
369  /* ConnectData */
370  if (!per_read_choice(s, &choice))
371  return FALSE;
372 
373  if (!per_read_object_identifier(s, t124_02_98_oid))
374  return FALSE;
375 
376  /* ConnectData::connectPDU (OCTET_STRING) */
377  if (!per_read_length(s, &length))
378  return FALSE;
379 
380  /* ConnectGCCPDU */
381  if (!per_read_choice(s, &choice))
382  return FALSE;
383 
384  if (!per_read_selection(s, &selection))
385  return FALSE;
386 
387  /* ConferenceCreateRequest::conferenceName */
388  if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
389  return FALSE;
390 
391  if (!per_read_padding(s, 1)) /* padding */
392  return FALSE;
393 
394  /* UserData (SET OF SEQUENCE) */
395  if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
396  return FALSE;
397 
398  if (!per_read_choice(s, &choice) ||
399  choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
400  return FALSE;
401 
402  /* h221NonStandard */
403  if (!per_read_octet_string(s, h221_cs_key, 4,
404  4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
405  return FALSE;
406 
407  /* userData::value (OCTET_STRING) */
408  if (!per_read_length(s, &length))
409  return FALSE;
410 
411  if (!Stream_CheckAndLogRequiredLength(TAG, s, length))
412  return FALSE;
413 
414  if (!gcc_read_client_data_blocks(s, mcs, length))
415  return FALSE;
416 
417  return TRUE;
418 }
419 
430 BOOL gcc_write_conference_create_request(wStream* s, wStream* userData)
431 {
432  WINPR_ASSERT(s);
433  WINPR_ASSERT(userData);
434  /* ConnectData */
435  if (!per_write_choice(s, 0)) /* From Key select object (0) of type OBJECT_IDENTIFIER */
436  return FALSE;
437  if (!per_write_object_identifier(s, t124_02_98_oid)) /* ITU-T T.124 (02/98) OBJECT_IDENTIFIER */
438  return FALSE;
439  /* ConnectData::connectPDU (OCTET_STRING) */
440  const size_t pos = Stream_GetPosition(userData);
441  WINPR_ASSERT(pos <= UINT16_MAX - 14);
442  if (!per_write_length(s, (UINT16)pos + 14)) /* connectPDU length */
443  return FALSE;
444  /* ConnectGCCPDU */
445  if (!per_write_choice(s, 0)) /* From ConnectGCCPDU select conferenceCreateRequest (0) of type
446  ConferenceCreateRequest */
447  return FALSE;
448  if (!per_write_selection(s, 0x08)) /* select optional userData from ConferenceCreateRequest */
449  return FALSE;
450  /* ConferenceCreateRequest::conferenceName */
451  if (!per_write_numeric_string(s, (BYTE*)"1", 1, 1)) /* ConferenceName::numeric */
452  return FALSE;
453  if (!per_write_padding(s, 1)) /* padding */
454  return FALSE;
455  /* UserData (SET OF SEQUENCE) */
456  if (!per_write_number_of_sets(s, 1)) /* one set of UserData */
457  return FALSE;
458  if (!per_write_choice(s, 0xC0)) /* UserData::value present + select h221NonStandard (1) */
459  return FALSE;
460  /* h221NonStandard */
461  if (!per_write_octet_string(s, h221_cs_key, 4,
462  4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
463  return FALSE;
464  /* userData::value (OCTET_STRING) */
465  const size_t upos = Stream_GetPosition(userData);
466  WINPR_ASSERT(upos <= UINT16_MAX);
467  return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)upos,
468  0); /* array of client data blocks */
469 }
470 
471 BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs)
472 {
473  UINT16 length = 0;
474  UINT32 tag = 0;
475  UINT16 nodeID = 0;
476  BYTE result = 0;
477  BYTE choice = 0;
478  BYTE number = 0;
479  WINPR_ASSERT(s);
480  WINPR_ASSERT(mcs);
481  /* ConnectData */
482  if (!per_read_choice(s, &choice) || !per_read_object_identifier(s, t124_02_98_oid))
483  return FALSE;
484 
485  /* ConnectData::connectPDU (OCTET_STRING) */
486  if (!per_read_length(s, &length))
487  return FALSE;
488 
489  /* ConnectGCCPDU */
490  if (!per_read_choice(s, &choice))
491  return FALSE;
492 
493  /* ConferenceCreateResponse::nodeID (UserID) */
494  if (!per_read_integer16(s, &nodeID, 1001))
495  return FALSE;
496 
497  /* ConferenceCreateResponse::tag (INTEGER) */
498  if (!per_read_integer(s, &tag))
499  return FALSE;
500 
501  /* ConferenceCreateResponse::result (ENUMERATED) */
502  if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
503  return FALSE;
504 
505  /* number of UserData sets */
506  if (!per_read_number_of_sets(s, &number))
507  return FALSE;
508 
509  /* UserData::value present + select h221NonStandard (1) */
510  if (!per_read_choice(s, &choice))
511  return FALSE;
512 
513  /* h221NonStandard */
514  if (!per_read_octet_string(s, h221_sc_key, 4,
515  4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
516  return FALSE;
517 
518  /* userData (OCTET_STRING) */
519  if (!per_read_length(s, &length))
520  return FALSE;
521 
522  if (!gcc_read_server_data_blocks(s, mcs, length))
523  {
524  WLog_ERR(TAG, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed");
525  return FALSE;
526  }
527 
528  return TRUE;
529 }
530 
531 BOOL gcc_write_conference_create_response(wStream* s, wStream* userData)
532 {
533  WINPR_ASSERT(s);
534  WINPR_ASSERT(userData);
535  /* ConnectData */
536  if (!per_write_choice(s, 0))
537  return FALSE;
538  if (!per_write_object_identifier(s, t124_02_98_oid))
539  return FALSE;
540  /* ConnectData::connectPDU (OCTET_STRING) */
541  /* This length MUST be ignored by the client according to [MS-RDPBCGR] */
542  if (!per_write_length(s, 0x2A))
543  return FALSE;
544  /* ConnectGCCPDU */
545  if (!per_write_choice(s, 0x14))
546  return FALSE;
547  /* ConferenceCreateResponse::nodeID (UserID) */
548  if (!per_write_integer16(s, 0x79F3, 1001))
549  return FALSE;
550  /* ConferenceCreateResponse::tag (INTEGER) */
551  if (!per_write_integer(s, 1))
552  return FALSE;
553  /* ConferenceCreateResponse::result (ENUMERATED) */
554  if (!per_write_enumerated(s, 0, MCS_Result_enum_length))
555  return FALSE;
556  /* number of UserData sets */
557  if (!per_write_number_of_sets(s, 1))
558  return FALSE;
559  /* UserData::value present + select h221NonStandard (1) */
560  if (!per_write_choice(s, 0xC0))
561  return FALSE;
562  /* h221NonStandard */
563  if (!per_write_octet_string(s, h221_sc_key, 4,
564  4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
565  return FALSE;
566  /* userData (OCTET_STRING) */
567  const size_t pos = Stream_GetPosition(userData);
568  WINPR_ASSERT(pos <= UINT16_MAX);
569  return per_write_octet_string(s, Stream_Buffer(userData), (UINT16)pos,
570  0); /* array of server data blocks */
571 }
572 
573 static BOOL gcc_read_client_unused1_data(wStream* s)
574 {
575  return Stream_SafeSeek(s, 2);
576 }
577 
578 BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, UINT16 length)
579 {
580  WINPR_ASSERT(s);
581  WINPR_ASSERT(mcs);
582 
583  BOOL gotMultitransport = FALSE;
584 
585  while (length > 0)
586  {
587  wStream sbuffer = { 0 };
588  UINT16 type = 0;
589  UINT16 blockLength = 0;
590 
591  if (!gcc_read_user_data_header(s, &type, &blockLength))
592  return FALSE;
593 
594  if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(blockLength - 4)))
595  return FALSE;
596 
597  wStream* sub = Stream_StaticConstInit(&sbuffer, Stream_Pointer(s), blockLength - 4);
598  WINPR_ASSERT(sub);
599 
600  Stream_Seek(s, blockLength - 4);
601 
602  switch (type)
603  {
604  case CS_CORE:
605  if (!gcc_read_client_core_data(sub, mcs))
606  return FALSE;
607 
608  break;
609 
610  case CS_SECURITY:
611  if (!gcc_read_client_security_data(sub, mcs))
612  return FALSE;
613 
614  break;
615 
616  case CS_NET:
617  if (!gcc_read_client_network_data(sub, mcs))
618  return FALSE;
619 
620  break;
621 
622  case CS_CLUSTER:
623  if (!gcc_read_client_cluster_data(sub, mcs))
624  return FALSE;
625 
626  break;
627 
628  case CS_MONITOR:
629  if (!gcc_read_client_monitor_data(sub, mcs))
630  return FALSE;
631 
632  break;
633 
634  case CS_MCS_MSGCHANNEL:
635  if (!gcc_read_client_message_channel_data(sub, mcs))
636  return FALSE;
637 
638  break;
639 
640  case CS_MONITOR_EX:
641  if (!gcc_read_client_monitor_extended_data(sub, mcs))
642  return FALSE;
643 
644  break;
645 
646  case CS_UNUSED1:
647  if (!gcc_read_client_unused1_data(sub))
648  return FALSE;
649 
650  break;
651 
652  case 0xC009:
653  case CS_MULTITRANSPORT:
654  gotMultitransport = TRUE;
655  if (!gcc_read_client_multitransport_channel_data(sub, mcs))
656  return FALSE;
657 
658  break;
659 
660  default:
661  WLog_ERR(TAG, "Unknown GCC client data block: 0x%04" PRIX16 "", type);
662  winpr_HexDump(TAG, WLOG_TRACE, Stream_Pointer(sub), Stream_GetRemainingLength(sub));
663  break;
664  }
665 
666  const size_t rem = Stream_GetRemainingLength(sub);
667  if (rem > 0)
668  {
669  char buffer[128] = { 0 };
670  const size_t total = Stream_Length(sub);
671  WLog_ERR(TAG,
672  "Error parsing GCC client data block %s: Actual Offset: %" PRIuz
673  " Expected Offset: %" PRIuz,
674  gcc_block_type_string(type, buffer, sizeof(buffer)), total - rem, total);
675  }
676 
677  if (blockLength > length)
678  {
679  char buffer[128] = { 0 };
680  WLog_ERR(TAG,
681  "Error parsing GCC client data block %s: got blockLength 0x%04" PRIx16
682  ", but only 0x%04" PRIx16 "remaining",
683  gcc_block_type_string(type, buffer, sizeof(buffer)), blockLength, length);
684  length = 0;
685  }
686  else
687  length -= blockLength;
688  }
689 
690  if (!gotMultitransport)
691  {
692  rdpSettings* settings = mcs_get_settings(mcs);
693  if (!freerdp_settings_set_bool(settings, FreeRDP_SupportMultitransport, FALSE))
694  return FALSE;
695  if (!freerdp_settings_set_uint32(settings, FreeRDP_MultitransportFlags, 0))
696  return FALSE;
697  }
698  return TRUE;
699 }
700 
701 BOOL gcc_write_client_data_blocks(wStream* s, const rdpMcs* mcs)
702 {
703  const rdpSettings* settings = mcs_get_const_settings(mcs);
704 
705  WINPR_ASSERT(s);
706  WINPR_ASSERT(settings);
707 
708  if (!gcc_write_client_core_data(s, mcs) || !gcc_write_client_cluster_data(s, mcs) ||
709  !gcc_write_client_security_data(s, mcs) || !gcc_write_client_network_data(s, mcs))
710  return FALSE;
711 
712  /* extended client data supported */
713 
714  if (settings->NegotiationFlags & EXTENDED_CLIENT_DATA_SUPPORTED)
715  {
716  if (settings->UseMultimon && !settings->SpanMonitors)
717  {
718  if (!gcc_write_client_monitor_data(s, mcs) ||
719  !gcc_write_client_monitor_extended_data(s, mcs))
720  return FALSE;
721  }
722 
723  if (!gcc_write_client_message_channel_data(s, mcs) ||
724  !gcc_write_client_multitransport_channel_data(s, mcs))
725  return FALSE;
726  }
727  else
728  {
729  if (settings->UseMultimon && !settings->SpanMonitors)
730  {
731  WLog_ERR(TAG, "WARNING: true multi monitor support was not advertised by server!");
732 
733  if (settings->ForceMultimon)
734  {
735  WLog_ERR(TAG, "Sending multi monitor information anyway (may break connectivity!)");
736  if (!gcc_write_client_monitor_data(s, mcs) ||
737  !gcc_write_client_monitor_extended_data(s, mcs))
738  return FALSE;
739  }
740  else
741  {
742  WLog_ERR(TAG, "Use /multimon:force to force sending multi monitor information");
743  }
744  }
745  }
746  return TRUE;
747 }
748 
749 char* gcc_block_type_string(UINT16 type, char* buffer, size_t size)
750 {
751  switch (type)
752  {
753  case CS_CORE:
754  (void)_snprintf(buffer, size, "CS_CORE [0x%04" PRIx16 "]", type);
755  break;
756  case CS_SECURITY:
757  (void)_snprintf(buffer, size, "CS_SECURITY [0x%04" PRIx16 "]", type);
758  break;
759  case CS_NET:
760  (void)_snprintf(buffer, size, "CS_NET [0x%04" PRIx16 "]", type);
761  break;
762  case CS_CLUSTER:
763  (void)_snprintf(buffer, size, "CS_CLUSTER [0x%04" PRIx16 "]", type);
764  break;
765  case CS_MONITOR:
766  (void)_snprintf(buffer, size, "CS_MONITOR [0x%04" PRIx16 "]", type);
767  break;
768  case CS_MCS_MSGCHANNEL:
769  (void)_snprintf(buffer, size, "CS_MONITOR [0x%04" PRIx16 "]", type);
770  break;
771  case CS_MONITOR_EX:
772  (void)_snprintf(buffer, size, "CS_MONITOR_EX [0x%04" PRIx16 "]", type);
773  break;
774  case CS_UNUSED1:
775  (void)_snprintf(buffer, size, "CS_UNUSED1 [0x%04" PRIx16 "]", type);
776  break;
777  case CS_MULTITRANSPORT:
778  (void)_snprintf(buffer, size, "CS_MONITOR_EX [0x%04" PRIx16 "]", type);
779  break;
780  case SC_CORE:
781  (void)_snprintf(buffer, size, "SC_CORE [0x%04" PRIx16 "]", type);
782  break;
783  case SC_SECURITY:
784  (void)_snprintf(buffer, size, "SC_SECURITY [0x%04" PRIx16 "]", type);
785  break;
786  case SC_NET:
787  (void)_snprintf(buffer, size, "SC_NET [0x%04" PRIx16 "]", type);
788  break;
789  case SC_MCS_MSGCHANNEL:
790  (void)_snprintf(buffer, size, "SC_MCS_MSGCHANNEL [0x%04" PRIx16 "]", type);
791  break;
792  case SC_MULTITRANSPORT:
793  (void)_snprintf(buffer, size, "SC_MULTITRANSPORT [0x%04" PRIx16 "]", type);
794  break;
795  default:
796  (void)_snprintf(buffer, size, "UNKNOWN [0x%04" PRIx16 "]", type);
797  break;
798  }
799  return buffer;
800 }
801 
802 BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, UINT16 length)
803 {
804  UINT16 type = 0;
805  UINT16 offset = 0;
806  UINT16 blockLength = 0;
807  BYTE* holdp = NULL;
808 
809  WINPR_ASSERT(s);
810  WINPR_ASSERT(mcs);
811 
812  while (offset < length)
813  {
814  char buffer[64] = { 0 };
815  size_t rest = 0;
816  wStream subbuffer;
817  wStream* sub = NULL;
818 
819  if (!gcc_read_user_data_header(s, &type, &blockLength))
820  {
821  WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_user_data_header failed");
822  return FALSE;
823  }
824  holdp = Stream_Pointer(s);
825  sub = Stream_StaticInit(&subbuffer, holdp, blockLength - 4);
826  if (!Stream_SafeSeek(s, blockLength - 4))
827  {
828  WLog_ERR(TAG, "gcc_read_server_data_blocks: stream too short");
829  return FALSE;
830  }
831  offset += blockLength;
832 
833  switch (type)
834  {
835  case SC_CORE:
836  if (!gcc_read_server_core_data(sub, mcs))
837  {
838  WLog_ERR(TAG, "gcc_read_server_data_blocks: gcc_read_server_core_data failed");
839  return FALSE;
840  }
841 
842  break;
843 
844  case SC_SECURITY:
845  if (!gcc_read_server_security_data(sub, mcs))
846  return FALSE;
847  break;
848 
849  case SC_NET:
850  if (!gcc_read_server_network_data(sub, mcs))
851  {
852  WLog_ERR(TAG,
853  "gcc_read_server_data_blocks: gcc_read_server_network_data failed");
854  return FALSE;
855  }
856 
857  break;
858 
859  case SC_MCS_MSGCHANNEL:
860  if (!gcc_read_server_message_channel_data(sub, mcs))
861  {
862  WLog_ERR(
863  TAG,
864  "gcc_read_server_data_blocks: gcc_read_server_message_channel_data failed");
865  return FALSE;
866  }
867 
868  break;
869 
870  case SC_MULTITRANSPORT:
871  if (!gcc_read_server_multitransport_channel_data(sub, mcs))
872  {
873  WLog_ERR(TAG, "gcc_read_server_data_blocks: "
874  "gcc_read_server_multitransport_channel_data failed");
875  return FALSE;
876  }
877 
878  break;
879 
880  default:
881  WLog_ERR(TAG, "gcc_read_server_data_blocks: ignoring type=%s",
882  gcc_block_type_string(type, buffer, sizeof(buffer)));
883  winpr_HexDump(TAG, WLOG_TRACE, Stream_Pointer(sub), Stream_GetRemainingLength(sub));
884  break;
885  }
886 
887  rest = Stream_GetRemainingLength(sub);
888  if (rest > 0)
889  {
890  WLog_WARN(TAG, "gcc_read_server_data_blocks: ignoring %" PRIuz " bytes with type=%s",
891  rest, gcc_block_type_string(type, buffer, sizeof(buffer)));
892  }
893  }
894 
895  return TRUE;
896 }
897 
898 BOOL gcc_write_server_data_blocks(wStream* s, rdpMcs* mcs)
899 {
900  WINPR_ASSERT(s);
901  WINPR_ASSERT(mcs);
902 
903  if (!gcc_write_server_core_data(s, mcs) || /* serverCoreData */
904  !gcc_write_server_network_data(s, mcs) || /* serverNetworkData */
905  !gcc_write_server_security_data(s, mcs) || /* serverSecurityData */
906  !gcc_write_server_message_channel_data(s, mcs)) /* serverMessageChannelData */
907  return FALSE;
908 
909  const rdpSettings* settings = mcs_get_const_settings(mcs);
910  WINPR_ASSERT(settings);
911 
912  if (settings->SupportMultitransport && (settings->MultitransportFlags != 0))
913  /* serverMultitransportChannelData */
914  return gcc_write_server_multitransport_channel_data(s, mcs);
915 
916  return TRUE;
917 }
918 
919 BOOL gcc_read_user_data_header(wStream* s, UINT16* type, UINT16* length)
920 {
921  WINPR_ASSERT(s);
922  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
923  return FALSE;
924 
925  Stream_Read_UINT16(s, *type); /* type */
926  Stream_Read_UINT16(s, *length); /* length */
927 
928  if ((*length < 4) || (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(*length - 4))))
929  return FALSE;
930 
931  return TRUE;
932 }
933 
945 BOOL gcc_write_user_data_header(wStream* s, UINT16 type, UINT16 length)
946 {
947 
948  WINPR_ASSERT(s);
949  if (!Stream_EnsureRemainingCapacity(s, 4 + length))
950  return FALSE;
951  Stream_Write_UINT16(s, type); /* type */
952  Stream_Write_UINT16(s, length); /* length */
953  return TRUE;
954 }
955 
956 static UINT32 filterAndLogEarlyServerCapabilityFlags(UINT32 flags)
957 {
958  const UINT32 mask =
959  (RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED |
960  RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED);
961  const UINT32 filtered = flags & mask;
962  const UINT32 unknown = flags & (~mask);
963  if (unknown != 0)
964  {
965  char buffer[256] = { 0 };
966  WLog_WARN(TAG,
967  "TS_UD_SC_CORE::EarlyCapabilityFlags [0x%08" PRIx32 " & 0x%08" PRIx32
968  " --> 0x%08" PRIx32 "] filtering %s, feature not implemented",
969  flags, ~mask, unknown,
970  rdp_early_server_caps_string(unknown, buffer, sizeof(buffer)));
971  }
972  return filtered;
973 }
974 
975 static UINT32 earlyServerCapsFromSettings(const rdpSettings* settings)
976 {
977  UINT32 EarlyCapabilityFlags = 0;
978 
979  if (settings->SupportEdgeActionV1)
980  EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1;
981  if (settings->SupportDynamicTimeZone)
982  EarlyCapabilityFlags |= RNS_UD_SC_DYNAMIC_DST_SUPPORTED;
983  if (settings->SupportEdgeActionV2)
984  EarlyCapabilityFlags |= RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2;
985  if (settings->SupportSkipChannelJoin)
986  EarlyCapabilityFlags |= RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED;
987 
988  return filterAndLogEarlyServerCapabilityFlags(EarlyCapabilityFlags);
989 }
990 
991 static UINT16 filterAndLogEarlyClientCapabilityFlags(UINT32 flags)
992 {
993  const UINT32 mask =
994  (RNS_UD_CS_SUPPORT_ERRINFO_PDU | RNS_UD_CS_WANT_32BPP_SESSION |
995  RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS |
996  RNS_UD_CS_RELATIVE_MOUSE_INPUT | RNS_UD_CS_VALID_CONNECTION_TYPE |
997  RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU | RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT |
998  RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE |
999  RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN);
1000  const UINT32 filtered = flags & mask;
1001  const UINT32 unknown = flags & ~mask;
1002  if (unknown != 0)
1003  {
1004  char buffer[256] = { 0 };
1005  WLog_WARN(TAG,
1006  "(TS_UD_CS_CORE)::EarlyCapabilityFlags [0x%08" PRIx32 " & 0x%08" PRIx32
1007  " --> 0x%08" PRIx32 "] filtering %s, feature not implemented",
1008  flags, ~mask, unknown,
1009  rdp_early_client_caps_string(unknown, buffer, sizeof(buffer)));
1010  }
1011 
1012  WINPR_ASSERT(filtered <= UINT16_MAX);
1013  return (UINT16)filtered;
1014 }
1015 
1016 static UINT16 earlyClientCapsFromSettings(const rdpSettings* settings)
1017 {
1018  UINT32 earlyCapabilityFlags = 0;
1019 
1020  WINPR_ASSERT(settings);
1021  if (settings->SupportErrorInfoPdu)
1022  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_ERRINFO_PDU;
1023 
1024  if (freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth) == 32)
1025  earlyCapabilityFlags |= RNS_UD_CS_WANT_32BPP_SESSION;
1026 
1027  if (settings->SupportStatusInfoPdu)
1028  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_STATUSINFO_PDU;
1029 
1030  if (settings->ConnectionType)
1031  earlyCapabilityFlags |= RNS_UD_CS_VALID_CONNECTION_TYPE;
1032 
1033  if (settings->SupportMonitorLayoutPdu)
1034  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU;
1035 
1036  if (freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect))
1037  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT;
1038 
1039  if (settings->SupportGraphicsPipeline)
1040  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL;
1041 
1042  if (settings->SupportDynamicTimeZone)
1043  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE;
1044 
1045  if (settings->SupportHeartbeatPdu)
1046  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_HEARTBEAT_PDU;
1047 
1048  if (settings->SupportAsymetricKeys)
1049  earlyCapabilityFlags |= RNS_UD_CS_STRONG_ASYMMETRIC_KEYS;
1050 
1051  if (settings->HasRelativeMouseEvent)
1052  earlyCapabilityFlags |= RNS_UD_CS_RELATIVE_MOUSE_INPUT;
1053 
1054  if (settings->SupportSkipChannelJoin)
1055  earlyCapabilityFlags |= RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN;
1056 
1057  return filterAndLogEarlyClientCapabilityFlags(earlyCapabilityFlags);
1058 }
1059 
1060 static BOOL updateEarlyClientCaps(rdpSettings* settings, UINT32 earlyCapabilityFlags,
1061  UINT32 connectionType)
1062 {
1063  WINPR_ASSERT(settings);
1064 
1065  if (settings->SupportErrorInfoPdu)
1066  settings->SupportErrorInfoPdu =
1067  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_ERRINFO_PDU) ? TRUE : FALSE;
1068 
1069  /* RNS_UD_CS_WANT_32BPP_SESSION is already handled in gcc_read_client_core_data:
1070  *
1071  * it is evaluated in combination with highColorDepth and the server side
1072  * settings to determine the session color depth to use.
1073  */
1074 
1075  if (settings->SupportStatusInfoPdu)
1076  settings->SupportStatusInfoPdu =
1077  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_STATUSINFO_PDU) ? TRUE : FALSE;
1078 
1079  if (settings->SupportAsymetricKeys)
1080  settings->SupportAsymetricKeys =
1081  (earlyCapabilityFlags & RNS_UD_CS_STRONG_ASYMMETRIC_KEYS) ? TRUE : FALSE;
1082 
1083  if (settings->HasRelativeMouseEvent)
1084  settings->HasRelativeMouseEvent =
1085  (earlyCapabilityFlags & RNS_UD_CS_RELATIVE_MOUSE_INPUT) ? TRUE : FALSE;
1086 
1087  if (settings->NetworkAutoDetect)
1088  settings->NetworkAutoDetect =
1089  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT) ? TRUE : FALSE;
1090 
1091  if (settings->SupportSkipChannelJoin)
1092  settings->SupportSkipChannelJoin =
1093  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN) ? TRUE : FALSE;
1094 
1095  if (settings->SupportMonitorLayoutPdu)
1096  settings->SupportMonitorLayoutPdu =
1097  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) ? TRUE : FALSE;
1098 
1099  if (settings->SupportHeartbeatPdu)
1100  settings->SupportHeartbeatPdu =
1101  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_HEARTBEAT_PDU) ? TRUE : FALSE;
1102 
1103  if (settings->SupportGraphicsPipeline)
1104  settings->SupportGraphicsPipeline =
1105  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL) ? TRUE : FALSE;
1106 
1107  if (settings->SupportDynamicTimeZone)
1108  settings->SupportDynamicTimeZone =
1109  (earlyCapabilityFlags & RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE) ? TRUE : FALSE;
1110 
1111  if ((earlyCapabilityFlags & RNS_UD_CS_VALID_CONNECTION_TYPE) == 0)
1112  connectionType = 0;
1113  settings->ConnectionType = connectionType;
1114 
1115  filterAndLogEarlyClientCapabilityFlags(earlyCapabilityFlags);
1116  return TRUE;
1117 }
1118 
1119 static BOOL updateEarlyServerCaps(rdpSettings* settings, UINT32 earlyCapabilityFlags,
1120  UINT32 connectionType)
1121 {
1122  WINPR_ASSERT(settings);
1123 
1124  settings->SupportEdgeActionV1 =
1125  settings->SupportEdgeActionV1 &&
1126  (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1)
1127  ? TRUE
1128  : FALSE;
1129  settings->SupportDynamicTimeZone =
1130  settings->SupportDynamicTimeZone && (earlyCapabilityFlags & RNS_UD_SC_DYNAMIC_DST_SUPPORTED)
1131  ? TRUE
1132  : FALSE;
1133  settings->SupportEdgeActionV2 =
1134  settings->SupportEdgeActionV2 &&
1135  (earlyCapabilityFlags & RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2)
1136  ? TRUE
1137  : FALSE;
1138  settings->SupportSkipChannelJoin =
1139  settings->SupportSkipChannelJoin &&
1140  (earlyCapabilityFlags & RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED)
1141  ? TRUE
1142  : FALSE;
1143 
1144  filterAndLogEarlyServerCapabilityFlags(earlyCapabilityFlags);
1145  return TRUE;
1146 }
1147 
1157 BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs)
1158 {
1159  char buffer[2048] = { 0 };
1160  char strbuffer[130] = { 0 };
1161  UINT32 version = 0;
1162  BYTE connectionType = 0;
1163  UINT32 clientColorDepth = 0;
1164  UINT16 colorDepth = 0;
1165  UINT16 postBeta2ColorDepth = 0;
1166  UINT16 highColorDepth = 0;
1167  UINT32 serverSelectedProtocol = 0;
1168  rdpSettings* settings = mcs_get_settings(mcs);
1169 
1170  WINPR_ASSERT(s);
1171  WINPR_ASSERT(settings);
1172 
1173  size_t blockLength = Stream_GetRemainingLength(s);
1174  /* Length of all required fields, until imeFileName */
1175  if (blockLength < 128)
1176  return FALSE;
1177 
1178  Stream_Read_UINT32(s, version); /* version (4 bytes) */
1179  settings->RdpVersion = rdp_version_common(version, settings->RdpVersion);
1180  Stream_Read_UINT16(s, settings->DesktopWidth); /* DesktopWidth (2 bytes) */
1181  Stream_Read_UINT16(s, settings->DesktopHeight); /* DesktopHeight (2 bytes) */
1182  Stream_Read_UINT16(s, colorDepth); /* ColorDepth (2 bytes) */
1183  Stream_Seek_UINT16(s); /* SASSequence (Secure Access Sequence) (2 bytes) */
1184  Stream_Read_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout (4 bytes) */
1185  Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */
1186 
1187  /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
1188  if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 32 / sizeof(WCHAR), strbuffer,
1189  ARRAYSIZE(strbuffer)) < 0)
1190  {
1191  WLog_ERR(TAG, "failed to convert client host name");
1192  return FALSE;
1193  }
1194 
1195  if (!freerdp_settings_set_string(settings, FreeRDP_ClientHostname, strbuffer))
1196  return FALSE;
1197 
1198  Stream_Read_UINT32(s, settings->KeyboardType); /* KeyboardType (4 bytes) */
1199  Stream_Read_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType (4 bytes) */
1200  Stream_Read_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey (4 bytes) */
1201  Stream_Seek(s, 64); /* imeFileName (64 bytes) */
1202  blockLength -= 128;
1203 
1211  do
1212  {
1213  UINT16 clientProductIdLen = 0;
1214  if (blockLength < 2)
1215  break;
1216 
1217  Stream_Read_UINT16(s, postBeta2ColorDepth); /* postBeta2ColorDepth (2 bytes) */
1218  blockLength -= 2;
1219 
1220  if (blockLength < 2)
1221  break;
1222 
1223  Stream_Read_UINT16(s, clientProductIdLen); /* clientProductID (2 bytes) */
1224  blockLength -= 2;
1225 
1226  if (blockLength < 4)
1227  break;
1228 
1229  Stream_Seek_UINT32(s); /* serialNumber (4 bytes) */
1230  blockLength -= 4;
1231 
1232  if (blockLength < 2)
1233  break;
1234 
1235  Stream_Read_UINT16(s, highColorDepth); /* highColorDepth (2 bytes) */
1236  blockLength -= 2;
1237 
1238  if (blockLength < 2)
1239  break;
1240 
1241  Stream_Read_UINT16(s, settings->SupportedColorDepths); /* supportedColorDepths (2 bytes) */
1242  blockLength -= 2;
1243 
1244  if (blockLength < 2)
1245  break;
1246 
1247  Stream_Read_UINT16(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags (2 bytes) */
1248  blockLength -= 2;
1249 
1250  /* clientDigProductId (64 bytes): Contains a value that uniquely identifies the client */
1251 
1252  if (blockLength < 64)
1253  break;
1254 
1255  if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, 64 / sizeof(WCHAR), strbuffer,
1256  ARRAYSIZE(strbuffer)) < 0)
1257  {
1258  WLog_ERR(TAG, "failed to convert the client product identifier");
1259  return FALSE;
1260  }
1261 
1262  if (!freerdp_settings_set_string(settings, FreeRDP_ClientProductId, strbuffer))
1263  return FALSE;
1264  blockLength -= 64;
1265 
1266  if (blockLength < 1)
1267  break;
1268 
1269  Stream_Read_UINT8(s, connectionType); /* connectionType (1 byte) */
1270  blockLength -= 1;
1271 
1272  if (blockLength < 1)
1273  break;
1274 
1275  Stream_Seek_UINT8(s); /* pad1octet (1 byte) */
1276  blockLength -= 1;
1277 
1278  if (blockLength < 4)
1279  break;
1280 
1281  Stream_Read_UINT32(s, serverSelectedProtocol); /* serverSelectedProtocol (4 bytes) */
1282  blockLength -= 4;
1283 
1284  if (blockLength < 4)
1285  break;
1286 
1287  Stream_Read_UINT32(s, settings->DesktopPhysicalWidth); /* desktopPhysicalWidth (4 bytes) */
1288  blockLength -= 4;
1289 
1290  if (blockLength < 4)
1291  break;
1292 
1293  Stream_Read_UINT32(s,
1294  settings->DesktopPhysicalHeight); /* desktopPhysicalHeight (4 bytes) */
1295  blockLength -= 4;
1296 
1297  if (blockLength < 2)
1298  break;
1299 
1300  Stream_Read_UINT16(s, settings->DesktopOrientation); /* desktopOrientation (2 bytes) */
1301  blockLength -= 2;
1302 
1303  if (blockLength < 4)
1304  break;
1305 
1306  Stream_Read_UINT32(s, settings->DesktopScaleFactor); /* desktopScaleFactor (4 bytes) */
1307  blockLength -= 4;
1308 
1309  if (blockLength < 4)
1310  break;
1311 
1312  Stream_Read_UINT32(s, settings->DeviceScaleFactor); /* deviceScaleFactor (4 bytes) */
1313 
1314  if (freerdp_settings_get_bool(settings, FreeRDP_TransportDumpReplay))
1315  settings->SelectedProtocol = serverSelectedProtocol;
1316  else if (settings->SelectedProtocol != serverSelectedProtocol)
1317  return FALSE;
1318  } while (0);
1319 
1320  if (highColorDepth > 0)
1321  {
1322  if (settings->EarlyCapabilityFlags & RNS_UD_CS_WANT_32BPP_SESSION)
1323  clientColorDepth = 32;
1324  else
1325  clientColorDepth = highColorDepth;
1326  }
1327  else if (postBeta2ColorDepth > 0)
1328  {
1329  switch (postBeta2ColorDepth)
1330  {
1331  case RNS_UD_COLOR_4BPP:
1332  clientColorDepth = 4;
1333  break;
1334 
1335  case RNS_UD_COLOR_8BPP:
1336  clientColorDepth = 8;
1337  break;
1338 
1339  case RNS_UD_COLOR_16BPP_555:
1340  clientColorDepth = 15;
1341  break;
1342 
1343  case RNS_UD_COLOR_16BPP_565:
1344  clientColorDepth = 16;
1345  break;
1346 
1347  case RNS_UD_COLOR_24BPP:
1348  clientColorDepth = 24;
1349  break;
1350 
1351  default:
1352  return FALSE;
1353  }
1354  }
1355  else
1356  {
1357  switch (colorDepth)
1358  {
1359  case RNS_UD_COLOR_4BPP:
1360  clientColorDepth = 4;
1361  break;
1362 
1363  case RNS_UD_COLOR_8BPP:
1364  clientColorDepth = 8;
1365  break;
1366 
1367  default:
1368  return FALSE;
1369  }
1370  }
1371 
1372  /*
1373  * If we are in server mode, accept client's color depth only if
1374  * it is smaller than ours. This is what Windows server does.
1375  */
1376  if ((clientColorDepth < freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth)) ||
1377  !settings->ServerMode)
1378  {
1379  if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, clientColorDepth))
1380  return FALSE;
1381  }
1382 
1383  WLog_DBG(TAG, "Received EarlyCapabilityFlags=%s",
1384  rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer, sizeof(buffer)));
1385 
1386  return updateEarlyClientCaps(settings, settings->EarlyCapabilityFlags, connectionType);
1387 }
1388 
1398 BOOL gcc_write_client_core_data(wStream* s, const rdpMcs* mcs)
1399 {
1400  char buffer[2048] = { 0 };
1401  char dbuffer[2048] = { 0 };
1402  BYTE connectionType = 0;
1403  HIGH_COLOR_DEPTH highColorDepth = HIGH_COLOR_4BPP;
1404 
1405  UINT16 earlyCapabilityFlags = 0;
1406  const rdpSettings* settings = mcs_get_const_settings(mcs);
1407 
1408  WINPR_ASSERT(s);
1409  WINPR_ASSERT(settings);
1410 
1411  const UINT16 SupportedColorDepths =
1412  freerdp_settings_get_uint16(settings, FreeRDP_SupportedColorDepths);
1413  const UINT32 ColorDepth = freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
1414 
1415  if (!gcc_write_user_data_header(s, CS_CORE, 234))
1416  return FALSE;
1417 
1418  Stream_Write_UINT32(s, settings->RdpVersion); /* Version */
1419  Stream_Write_UINT16(
1420  s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopWidth)); /* DesktopWidth */
1421  Stream_Write_UINT16(
1422  s, WINPR_ASSERTING_INT_CAST(uint16_t, settings->DesktopHeight)); /* DesktopHeight */
1423  Stream_Write_UINT16(s,
1424  RNS_UD_COLOR_8BPP); /* ColorDepth, ignored because of postBeta2ColorDepth */
1425  Stream_Write_UINT16(s, RNS_UD_SAS_DEL); /* SASSequence (Secure Access Sequence) */
1426  Stream_Write_UINT32(s, settings->KeyboardLayout); /* KeyboardLayout */
1427  Stream_Write_UINT32(s, settings->ClientBuild); /* ClientBuild */
1428 
1429  if (!Stream_EnsureRemainingCapacity(s, 32 + 12 + 64 + 8))
1430  return FALSE;
1431 
1432  /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
1433  size_t clientNameLength = 0;
1434  WCHAR* clientName = ConvertUtf8ToWCharAlloc(settings->ClientHostname, &clientNameLength);
1435  if (clientNameLength >= 16)
1436  {
1437  clientNameLength = 16;
1438  clientName[clientNameLength - 1] = 0;
1439  }
1440 
1441  Stream_Write(s, clientName, (clientNameLength * 2));
1442  Stream_Zero(s, 32 - (clientNameLength * 2));
1443  free(clientName);
1444  Stream_Write_UINT32(s, settings->KeyboardType); /* KeyboardType */
1445  Stream_Write_UINT32(s, settings->KeyboardSubType); /* KeyboardSubType */
1446  Stream_Write_UINT32(s, settings->KeyboardFunctionKey); /* KeyboardFunctionKey */
1447  Stream_Zero(s, 64); /* imeFileName */
1448  Stream_Write_UINT16(s, RNS_UD_COLOR_8BPP); /* postBeta2ColorDepth */
1449  Stream_Write_UINT16(s, 1); /* clientProductID */
1450  Stream_Write_UINT32(s, 0); /* serialNumber (should be initialized to 0) */
1451  highColorDepth = ColorDepthToHighColor(ColorDepth);
1452  earlyCapabilityFlags = earlyClientCapsFromSettings(settings);
1453 
1454  WINPR_ASSERT(settings->ConnectionType <= UINT8_MAX);
1455  connectionType = (UINT8)settings->ConnectionType;
1456 
1457  if (!Stream_EnsureRemainingCapacity(s, 6))
1458  return FALSE;
1459 
1460  WLog_DBG(TAG, "Sending highColorDepth=%s, supportedColorDepths=%s, earlyCapabilityFlags=%s",
1461  HighColorToString(highColorDepth),
1462  freerdp_supported_color_depths_string(SupportedColorDepths, dbuffer, sizeof(dbuffer)),
1463  rdp_early_client_caps_string(earlyCapabilityFlags, buffer, sizeof(buffer)));
1464  Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, highColorDepth)); /* highColorDepth */
1465  Stream_Write_UINT16(s, SupportedColorDepths); /* supportedColorDepths */
1466  Stream_Write_UINT16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
1467 
1468  if (!Stream_EnsureRemainingCapacity(s, 64 + 24))
1469  return FALSE;
1470 
1471  /* clientDigProductId (64 bytes, null-terminated unicode, truncated to 31 characters) */
1472  size_t clientDigProductIdLength = 0;
1473  WCHAR* clientDigProductId =
1474  ConvertUtf8ToWCharAlloc(settings->ClientProductId, &clientDigProductIdLength);
1475  if (clientDigProductIdLength >= 32)
1476  {
1477  clientDigProductIdLength = 32;
1478  clientDigProductId[clientDigProductIdLength - 1] = 0;
1479  }
1480 
1481  Stream_Write(s, clientDigProductId, (clientDigProductIdLength * 2));
1482  Stream_Zero(s, 64 - (clientDigProductIdLength * 2));
1483  free(clientDigProductId);
1484  Stream_Write_UINT8(s, connectionType); /* connectionType */
1485  Stream_Write_UINT8(s, 0); /* pad1octet */
1486  Stream_Write_UINT32(s, settings->SelectedProtocol); /* serverSelectedProtocol */
1487  Stream_Write_UINT32(s, settings->DesktopPhysicalWidth); /* desktopPhysicalWidth */
1488  Stream_Write_UINT32(s, settings->DesktopPhysicalHeight); /* desktopPhysicalHeight */
1489  Stream_Write_UINT16(s, settings->DesktopOrientation); /* desktopOrientation */
1490  Stream_Write_UINT32(s, settings->DesktopScaleFactor); /* desktopScaleFactor */
1491  Stream_Write_UINT32(s, settings->DeviceScaleFactor); /* deviceScaleFactor */
1492  return TRUE;
1493 }
1494 
1495 BOOL gcc_read_server_core_data(wStream* s, rdpMcs* mcs)
1496 {
1497  UINT32 serverVersion = 0;
1498  rdpSettings* settings = mcs_get_settings(mcs);
1499 
1500  WINPR_ASSERT(s);
1501  WINPR_ASSERT(settings);
1502 
1503  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1504  return FALSE;
1505 
1506  Stream_Read_UINT32(s, serverVersion); /* version */
1507  settings->RdpVersion = rdp_version_common(serverVersion, settings->RdpVersion);
1508 
1509  if (Stream_GetRemainingLength(s) >= 4)
1510  {
1511  Stream_Read_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols */
1512  }
1513 
1514  if (Stream_GetRemainingLength(s) >= 4)
1515  {
1516  char buffer[2048] = { 0 };
1517 
1518  Stream_Read_UINT32(s, settings->EarlyCapabilityFlags); /* earlyCapabilityFlags */
1519  WLog_DBG(
1520  TAG, "Received EarlyCapabilityFlags=%s",
1521  rdp_early_client_caps_string(settings->EarlyCapabilityFlags, buffer, sizeof(buffer)));
1522  }
1523 
1524  return updateEarlyServerCaps(settings, settings->EarlyCapabilityFlags,
1525  settings->ConnectionType);
1526 }
1527 
1528 /* TODO: This function modifies rdpMcs
1529  * TODO: Split this out of this function
1530  */
1531 BOOL gcc_write_server_core_data(wStream* s, rdpMcs* mcs)
1532 {
1533  const rdpSettings* settings = mcs_get_const_settings(mcs);
1534 
1535  WINPR_ASSERT(s);
1536  WINPR_ASSERT(settings);
1537 
1538  if (!gcc_write_user_data_header(s, SC_CORE, 16))
1539  return FALSE;
1540 
1541  const UINT32 EarlyCapabilityFlags = earlyServerCapsFromSettings(settings);
1542  Stream_Write_UINT32(s, settings->RdpVersion); /* version (4 bytes) */
1543  Stream_Write_UINT32(s, settings->RequestedProtocols); /* clientRequestedProtocols (4 bytes) */
1544  Stream_Write_UINT32(s, EarlyCapabilityFlags); /* earlyCapabilityFlags (4 bytes) */
1545  return TRUE;
1546 }
1547 
1557 BOOL gcc_read_client_security_data(wStream* s, rdpMcs* mcs)
1558 {
1559  rdpSettings* settings = mcs_get_settings(mcs);
1560 
1561  WINPR_ASSERT(s);
1562  WINPR_ASSERT(settings);
1563 
1564  const size_t blockLength = Stream_GetRemainingLength(s);
1565  if (blockLength < 8)
1566  return FALSE;
1567 
1568  if (settings->UseRdpSecurityLayer)
1569  {
1570  Stream_Read_UINT32(s, settings->EncryptionMethods); /* encryptionMethods */
1571 
1572  if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1573  Stream_Read_UINT32(s, settings->EncryptionMethods); /* extEncryptionMethods */
1574  else
1575  Stream_Seek(s, 4);
1576  }
1577  else
1578  {
1579  Stream_Seek(s, 8);
1580  }
1581 
1582  return TRUE;
1583 }
1584 
1594 BOOL gcc_write_client_security_data(wStream* s, const rdpMcs* mcs)
1595 {
1596  const rdpSettings* settings = mcs_get_const_settings(mcs);
1597 
1598  WINPR_ASSERT(s);
1599  WINPR_ASSERT(settings);
1600 
1601  if (!gcc_write_user_data_header(s, CS_SECURITY, 12))
1602  return FALSE;
1603 
1604  if (settings->UseRdpSecurityLayer)
1605  {
1606  Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethods */
1607  Stream_Write_UINT32(s, 0); /* extEncryptionMethods */
1608  }
1609  else
1610  {
1611  /* French locale, disable encryption */
1612  Stream_Write_UINT32(s, 0); /* encryptionMethods */
1613  Stream_Write_UINT32(s, settings->EncryptionMethods); /* extEncryptionMethods */
1614  }
1615  return TRUE;
1616 }
1617 
1618 BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs)
1619 {
1620  const BYTE* data = NULL;
1621  UINT32 length = 0;
1622  BOOL validCryptoConfig = FALSE;
1623  UINT32 EncryptionMethod = 0;
1624  UINT32 EncryptionLevel = 0;
1625  rdpSettings* settings = mcs_get_settings(mcs);
1626 
1627  WINPR_ASSERT(s);
1628  WINPR_ASSERT(settings);
1629 
1630  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1631  return FALSE;
1632 
1633  Stream_Read_UINT32(s, EncryptionMethod); /* encryptionMethod */
1634  Stream_Read_UINT32(s, EncryptionLevel); /* encryptionLevel */
1635 
1636  /* Only accept valid/known encryption methods */
1637  switch (EncryptionMethod)
1638  {
1639  case ENCRYPTION_METHOD_NONE:
1640  WLog_DBG(TAG, "Server rdp encryption method: NONE");
1641  break;
1642 
1643  case ENCRYPTION_METHOD_40BIT:
1644  WLog_DBG(TAG, "Server rdp encryption method: 40BIT");
1645  break;
1646 
1647  case ENCRYPTION_METHOD_56BIT:
1648  WLog_DBG(TAG, "Server rdp encryption method: 56BIT");
1649  break;
1650 
1651  case ENCRYPTION_METHOD_128BIT:
1652  WLog_DBG(TAG, "Server rdp encryption method: 128BIT");
1653  break;
1654 
1655  case ENCRYPTION_METHOD_FIPS:
1656  WLog_DBG(TAG, "Server rdp encryption method: FIPS");
1657  break;
1658 
1659  default:
1660  WLog_ERR(TAG, "Received unknown encryption method %08" PRIX32 "", EncryptionMethod);
1661  return FALSE;
1662  }
1663 
1664  if (settings->UseRdpSecurityLayer && !(settings->EncryptionMethods & EncryptionMethod))
1665  {
1666  WLog_WARN(TAG, "Server uses non-advertised encryption method 0x%08" PRIX32 "",
1667  EncryptionMethod);
1668  /* FIXME: Should we return FALSE; in this case ?? */
1669  }
1670 
1671  settings->EncryptionMethods = EncryptionMethod;
1672  settings->EncryptionLevel = EncryptionLevel;
1673  /* Verify encryption level/method combinations according to MS-RDPBCGR Section 5.3.2 */
1674  switch (settings->EncryptionLevel)
1675  {
1676  case ENCRYPTION_LEVEL_NONE:
1677  if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1678  {
1679  validCryptoConfig = TRUE;
1680  }
1681 
1682  break;
1683 
1684  case ENCRYPTION_LEVEL_FIPS:
1685  if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1686  {
1687  validCryptoConfig = TRUE;
1688  }
1689 
1690  break;
1691 
1692  case ENCRYPTION_LEVEL_LOW:
1693  case ENCRYPTION_LEVEL_HIGH:
1694  case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE:
1695  if (settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT ||
1696  settings->EncryptionMethods == ENCRYPTION_METHOD_56BIT ||
1697  settings->EncryptionMethods == ENCRYPTION_METHOD_128BIT ||
1698  settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1699  {
1700  validCryptoConfig = TRUE;
1701  }
1702 
1703  break;
1704 
1705  default:
1706  WLog_ERR(TAG, "Received unknown encryption level 0x%08" PRIX32 "",
1707  settings->EncryptionLevel);
1708  }
1709 
1710  if (!validCryptoConfig)
1711  {
1712  WLog_ERR(TAG,
1713  "Received invalid cryptographic configuration (level=0x%08" PRIX32
1714  " method=0x%08" PRIX32 ")",
1715  settings->EncryptionLevel, settings->EncryptionMethods);
1716  return FALSE;
1717  }
1718 
1719  if (settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE)
1720  {
1721  /* serverRandomLen and serverCertLen must not be present */
1722  settings->UseRdpSecurityLayer = FALSE;
1723  return TRUE;
1724  }
1725 
1726  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
1727  return FALSE;
1728 
1729  Stream_Read_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
1730  Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */
1731 
1732  if ((settings->ServerRandomLength == 0) || (settings->ServerCertificateLength == 0))
1733  {
1734  WLog_ERR(TAG,
1735  "Invalid ServerRandom (length=%" PRIu32 ") or ServerCertificate (length=%" PRIu32
1736  ")",
1737  settings->ServerRandomLength, settings->ServerCertificateLength);
1738  return FALSE;
1739  }
1740 
1741  if (!Stream_CheckAndLogRequiredLength(TAG, s, settings->ServerRandomLength))
1742  return FALSE;
1743 
1744  /* serverRandom */
1745  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerRandom, NULL,
1746  settings->ServerRandomLength))
1747  goto fail;
1748 
1749  Stream_Read(s, settings->ServerRandom, settings->ServerRandomLength);
1750 
1751  if (!Stream_CheckAndLogRequiredLength(TAG, s, settings->ServerCertificateLength))
1752  goto fail;
1753 
1754  /* serverCertificate */
1755  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerCertificate, NULL,
1756  settings->ServerCertificateLength))
1757  goto fail;
1758 
1759  Stream_Read(s, settings->ServerCertificate, settings->ServerCertificateLength);
1760 
1761  data = settings->ServerCertificate;
1762  length = settings->ServerCertificateLength;
1763 
1764  if (!freerdp_certificate_read_server_cert(settings->RdpServerCertificate, data, length))
1765  goto fail;
1766 
1767  return TRUE;
1768 fail:
1769  free(settings->ServerRandom);
1770  free(settings->ServerCertificate);
1771  settings->ServerRandom = NULL;
1772  settings->ServerCertificate = NULL;
1773  return FALSE;
1774 }
1775 
1776 static BOOL gcc_update_server_random(rdpSettings* settings)
1777 {
1778  const size_t length = 32;
1779  WINPR_ASSERT(settings);
1780  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerRandom, NULL, length))
1781  return FALSE;
1782  BYTE* data = freerdp_settings_get_pointer_writable(settings, FreeRDP_ServerRandom);
1783  if (!data)
1784  return FALSE;
1785  winpr_RAND(data, length);
1786  return TRUE;
1787 }
1788 
1789 /* TODO: This function does manipulate data in rdpMcs
1790  * TODO: Split this out of this function
1791  */
1792 BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs)
1793 {
1794  if (!gcc_update_server_random(mcs_get_settings(mcs)))
1795  return FALSE;
1796 
1797  const rdpSettings* settings = mcs_get_const_settings(mcs);
1798 
1799  WINPR_ASSERT(s);
1800  WINPR_ASSERT(settings);
1801 
1802  const size_t posHeader = Stream_GetPosition(s);
1803  if (!gcc_write_user_data_header(s, SC_SECURITY, 12))
1804  return FALSE;
1805 
1806  Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */
1807  Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */
1808 
1809  if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1810  return TRUE;
1811 
1812  if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32) + settings->ServerRandomLength))
1813  return FALSE;
1814  Stream_Write_UINT32(s, settings->ServerRandomLength); /* serverRandomLen */
1815  const size_t posCertLen = Stream_GetPosition(s);
1816  Stream_Seek_UINT32(s); /* serverCertLen */
1817  Stream_Write(s, settings->ServerRandom, settings->ServerRandomLength);
1818 
1819  const SSIZE_T len = freerdp_certificate_write_server_cert(
1820  settings->RdpServerCertificate, CERT_TEMPORARILY_ISSUED | CERT_CHAIN_VERSION_1, s);
1821  if (len < 0)
1822  return FALSE;
1823  const size_t end = Stream_GetPosition(s);
1824 
1825  WINPR_ASSERT(end >= posHeader);
1826  const size_t diff = end - posHeader;
1827  WINPR_ASSERT(diff <= UINT16_MAX);
1828  Stream_SetPosition(s, posHeader);
1829  if (!gcc_write_user_data_header(s, SC_SECURITY, (UINT16)diff))
1830  return FALSE;
1831  Stream_SetPosition(s, posCertLen);
1832  WINPR_ASSERT(len <= UINT32_MAX);
1833  Stream_Write_UINT32(s, (UINT32)len);
1834  Stream_SetPosition(s, end);
1835  return TRUE;
1836 }
1837 
1848 BOOL gcc_read_client_network_data(wStream* s, rdpMcs* mcs)
1849 {
1850  WINPR_ASSERT(s);
1851  WINPR_ASSERT(mcs);
1852 
1853  const size_t blockLength = Stream_GetRemainingLength(s);
1854  if (blockLength < 4)
1855  return FALSE;
1856 
1857  Stream_Read_UINT32(s, mcs->channelCount); /* channelCount */
1858 
1859  if (blockLength < 4 + mcs->channelCount * 12)
1860  return FALSE;
1861 
1862  if (mcs->channelCount > CHANNEL_MAX_COUNT)
1863  return FALSE;
1864 
1865  /* channelDefArray */
1866  for (UINT32 i = 0; i < mcs->channelCount; i++)
1867  {
1874  rdpMcsChannel* channel = &mcs->channels[i];
1875  Stream_Read(s, channel->Name, CHANNEL_NAME_LEN + 1); /* name (8 bytes) */
1876 
1877  if (!memchr(channel->Name, 0, CHANNEL_NAME_LEN + 1))
1878  {
1879  WLog_ERR(
1880  TAG,
1881  "protocol violation: received a static channel name with missing null-termination");
1882  return FALSE;
1883  }
1884 
1885  Stream_Read_UINT32(s, channel->options); /* options (4 bytes) */
1886  channel->ChannelId = mcs->baseChannelId++;
1887  }
1888 
1889  return TRUE;
1890 }
1891 
1901 BOOL gcc_write_client_network_data(wStream* s, const rdpMcs* mcs)
1902 {
1903  WINPR_ASSERT(s);
1904  WINPR_ASSERT(mcs);
1905  if (mcs->channelCount > 0)
1906  {
1907  const size_t length = mcs->channelCount * 12 + 8;
1908  WINPR_ASSERT(length <= UINT16_MAX);
1909  if (!gcc_write_user_data_header(s, CS_NET, (UINT16)length))
1910  return FALSE;
1911  Stream_Write_UINT32(s, mcs->channelCount); /* channelCount */
1912 
1913  /* channelDefArray */
1914  for (UINT32 i = 0; i < mcs->channelCount; i++)
1915  {
1916  /* CHANNEL_DEF */
1917  rdpMcsChannel* channel = &mcs->channels[i];
1918  Stream_Write(s, channel->Name, CHANNEL_NAME_LEN + 1); /* name (8 bytes) */
1919  Stream_Write_UINT32(s, channel->options); /* options (4 bytes) */
1920  }
1921  }
1922  return TRUE;
1923 }
1924 
1925 BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs)
1926 {
1927  UINT16 channelId = 0;
1928  UINT16 MCSChannelId = 0;
1929  UINT16 channelCount = 0;
1930  UINT32 parsedChannelCount = 0;
1931  WINPR_ASSERT(s);
1932  WINPR_ASSERT(mcs);
1933  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
1934  return FALSE;
1935 
1936  Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
1937  Stream_Read_UINT16(s, channelCount); /* channelCount */
1938  parsedChannelCount = channelCount;
1939 
1940  if (channelCount != mcs->channelCount)
1941  {
1942  WLog_ERR(TAG, "requested %" PRIu32 " channels, got %" PRIu16 " instead", mcs->channelCount,
1943  channelCount);
1944 
1945  /* we ensure that the response is not bigger than the request */
1946 
1947  mcs->channelCount = channelCount;
1948  }
1949 
1950  if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, channelCount, 2ull))
1951  return FALSE;
1952 
1953  if (mcs->channelMaxCount < parsedChannelCount)
1954  {
1955  WLog_ERR(TAG, "requested %" PRIu32 " channels > channelMaxCount %" PRIu16,
1956  mcs->channelCount, mcs->channelMaxCount);
1957  return FALSE;
1958  }
1959 
1960  for (UINT32 i = 0; i < parsedChannelCount; i++)
1961  {
1962  rdpMcsChannel* channel = &mcs->channels[i];
1963  Stream_Read_UINT16(s, channelId); /* channelId */
1964  channel->ChannelId = channelId;
1965  }
1966 
1967  if (channelCount % 2 == 1)
1968  return Stream_SafeSeek(s, 2); /* padding */
1969 
1970  return TRUE;
1971 }
1972 
1973 BOOL gcc_write_server_network_data(wStream* s, const rdpMcs* mcs)
1974 {
1975  WINPR_ASSERT(s);
1976  WINPR_ASSERT(mcs);
1977  const size_t payloadLen = 8 + mcs->channelCount * 2 + (mcs->channelCount % 2 == 1 ? 2 : 0);
1978 
1979  WINPR_ASSERT(payloadLen <= UINT16_MAX);
1980  if (!gcc_write_user_data_header(s, SC_NET, (UINT16)payloadLen))
1981  return FALSE;
1982 
1983  Stream_Write_UINT16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
1984  Stream_Write_UINT16(s,
1985  WINPR_ASSERTING_INT_CAST(uint16_t, mcs->channelCount)); /* channelCount */
1986 
1987  for (UINT32 i = 0; i < mcs->channelCount; i++)
1988  {
1989  const rdpMcsChannel* channel = &mcs->channels[i];
1990  Stream_Write_UINT16(s, channel->ChannelId);
1991  }
1992 
1993  if (mcs->channelCount % 2 == 1)
1994  Stream_Write_UINT16(s, 0);
1995 
1996  return TRUE;
1997 }
1998 
2008 BOOL gcc_read_client_cluster_data(wStream* s, rdpMcs* mcs)
2009 {
2010  char buffer[128] = { 0 };
2011  UINT32 redirectedSessionId = 0;
2012  rdpSettings* settings = mcs_get_settings(mcs);
2013 
2014  WINPR_ASSERT(s);
2015  WINPR_ASSERT(settings);
2016 
2017  const size_t blockLength = Stream_GetRemainingLength(s);
2018  if (blockLength < 8)
2019  return FALSE;
2020 
2021  Stream_Read_UINT32(s, settings->ClusterInfoFlags); /* flags */
2022  Stream_Read_UINT32(s, redirectedSessionId); /* redirectedSessionId */
2023 
2024  WLog_VRB(TAG, "read ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2025  rdp_cluster_info_flags_to_string(settings->ClusterInfoFlags, buffer, sizeof(buffer)),
2026  redirectedSessionId);
2027  if (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID)
2028  settings->RedirectedSessionId = redirectedSessionId;
2029 
2030  settings->ConsoleSession =
2031  (settings->ClusterInfoFlags & REDIRECTED_SESSIONID_FIELD_VALID) ? TRUE : FALSE;
2032  settings->RedirectSmartCards =
2033  (settings->ClusterInfoFlags & REDIRECTED_SMARTCARD) ? TRUE : FALSE;
2034 
2035  if (blockLength > 8ULL)
2036  {
2037  if (Stream_GetRemainingLength(s) >= (blockLength - 8ULL))
2038  {
2039  /* The old Microsoft Mac RDP client can send a pad here */
2040  Stream_Seek(s, (blockLength - 8));
2041  }
2042  }
2043 
2044  return TRUE;
2045 }
2046 
2056 BOOL gcc_write_client_cluster_data(wStream* s, const rdpMcs* mcs)
2057 {
2058  char buffer[128] = { 0 };
2059  UINT32 flags = 0;
2060  const rdpSettings* settings = mcs_get_const_settings(mcs);
2061 
2062  WINPR_ASSERT(s);
2063  WINPR_ASSERT(settings);
2064 
2065  if (!gcc_write_user_data_header(s, CS_CLUSTER, 12))
2066  return FALSE;
2067  flags = settings->ClusterInfoFlags;
2068 
2069  if (settings->ConsoleSession || settings->RedirectedSessionId)
2070  flags |= REDIRECTED_SESSIONID_FIELD_VALID;
2071 
2072  if (settings->RedirectSmartCards && settings->SmartcardLogon)
2073  flags |= REDIRECTED_SMARTCARD;
2074 
2075  if (flags & REDIRECTION_SUPPORTED)
2076  {
2077  /* REDIRECTION_VERSION6 requires multitransport enabled.
2078  * if we run without that use REDIRECTION_VERSION5 */
2079  if (freerdp_settings_get_bool(settings, FreeRDP_SupportMultitransport))
2080  flags |= (REDIRECTION_VERSION6 << 2);
2081  else
2082  flags |= (REDIRECTION_VERSION5 << 2);
2083  }
2084 
2085  WLog_VRB(TAG, "write ClusterInfoFlags=%s, RedirectedSessionId=0x%08" PRIx32,
2086  rdp_cluster_info_flags_to_string(flags, buffer, sizeof(buffer)),
2087  settings->RedirectedSessionId);
2088  Stream_Write_UINT32(s, flags); /* flags */
2089  Stream_Write_UINT32(s, settings->RedirectedSessionId); /* redirectedSessionID */
2090  return TRUE;
2091 }
2092 
2102 BOOL gcc_read_client_monitor_data(wStream* s, rdpMcs* mcs)
2103 {
2104  UINT32 monitorCount = 0;
2105  rdpSettings* settings = mcs_get_settings(mcs);
2106 
2107  WINPR_ASSERT(s);
2108  WINPR_ASSERT(settings);
2109 
2110  const size_t blockLength = Stream_GetRemainingLength(s);
2111  if (blockLength < 8)
2112  return FALSE;
2113 
2114  Stream_Read_UINT32(s, settings->MonitorFlags); /* flags */
2115  Stream_Read_UINT32(s, monitorCount); /* monitorCount */
2116 
2117  /* 2.2.1.3.6 Client Monitor Data -
2118  * monitorCount (4 bytes): A 32-bit, unsigned integer. The number of display
2119  * monitor definitions in the monitorDefArray field (the maximum allowed is 16).
2120  */
2121  if (monitorCount > 16)
2122  {
2123  WLog_ERR(TAG, "announced monitors(%" PRIu32 ") exceed the 16 limit", monitorCount);
2124  return FALSE;
2125  }
2126 
2127  if (monitorCount > settings->MonitorDefArraySize)
2128  {
2129  WLog_ERR(TAG, "too many announced monitors(%" PRIu32 "), clamping to %" PRIu32 "",
2130  monitorCount, settings->MonitorDefArraySize);
2131  monitorCount = settings->MonitorDefArraySize;
2132  }
2133 
2134  if ((UINT32)((blockLength - 8) / 20) < monitorCount)
2135  return FALSE;
2136 
2137  settings->MonitorCount = monitorCount;
2138 
2139  for (UINT32 index = 0; index < monitorCount; index++)
2140  {
2141  INT32 left = 0;
2142  INT32 top = 0;
2143  INT32 right = 0;
2144  INT32 bottom = 0;
2145  INT32 flags = 0;
2146  rdpMonitor* current = &settings->MonitorDefArray[index];
2147 
2148  Stream_Read_INT32(s, left); /* left */
2149  Stream_Read_INT32(s, top); /* top */
2150  Stream_Read_INT32(s, right); /* right */
2151  Stream_Read_INT32(s, bottom); /* bottom */
2152  Stream_Read_INT32(s, flags); /* flags */
2153  current->x = left;
2154  current->y = top;
2155  current->width = right - left + 1;
2156  current->height = bottom - top + 1;
2157  current->is_primary = (flags & MONITOR_PRIMARY) ? TRUE : FALSE;
2158  }
2159 
2160  return TRUE;
2161 }
2162 
2172 BOOL gcc_write_client_monitor_data(wStream* s, const rdpMcs* mcs)
2173 {
2174  INT32 baseX = 0;
2175  INT32 baseY = 0;
2176  const rdpSettings* settings = mcs_get_const_settings(mcs);
2177 
2178  WINPR_ASSERT(s);
2179  WINPR_ASSERT(settings);
2180 
2181  WLog_DBG(TAG, "MonitorCount=%" PRIu32, settings->MonitorCount);
2182  if (settings->MonitorCount > 1)
2183  {
2184  const size_t len = (20 * settings->MonitorCount) + 12;
2185  WINPR_ASSERT(len <= UINT16_MAX);
2186  const UINT16 length = (UINT16)len;
2187  if (!gcc_write_user_data_header(s, CS_MONITOR, length))
2188  return FALSE;
2189  Stream_Write_UINT32(s, settings->MonitorFlags); /* flags */
2190  Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */
2191 
2192  /* first pass to get the primary monitor coordinates (it is supposed to be
2193  * in (0,0) */
2194  for (UINT32 i = 0; i < settings->MonitorCount; i++)
2195  {
2196  const rdpMonitor* current = &settings->MonitorDefArray[i];
2197  if (current->is_primary)
2198  {
2199  baseX = current->x;
2200  baseY = current->y;
2201  break;
2202  }
2203  }
2204 
2205  for (UINT32 i = 0; i < settings->MonitorCount; i++)
2206  {
2207  const rdpMonitor* current = &settings->MonitorDefArray[i];
2208  const UINT32 left = WINPR_ASSERTING_INT_CAST(uint32_t, current->x - baseX);
2209  const UINT32 top = WINPR_ASSERTING_INT_CAST(uint32_t, current->y - baseY);
2210  const UINT32 right = left + WINPR_ASSERTING_INT_CAST(uint32_t, current->width - 1);
2211  const UINT32 bottom = top + WINPR_ASSERTING_INT_CAST(uint32_t, current->height - 1);
2212  const UINT32 flags = current->is_primary ? MONITOR_PRIMARY : 0;
2213  WLog_DBG(TAG,
2214  "Monitor[%" PRIu32 "]: top=%" PRIu32 ", left=%" PRIu32 ", bottom=%" PRIu32
2215  ", right=%" PRIu32 ", flags=%" PRIu32,
2216  i, top, left, bottom, right, flags);
2217  Stream_Write_UINT32(s, left); /* left */
2218  Stream_Write_UINT32(s, top); /* top */
2219  Stream_Write_UINT32(s, right); /* right */
2220  Stream_Write_UINT32(s, bottom); /* bottom */
2221  Stream_Write_UINT32(s, flags); /* flags */
2222  }
2223  }
2224  WLog_DBG(TAG, "FINISHED");
2225  return TRUE;
2226 }
2227 
2228 BOOL gcc_read_client_monitor_extended_data(wStream* s, rdpMcs* mcs)
2229 {
2230  UINT32 monitorCount = 0;
2231  UINT32 monitorAttributeSize = 0;
2232  rdpSettings* settings = mcs_get_settings(mcs);
2233 
2234  WINPR_ASSERT(s);
2235  WINPR_ASSERT(settings);
2236 
2237  const size_t blockLength = Stream_GetRemainingLength(s);
2238  if (blockLength < 12)
2239  return FALSE;
2240 
2241  Stream_Read_UINT32(s, settings->MonitorAttributeFlags); /* flags */
2242  Stream_Read_UINT32(s, monitorAttributeSize); /* monitorAttributeSize */
2243  Stream_Read_UINT32(s, monitorCount); /* monitorCount */
2244 
2245  if (monitorAttributeSize != 20)
2246  return FALSE;
2247 
2248  if ((blockLength - 12) / monitorAttributeSize < monitorCount)
2249  return FALSE;
2250 
2251  if (settings->MonitorCount != monitorCount)
2252  return FALSE;
2253 
2254  settings->HasMonitorAttributes = TRUE;
2255 
2256  for (UINT32 index = 0; index < monitorCount; index++)
2257  {
2258  rdpMonitor* current = &settings->MonitorDefArray[index];
2259  Stream_Read_UINT32(s, current->attributes.physicalWidth); /* physicalWidth */
2260  Stream_Read_UINT32(s, current->attributes.physicalHeight); /* physicalHeight */
2261  Stream_Read_UINT32(s, current->attributes.orientation); /* orientation */
2262  Stream_Read_UINT32(s, current->attributes.desktopScaleFactor); /* desktopScaleFactor */
2263  Stream_Read_UINT32(s, current->attributes.deviceScaleFactor); /* deviceScaleFactor */
2264  }
2265 
2266  return TRUE;
2267 }
2268 
2269 BOOL gcc_write_client_monitor_extended_data(wStream* s, const rdpMcs* mcs)
2270 {
2271  const rdpSettings* settings = mcs_get_const_settings(mcs);
2272 
2273  WINPR_ASSERT(s);
2274  WINPR_ASSERT(settings);
2275 
2276  if (settings->HasMonitorAttributes)
2277  {
2278  const size_t length = (20 * settings->MonitorCount) + 16;
2279  WINPR_ASSERT(length <= UINT16_MAX);
2280  if (!gcc_write_user_data_header(s, CS_MONITOR_EX, (UINT16)length))
2281  return FALSE;
2282  Stream_Write_UINT32(s, settings->MonitorAttributeFlags); /* flags */
2283  Stream_Write_UINT32(s, 20); /* monitorAttributeSize */
2284  Stream_Write_UINT32(s, settings->MonitorCount); /* monitorCount */
2285 
2286  for (UINT32 i = 0; i < settings->MonitorCount; i++)
2287  {
2288  const rdpMonitor* current = &settings->MonitorDefArray[i];
2289  Stream_Write_UINT32(s, current->attributes.physicalWidth); /* physicalWidth */
2290  Stream_Write_UINT32(s, current->attributes.physicalHeight); /* physicalHeight */
2291  Stream_Write_UINT32(s, current->attributes.orientation); /* orientation */
2292  Stream_Write_UINT32(s, current->attributes.desktopScaleFactor); /* desktopScaleFactor */
2293  Stream_Write_UINT32(s, current->attributes.deviceScaleFactor); /* deviceScaleFactor */
2294  }
2295  }
2296  return TRUE;
2297 }
2298 
2308 BOOL gcc_read_client_message_channel_data(wStream* s, rdpMcs* mcs)
2309 {
2310  WINPR_ASSERT(s);
2311  WINPR_ASSERT(mcs);
2312 
2313  const size_t blockLength = Stream_GetRemainingLength(s);
2314  if (blockLength < 4)
2315  return FALSE;
2316 
2317  Stream_Read_UINT32(s, mcs->flags);
2318  mcs->messageChannelId = mcs->baseChannelId++;
2319  return TRUE;
2320 }
2321 
2331 BOOL gcc_write_client_message_channel_data(wStream* s, const rdpMcs* mcs)
2332 {
2333  const rdpSettings* settings = mcs_get_const_settings(mcs);
2334 
2335  WINPR_ASSERT(s);
2336  WINPR_ASSERT(mcs);
2337  WINPR_ASSERT(settings);
2338  if (freerdp_settings_get_bool(settings, FreeRDP_NetworkAutoDetect) ||
2339  settings->SupportHeartbeatPdu || settings->SupportMultitransport)
2340  {
2341  if (!gcc_write_user_data_header(s, CS_MCS_MSGCHANNEL, 8))
2342  return FALSE;
2343  Stream_Write_UINT32(s, mcs->flags); /* flags */
2344  }
2345  return TRUE;
2346 }
2347 
2348 BOOL gcc_read_server_message_channel_data(wStream* s, rdpMcs* mcs)
2349 {
2350  UINT16 MCSChannelId = 0;
2351  WINPR_ASSERT(s);
2352  WINPR_ASSERT(mcs);
2353  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
2354  return FALSE;
2355 
2356  Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
2357  /* Save the MCS message channel id */
2358  mcs->messageChannelId = MCSChannelId;
2359  return TRUE;
2360 }
2361 
2362 BOOL gcc_write_server_message_channel_data(wStream* s, const rdpMcs* mcs)
2363 {
2364  WINPR_ASSERT(s);
2365  WINPR_ASSERT(mcs);
2366  if (mcs->messageChannelId == 0)
2367  return TRUE;
2368 
2369  if (!gcc_write_user_data_header(s, SC_MCS_MSGCHANNEL, 6))
2370  return FALSE;
2371 
2372  Stream_Write_UINT16(s, mcs->messageChannelId); /* mcsChannelId (2 bytes) */
2373  return TRUE;
2374 }
2375 
2385 BOOL gcc_read_client_multitransport_channel_data(wStream* s, rdpMcs* mcs)
2386 {
2387  rdpSettings* settings = mcs_get_settings(mcs);
2388 
2389  WINPR_ASSERT(s);
2390  WINPR_ASSERT(settings);
2391 
2392  const size_t blockLength = Stream_GetRemainingLength(s);
2393  if (blockLength < 4)
2394  return FALSE;
2395 
2396  UINT32 remoteFlags = 0;
2397  Stream_Read_UINT32(s, remoteFlags);
2398  settings->MultitransportFlags &= remoteFlags; /* merge local and remote flags */
2399  return TRUE;
2400 }
2401 
2412 BOOL gcc_write_client_multitransport_channel_data(wStream* s, const rdpMcs* mcs)
2413 {
2414  const rdpSettings* settings = mcs_get_const_settings(mcs);
2415 
2416  WINPR_ASSERT(s);
2417  WINPR_ASSERT(settings);
2418  if (!gcc_write_user_data_header(s, CS_MULTITRANSPORT, 8))
2419  return FALSE;
2420  Stream_Write_UINT32(s, settings->MultitransportFlags); /* flags */
2421  return TRUE;
2422 }
2423 
2424 BOOL gcc_read_server_multitransport_channel_data(wStream* s, rdpMcs* mcs)
2425 {
2426  rdpSettings* settings = mcs_get_settings(mcs);
2427  UINT32 remoteFlags = 0;
2428 
2429  WINPR_ASSERT(s);
2430  WINPR_ASSERT(settings);
2431  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2432  return FALSE;
2433 
2434  Stream_Read_UINT32(s, remoteFlags);
2435  settings->MultitransportFlags &= remoteFlags; /* merge with client setting */
2436  return TRUE;
2437 }
2438 
2439 BOOL gcc_write_server_multitransport_channel_data(wStream* s, const rdpMcs* mcs)
2440 {
2441  const rdpSettings* settings = mcs_get_const_settings(mcs);
2442 
2443  WINPR_ASSERT(s);
2444  WINPR_ASSERT(settings);
2445 
2446  if (!gcc_write_user_data_header(s, SC_MULTITRANSPORT, 8))
2447  return FALSE;
2448 
2449  Stream_Write_UINT32(s, settings->MultitransportFlags); /* flags (4 bytes) */
2450  return TRUE;
2451 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *param)
Sets a string settings value. The param is copied.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id, const void *data, size_t len)
Set a pointer to value data.
FREERDP_API const char * freerdp_supported_color_depths_string(UINT16 mask, char *buffer, size_t size)
returns a string representation of RNS_UD_XXBPP_SUPPORT values
FREERDP_API UINT16 freerdp_settings_get_uint16(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt16 id)
Returns a UINT16 settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.
FREERDP_API void * freerdp_settings_get_pointer_writable(rdpSettings *settings, FreeRDP_Settings_Keys_Pointer id)
Returns a mutable pointer settings value.