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