FreeRDP
mcs.c
1 
24 #include <freerdp/config.h>
25 
26 #include <winpr/crt.h>
27 #include <winpr/assert.h>
28 #include <freerdp/log.h>
29 
30 #include "gcc.h"
31 
32 #include "mcs.h"
33 #include "tpdu.h"
34 #include "tpkt.h"
35 #include "client.h"
36 #include "connection.h"
37 
38 #define TAG FREERDP_TAG("core")
39 
169 static const BYTE callingDomainSelector[1] = "\x01";
170 static const BYTE calledDomainSelector[1] = "\x01";
171 
172 /*
173 static const char* const mcs_result_enumerated[] =
174 {
175  "rt-successful",
176  "rt-domain-merging",
177  "rt-domain-not-hierarchical",
178  "rt-no-such-channel",
179  "rt-no-such-domain",
180  "rt-no-such-user",
181  "rt-not-admitted",
182  "rt-other-user-id",
183  "rt-parameters-unacceptable",
184  "rt-token-not-available",
185  "rt-token-not-possessed",
186  "rt-too-many-channels",
187  "rt-too-many-tokens",
188  "rt-too-many-users",
189  "rt-unspecified-failure",
190  "rt-user-rejected"
191 };
192 */
193 
194 const char* mcs_domain_pdu_string(DomainMCSPDU pdu)
195 {
196  switch (pdu)
197  {
198  case DomainMCSPDU_PlumbDomainIndication:
199  return "DomainMCSPDU_PlumbDomainIndication";
200  case DomainMCSPDU_ErectDomainRequest:
201  return "DomainMCSPDU_ErectDomainRequest";
202  case DomainMCSPDU_MergeChannelsRequest:
203  return "DomainMCSPDU_MergeChannelsRequest";
204  case DomainMCSPDU_MergeChannelsConfirm:
205  return "DomainMCSPDU_MergeChannelsConfirm";
206  case DomainMCSPDU_PurgeChannelsIndication:
207  return "DomainMCSPDU_PurgeChannelsIndication";
208  case DomainMCSPDU_MergeTokensRequest:
209  return "DomainMCSPDU_MergeTokensRequest";
210  case DomainMCSPDU_MergeTokensConfirm:
211  return "DomainMCSPDU_MergeTokensConfirm";
212  case DomainMCSPDU_PurgeTokensIndication:
213  return "DomainMCSPDU_PurgeTokensIndication";
214  case DomainMCSPDU_DisconnectProviderUltimatum:
215  return "DomainMCSPDU_DisconnectProviderUltimatum";
216  case DomainMCSPDU_RejectMCSPDUUltimatum:
217  return "DomainMCSPDU_RejectMCSPDUUltimatum";
218  case DomainMCSPDU_AttachUserRequest:
219  return "DomainMCSPDU_AttachUserRequest";
220  case DomainMCSPDU_AttachUserConfirm:
221  return "DomainMCSPDU_AttachUserConfirm";
222  case DomainMCSPDU_DetachUserRequest:
223  return "DomainMCSPDU_DetachUserRequest";
224  case DomainMCSPDU_DetachUserIndication:
225  return "DomainMCSPDU_DetachUserIndication";
226  case DomainMCSPDU_ChannelJoinRequest:
227  return "DomainMCSPDU_ChannelJoinRequest";
228  case DomainMCSPDU_ChannelJoinConfirm:
229  return "DomainMCSPDU_ChannelJoinConfirm";
230  case DomainMCSPDU_ChannelLeaveRequest:
231  return "DomainMCSPDU_ChannelLeaveRequest";
232  case DomainMCSPDU_ChannelConveneRequest:
233  return "DomainMCSPDU_ChannelConveneRequest";
234  case DomainMCSPDU_ChannelConveneConfirm:
235  return "DomainMCSPDU_ChannelConveneConfirm";
236  case DomainMCSPDU_ChannelDisbandRequest:
237  return "DomainMCSPDU_ChannelDisbandRequest";
238  case DomainMCSPDU_ChannelDisbandIndication:
239  return "DomainMCSPDU_ChannelDisbandIndication";
240  case DomainMCSPDU_ChannelAdmitRequest:
241  return "DomainMCSPDU_ChannelAdmitRequest";
242  case DomainMCSPDU_ChannelAdmitIndication:
243  return "DomainMCSPDU_ChannelAdmitIndication";
244  case DomainMCSPDU_ChannelExpelRequest:
245  return "DomainMCSPDU_ChannelExpelRequest";
246  case DomainMCSPDU_ChannelExpelIndication:
247  return "DomainMCSPDU_ChannelExpelIndication";
248  case DomainMCSPDU_SendDataRequest:
249  return "DomainMCSPDU_SendDataRequest";
250  case DomainMCSPDU_SendDataIndication:
251  return "DomainMCSPDU_SendDataIndication";
252  case DomainMCSPDU_UniformSendDataRequest:
253  return "DomainMCSPDU_UniformSendDataRequest";
254  case DomainMCSPDU_UniformSendDataIndication:
255  return "DomainMCSPDU_UniformSendDataIndication";
256  case DomainMCSPDU_TokenGrabRequest:
257  return "DomainMCSPDU_TokenGrabRequest";
258  case DomainMCSPDU_TokenGrabConfirm:
259  return "DomainMCSPDU_TokenGrabConfirm";
260  case DomainMCSPDU_TokenInhibitRequest:
261  return "DomainMCSPDU_TokenInhibitRequest";
262  case DomainMCSPDU_TokenInhibitConfirm:
263  return "DomainMCSPDU_TokenInhibitConfirm";
264  case DomainMCSPDU_TokenGiveRequest:
265  return "DomainMCSPDU_TokenGiveRequest";
266  case DomainMCSPDU_TokenGiveIndication:
267  return "DomainMCSPDU_TokenGiveIndication";
268  case DomainMCSPDU_TokenGiveResponse:
269  return "DomainMCSPDU_TokenGiveResponse";
270  case DomainMCSPDU_TokenGiveConfirm:
271  return "DomainMCSPDU_TokenGiveConfirm";
272  case DomainMCSPDU_TokenPleaseRequest:
273  return "DomainMCSPDU_TokenPleaseRequest";
274  case DomainMCSPDU_TokenPleaseConfirm:
275  return "DomainMCSPDU_TokenPleaseConfirm";
276  case DomainMCSPDU_TokenReleaseRequest:
277  return "DomainMCSPDU_TokenReleaseRequest";
278  case DomainMCSPDU_TokenReleaseConfirm:
279  return "DomainMCSPDU_TokenReleaseConfirm";
280  case DomainMCSPDU_TokenTestRequest:
281  return "DomainMCSPDU_TokenTestRequest";
282  case DomainMCSPDU_TokenTestConfirm:
283  return "DomainMCSPDU_TokenTestConfirm";
284  case DomainMCSPDU_enum_length:
285  return "DomainMCSPDU_enum_length";
286  default:
287  return "DomainMCSPDU_UNKNOWN";
288  }
289 }
290 
291 static BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters,
292  DomainParameters* minimumParameters,
293  DomainParameters* maximumParameters,
294  DomainParameters* pOutParameters);
295 
296 static BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData);
297 static BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData);
298 static BOOL mcs_read_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU, UINT16* length,
299  DomainMCSPDU* actual);
300 
301 static int mcs_initialize_client_channels(rdpMcs* mcs, const rdpSettings* settings)
302 {
303  if (!mcs || !settings)
304  return -1;
305 
306  mcs->channelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount);
307 
308  if (mcs->channelCount > mcs->channelMaxCount)
309  mcs->channelCount = mcs->channelMaxCount;
310 
311  ZeroMemory(mcs->channels, sizeof(rdpMcsChannel) * mcs->channelMaxCount);
312 
313  for (UINT32 index = 0; index < mcs->channelCount; index++)
314  {
315  const CHANNEL_DEF* defchannel =
316  freerdp_settings_get_pointer_array(settings, FreeRDP_ChannelDefArray, index);
317  rdpMcsChannel* cur = &mcs->channels[index];
318  WINPR_ASSERT(defchannel);
319  CopyMemory(cur->Name, defchannel->name, CHANNEL_NAME_LEN);
320  cur->options = defchannel->options;
321  }
322 
323  return 0;
324 }
325 
335 BOOL mcs_read_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU, UINT16* length,
336  DomainMCSPDU* actual)
337 {
338  UINT16 li = 0;
339  BYTE choice = 0;
340 
341  if (actual)
342  *actual = DomainMCSPDU_invalid;
343 
344  WINPR_ASSERT(s);
345  WINPR_ASSERT(domainMCSPDU);
346  WINPR_ASSERT(length);
347 
348  if (!tpkt_read_header(s, length))
349  return FALSE;
350 
351  if (!tpdu_read_data(s, &li, *length))
352  return FALSE;
353 
354  if (!per_read_choice(s, &choice))
355  return FALSE;
356 
357  const DomainMCSPDU MCSPDU = (choice >> 2);
358  if (actual)
359  *actual = MCSPDU;
360 
361  if (domainMCSPDU != MCSPDU)
362  {
363  WLog_ERR(TAG, "Expected MCS %s, got %s", mcs_domain_pdu_string(domainMCSPDU),
364  mcs_domain_pdu_string(MCSPDU));
365  return FALSE;
366  }
367 
368  return TRUE;
369 }
370 
378 BOOL mcs_write_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU, UINT16 length,
379  BYTE options)
380 {
381  WINPR_ASSERT(s);
382  WINPR_ASSERT((options & ~0x03) == 0);
383  WINPR_ASSERT((domainMCSPDU & ~0x3F) == 0);
384 
385  if (!tpkt_write_header(s, length))
386  return FALSE;
387  if (!tpdu_write_data(s))
388  return FALSE;
389  return per_write_choice(s, (BYTE)((domainMCSPDU << 2) | options));
390 }
391 
401 static BOOL mcs_init_domain_parameters(DomainParameters* domainParameters, UINT32 maxChannelIds,
402  UINT32 maxUserIds, UINT32 maxTokenIds, UINT32 maxMCSPDUsize)
403 {
404  if (!domainParameters)
405  return FALSE;
406 
407  domainParameters->maxChannelIds = maxChannelIds;
408  domainParameters->maxUserIds = maxUserIds;
409  domainParameters->maxTokenIds = maxTokenIds;
410  domainParameters->maxMCSPDUsize = maxMCSPDUsize;
411  domainParameters->numPriorities = 1;
412  domainParameters->minThroughput = 0;
413  domainParameters->maxHeight = 1;
414  domainParameters->protocolVersion = 2;
415  return TRUE;
416 }
417 
424 static BOOL mcs_read_domain_parameters(wStream* s, DomainParameters* domainParameters)
425 {
426  size_t length = 0;
427 
428  if (!s || !domainParameters)
429  return FALSE;
430 
431  return ber_read_sequence_tag(s, &length) &&
432  ber_read_integer(s, &(domainParameters->maxChannelIds)) &&
433  ber_read_integer(s, &(domainParameters->maxUserIds)) &&
434  ber_read_integer(s, &(domainParameters->maxTokenIds)) &&
435  ber_read_integer(s, &(domainParameters->numPriorities)) &&
436  ber_read_integer(s, &(domainParameters->minThroughput)) &&
437  ber_read_integer(s, &(domainParameters->maxHeight)) &&
438  ber_read_integer(s, &(domainParameters->maxMCSPDUsize)) &&
439  ber_read_integer(s, &(domainParameters->protocolVersion));
440 }
441 
448 static BOOL mcs_write_domain_parameters(wStream* s, DomainParameters* domainParameters)
449 {
450  size_t length = 0;
451  wStream* tmps = NULL;
452 
453  if (!s || !domainParameters)
454  return FALSE;
455 
456  tmps = Stream_New(NULL, Stream_Capacity(s));
457 
458  if (!tmps)
459  {
460  WLog_ERR(TAG, "Stream_New failed!");
461  return FALSE;
462  }
463 
464  ber_write_integer(tmps, domainParameters->maxChannelIds);
465  ber_write_integer(tmps, domainParameters->maxUserIds);
466  ber_write_integer(tmps, domainParameters->maxTokenIds);
467  ber_write_integer(tmps, domainParameters->numPriorities);
468  ber_write_integer(tmps, domainParameters->minThroughput);
469  ber_write_integer(tmps, domainParameters->maxHeight);
470  ber_write_integer(tmps, domainParameters->maxMCSPDUsize);
471  ber_write_integer(tmps, domainParameters->protocolVersion);
472  length = Stream_GetPosition(tmps);
473  ber_write_sequence_tag(s, length);
474  Stream_Write(s, Stream_Buffer(tmps), length);
475  Stream_Free(tmps, TRUE);
476  return TRUE;
477 }
478 
479 #ifdef DEBUG_MCS
485 static void mcs_print_domain_parameters(DomainParameters* domainParameters)
486 {
487  WLog_INFO(TAG, "DomainParameters {");
488 
489  if (domainParameters)
490  {
491  WLog_INFO(TAG, "\tmaxChannelIds:%" PRIu32 "", domainParameters->maxChannelIds);
492  WLog_INFO(TAG, "\tmaxUserIds:%" PRIu32 "", domainParameters->maxUserIds);
493  WLog_INFO(TAG, "\tmaxTokenIds:%" PRIu32 "", domainParameters->maxTokenIds);
494  WLog_INFO(TAG, "\tnumPriorities:%" PRIu32 "", domainParameters->numPriorities);
495  WLog_INFO(TAG, "\tminThroughput:%" PRIu32 "", domainParameters->minThroughput);
496  WLog_INFO(TAG, "\tmaxHeight:%" PRIu32 "", domainParameters->maxHeight);
497  WLog_INFO(TAG, "\tmaxMCSPDUsize:%" PRIu32 "", domainParameters->maxMCSPDUsize);
498  WLog_INFO(TAG, "\tprotocolVersion:%" PRIu32 "", domainParameters->protocolVersion);
499  }
500  else
501  WLog_INFO(TAG, "\tdomainParameters=%p", domainParameters);
502 
503  WLog_INFO(TAG, "}");
504 }
505 #endif
506 
517 BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters,
518  DomainParameters* minimumParameters,
519  DomainParameters* maximumParameters,
520  DomainParameters* pOutParameters)
521 {
522  /* maxChannelIds */
523  if (!targetParameters || !minimumParameters || !maximumParameters || !pOutParameters)
524  return FALSE;
525 
526  if (targetParameters->maxChannelIds >= 4)
527  {
528  pOutParameters->maxChannelIds = targetParameters->maxChannelIds;
529  }
530  else if (maximumParameters->maxChannelIds >= 4)
531  {
532  pOutParameters->maxChannelIds = 4;
533  }
534  else
535  {
536  WLog_ERR(TAG, "invalid maxChannelIds [%" PRIu32 ", %" PRIu32 "]",
537  targetParameters->maxChannelIds, maximumParameters->maxChannelIds);
538  return FALSE;
539  }
540 
541  /* maxUserIds */
542 
543  if (targetParameters->maxUserIds >= 3)
544  {
545  pOutParameters->maxUserIds = targetParameters->maxUserIds;
546  }
547  else if (maximumParameters->maxUserIds >= 3)
548  {
549  pOutParameters->maxUserIds = 3;
550  }
551  else
552  {
553  WLog_ERR(TAG, "invalid maxUserIds [%" PRIu32 ", %" PRIu32 "]", targetParameters->maxUserIds,
554  maximumParameters->maxUserIds);
555  return FALSE;
556  }
557 
558  /* maxTokenIds */
559  pOutParameters->maxTokenIds = targetParameters->maxTokenIds;
560 
561  /* numPriorities */
562 
563  if (minimumParameters->numPriorities <= 1)
564  {
565  pOutParameters->numPriorities = 1;
566  }
567  else
568  {
569  WLog_ERR(TAG, "invalid numPriorities [%" PRIu32 "]", maximumParameters->numPriorities);
570  return FALSE;
571  }
572 
573  /* minThroughput */
574  pOutParameters->minThroughput = targetParameters->minThroughput;
575 
576  /* maxHeight */
577 
578  if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1))
579  {
580  pOutParameters->maxHeight = 1;
581  }
582  else
583  {
584  WLog_ERR(TAG, "invalid maxHeight [%" PRIu32 ", %" PRIu32 "]", targetParameters->maxHeight,
585  minimumParameters->maxHeight);
586  return FALSE;
587  }
588 
589  /* maxMCSPDUsize */
590 
591  if (targetParameters->maxMCSPDUsize >= 1024)
592  {
593  if (targetParameters->maxMCSPDUsize <= 65528)
594  {
595  pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize;
596  }
597  else if ((minimumParameters->maxMCSPDUsize >= 124) &&
598  (minimumParameters->maxMCSPDUsize <= 65528))
599  {
600  pOutParameters->maxMCSPDUsize = 65528;
601  }
602  else
603  {
604  WLog_ERR(TAG, "invalid maxMCSPDUsize [%" PRIu32 ", %" PRIu32 "]",
605  targetParameters->maxMCSPDUsize, minimumParameters->maxMCSPDUsize);
606  return FALSE;
607  }
608  }
609  else
610  {
611  if (maximumParameters->maxMCSPDUsize >= 124)
612  {
613  pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize;
614  }
615  else
616  {
617  WLog_ERR(TAG, "invalid maxMCSPDUsize [%" PRIu32 "]", maximumParameters->maxMCSPDUsize);
618  return FALSE;
619  }
620  }
621 
622  /* protocolVersion */
623 
624  if ((targetParameters->protocolVersion == 2) ||
625  ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2)))
626  {
627  pOutParameters->protocolVersion = 2;
628  }
629  else
630  {
631  WLog_ERR(TAG, "invalid protocolVersion [%" PRIu32 ", %" PRIu32 ", %" PRIu32 "]",
632  targetParameters->protocolVersion, minimumParameters->protocolVersion,
633  maximumParameters->protocolVersion);
634  return FALSE;
635  }
636 
637  return TRUE;
638 }
639 
647 BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
648 {
649  UINT16 li = 0;
650  size_t length = 0;
651  BOOL upwardFlag = FALSE;
652  UINT16 tlength = 0;
653 
654  WINPR_ASSERT(mcs);
655  WINPR_ASSERT(s);
656 
657  if (!tpkt_read_header(s, &tlength))
658  return FALSE;
659 
660  if (!tpdu_read_data(s, &li, tlength))
661  return FALSE;
662 
663  if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
664  return FALSE;
665 
666  /* callingDomainSelector (OCTET_STRING) */
667  if (!ber_read_octet_string_tag(s, &length) ||
668  (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
669  return FALSE;
670 
671  Stream_Seek(s, length);
672 
673  /* calledDomainSelector (OCTET_STRING) */
674  if (!ber_read_octet_string_tag(s, &length) ||
675  (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
676  return FALSE;
677 
678  Stream_Seek(s, length);
679 
680  /* upwardFlag (BOOLEAN) */
681  if (!ber_read_BOOL(s, &upwardFlag))
682  return FALSE;
683 
684  /* targetParameters (DomainParameters) */
685  if (!mcs_read_domain_parameters(s, &mcs->targetParameters))
686  return FALSE;
687 
688  /* minimumParameters (DomainParameters) */
689  if (!mcs_read_domain_parameters(s, &mcs->minimumParameters))
690  return FALSE;
691 
692  /* maximumParameters (DomainParameters) */
693  if (!mcs_read_domain_parameters(s, &mcs->maximumParameters))
694  return FALSE;
695 
696  if (!ber_read_octet_string_tag(s, &length) ||
697  (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
698  return FALSE;
699 
700  if (!gcc_read_conference_create_request(s, mcs))
701  return FALSE;
702 
703  if (!mcs_merge_domain_parameters(&mcs->targetParameters, &mcs->minimumParameters,
704  &mcs->maximumParameters, &mcs->domainParameters))
705  return FALSE;
706 
707  return tpkt_ensure_stream_consumed(s, tlength);
708 }
709 
718 BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData)
719 {
720  size_t length = 0;
721  wStream* tmps = NULL;
722  BOOL ret = FALSE;
723 
724  if (!s || !mcs || !userData)
725  return FALSE;
726 
727  tmps = Stream_New(NULL, Stream_Capacity(s));
728 
729  if (!tmps)
730  {
731  WLog_ERR(TAG, "Stream_New failed!");
732  return FALSE;
733  }
734 
735  /* callingDomainSelector (OCTET_STRING) */
736  ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector));
737  /* calledDomainSelector (OCTET_STRING) */
738  ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector));
739  /* upwardFlag (BOOLEAN) */
740  ber_write_BOOL(tmps, TRUE);
741 
742  /* targetParameters (DomainParameters) */
743  if (!mcs_write_domain_parameters(tmps, &mcs->targetParameters))
744  goto out;
745 
746  /* minimumParameters (DomainParameters) */
747  if (!mcs_write_domain_parameters(tmps, &mcs->minimumParameters))
748  goto out;
749 
750  /* maximumParameters (DomainParameters) */
751  if (!mcs_write_domain_parameters(tmps, &mcs->maximumParameters))
752  goto out;
753 
754  /* userData (OCTET_STRING) */
755  ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
756  length = Stream_GetPosition(tmps);
757  /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
758  ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
759  Stream_Write(s, Stream_Buffer(tmps), length);
760  ret = TRUE;
761 out:
762  Stream_Free(tmps, TRUE);
763  return ret;
764 }
765 
776 BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData)
777 {
778  size_t length = 0;
779  wStream* tmps = NULL;
780  BOOL ret = FALSE;
781 
782  if (!s || !mcs || !userData)
783  return FALSE;
784 
785  tmps = Stream_New(NULL, Stream_Capacity(s));
786 
787  if (!tmps)
788  {
789  WLog_ERR(TAG, "Stream_New failed!");
790  return FALSE;
791  }
792 
793  ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
794  ber_write_integer(tmps, 0); /* calledConnectId */
795 
796  if (!mcs_write_domain_parameters(tmps, &(mcs->domainParameters)))
797  goto out;
798 
799  /* userData (OCTET_STRING) */
800  ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
801  length = Stream_GetPosition(tmps);
802  ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
803  Stream_Write(s, Stream_Buffer(tmps), length);
804  ret = TRUE;
805 out:
806  Stream_Free(tmps, TRUE);
807  return ret;
808 }
809 
816 static BOOL mcs_send_connect_initial(rdpMcs* mcs)
817 {
818  int status = -1;
819  size_t length = 0;
820  wStream* s = NULL;
821  size_t bm = 0;
822  size_t em = 0;
823  wStream* gcc_CCrq = NULL;
824  wStream* client_data = NULL;
825  rdpContext* context = NULL;
826 
827  if (!mcs)
828  return FALSE;
829 
830  context = transport_get_context(mcs->transport);
831  WINPR_ASSERT(context);
832 
833  mcs_initialize_client_channels(mcs, context->settings);
834  client_data = Stream_New(NULL, 512);
835 
836  if (!client_data)
837  {
838  WLog_ERR(TAG, "Stream_New failed!");
839  return FALSE;
840  }
841 
842  if (!gcc_write_client_data_blocks(client_data, mcs))
843  goto out;
844  gcc_CCrq = Stream_New(NULL, 1024);
845 
846  if (!gcc_CCrq)
847  {
848  WLog_ERR(TAG, "Stream_New failed!");
849  goto out;
850  }
851 
852  if (!gcc_write_conference_create_request(gcc_CCrq, client_data))
853  goto out;
854  length = Stream_GetPosition(gcc_CCrq) + 7;
855  s = Stream_New(NULL, 1024 + length);
856 
857  if (!s)
858  {
859  WLog_ERR(TAG, "Stream_New failed!");
860  goto out;
861  }
862 
863  bm = Stream_GetPosition(s);
864  Stream_Seek(s, 7);
865 
866  if (!mcs_write_connect_initial(s, mcs, gcc_CCrq))
867  {
868  WLog_ERR(TAG, "mcs_write_connect_initial failed!");
869  goto out;
870  }
871 
872  em = Stream_GetPosition(s);
873  length = (em - bm);
874  if (length > UINT16_MAX)
875  goto out;
876  Stream_SetPosition(s, bm);
877  if (!tpkt_write_header(s, (UINT16)length))
878  goto out;
879  if (!tpdu_write_data(s))
880  goto out;
881  Stream_SetPosition(s, em);
882  Stream_SealLength(s);
883  status = transport_write(mcs->transport, s);
884 out:
885  Stream_Free(s, TRUE);
886  Stream_Free(gcc_CCrq, TRUE);
887  Stream_Free(client_data, TRUE);
888  return (status < 0 ? FALSE : TRUE);
889 }
890 
897 BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
898 {
899  size_t length = 0;
900  UINT16 tlength = 0;
901  BYTE result = 0;
902  UINT16 li = 0;
903  UINT32 calledConnectId = 0;
904 
905  if (!mcs || !s)
906  return FALSE;
907 
908  if (!tpkt_read_header(s, &tlength))
909  return FALSE;
910 
911  if (!tpdu_read_data(s, &li, tlength))
912  return FALSE;
913 
914  if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
915  !ber_read_enumerated(s, &result, MCS_Result_enum_length) ||
916  !ber_read_integer(s, &calledConnectId) ||
917  !mcs_read_domain_parameters(s, &(mcs->domainParameters)) ||
918  !ber_read_octet_string_tag(s, &length))
919  {
920  return FALSE;
921  }
922 
923  if (!gcc_read_conference_create_response(s, mcs))
924  {
925  WLog_ERR(TAG, "gcc_read_conference_create_response failed");
926  return FALSE;
927  }
928 
929  return tpkt_ensure_stream_consumed(s, tlength);
930 }
931 
938 BOOL mcs_send_connect_response(rdpMcs* mcs)
939 {
940  size_t length = 0;
941  int status = -1;
942  wStream* s = NULL;
943  size_t bm = 0;
944  size_t em = 0;
945  wStream* gcc_CCrsp = NULL;
946  wStream* server_data = NULL;
947 
948  if (!mcs)
949  return FALSE;
950 
951  server_data = Stream_New(NULL, 512);
952 
953  if (!server_data)
954  {
955  WLog_ERR(TAG, "Stream_New failed!");
956  return FALSE;
957  }
958 
959  if (!gcc_write_server_data_blocks(server_data, mcs))
960  goto out;
961 
962  gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data));
963 
964  if (!gcc_CCrsp)
965  {
966  WLog_ERR(TAG, "Stream_New failed!");
967  goto out;
968  }
969 
970  if (!gcc_write_conference_create_response(gcc_CCrsp, server_data))
971  goto out;
972  length = Stream_GetPosition(gcc_CCrsp) + 7;
973  s = Stream_New(NULL, length + 1024);
974 
975  if (!s)
976  {
977  WLog_ERR(TAG, "Stream_New failed!");
978  goto out;
979  }
980 
981  bm = Stream_GetPosition(s);
982  Stream_Seek(s, 7);
983 
984  if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
985  goto out;
986 
987  em = Stream_GetPosition(s);
988  length = (em - bm);
989  if (length > UINT16_MAX)
990  goto out;
991  Stream_SetPosition(s, bm);
992  if (!tpkt_write_header(s, (UINT16)length))
993  goto out;
994  if (!tpdu_write_data(s))
995  goto out;
996  Stream_SetPosition(s, em);
997  Stream_SealLength(s);
998  status = transport_write(mcs->transport, s);
999 out:
1000  Stream_Free(s, TRUE);
1001  Stream_Free(gcc_CCrsp, TRUE);
1002  Stream_Free(server_data, TRUE);
1003  return (status < 0) ? FALSE : TRUE;
1004 }
1005 
1013 BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
1014 {
1015  UINT16 length = 0;
1016  UINT32 subHeight = 0;
1017  UINT32 subInterval = 0;
1018 
1019  WINPR_ASSERT(mcs);
1020  WINPR_ASSERT(s);
1021 
1022  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, &length, NULL))
1023  return FALSE;
1024 
1025  if (!per_read_integer(s, &subHeight)) /* subHeight (INTEGER) */
1026  return FALSE;
1027 
1028  if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
1029  return FALSE;
1030 
1031  return tpkt_ensure_stream_consumed(s, length);
1032 }
1033 
1040 BOOL mcs_send_erect_domain_request(rdpMcs* mcs)
1041 {
1042  wStream* s = NULL;
1043  int status = 0;
1044  UINT16 length = 12;
1045 
1046  if (!mcs)
1047  return FALSE;
1048 
1049  s = Stream_New(NULL, length);
1050 
1051  if (!s)
1052  {
1053  WLog_ERR(TAG, "Stream_New failed!");
1054  return FALSE;
1055  }
1056 
1057  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0);
1058  per_write_integer(s, 0); /* subHeight (INTEGER) */
1059  per_write_integer(s, 0); /* subInterval (INTEGER) */
1060  Stream_SealLength(s);
1061  status = transport_write(mcs->transport, s);
1062  Stream_Free(s, TRUE);
1063  return (status < 0) ? FALSE : TRUE;
1064 }
1065 
1073 BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s)
1074 {
1075  UINT16 length = 0;
1076 
1077  if (!mcs || !s)
1078  return FALSE;
1079 
1080  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, &length, NULL))
1081  return FALSE;
1082  return tpkt_ensure_stream_consumed(s, length);
1083 }
1084 
1091 BOOL mcs_send_attach_user_request(rdpMcs* mcs)
1092 {
1093  wStream* s = NULL;
1094  int status = 0;
1095  UINT16 length = 8;
1096 
1097  if (!mcs)
1098  return FALSE;
1099 
1100  s = Stream_New(NULL, length);
1101 
1102  if (!s)
1103  {
1104  WLog_ERR(TAG, "Stream_New failed!");
1105  return FALSE;
1106  }
1107 
1108  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0);
1109  Stream_SealLength(s);
1110  status = transport_write(mcs->transport, s);
1111  Stream_Free(s, TRUE);
1112  return (status < 0) ? FALSE : TRUE;
1113 }
1114 
1121 BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
1122 {
1123  BYTE result = 0;
1124  UINT16 length = 0;
1125 
1126  if (!mcs || !s)
1127  return FALSE;
1128 
1129  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, &length, NULL))
1130  return FALSE;
1131  if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1132  return FALSE;
1133  if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1134  return FALSE;
1135  return tpkt_ensure_stream_consumed(s, length);
1136 }
1137 
1144 BOOL mcs_send_attach_user_confirm(rdpMcs* mcs)
1145 {
1146  wStream* s = NULL;
1147  int status = 0;
1148  UINT16 length = 11;
1149 
1150  if (!mcs)
1151  return FALSE;
1152 
1153  s = Stream_New(NULL, length);
1154 
1155  if (!s)
1156  {
1157  WLog_ERR(TAG, "Stream_New failed!");
1158  return FALSE;
1159  }
1160 
1161  mcs->userId = mcs->baseChannelId++;
1162  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2);
1163  per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
1164  per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
1165  Stream_SealLength(s);
1166  status = transport_write(mcs->transport, s);
1167  Stream_Free(s, TRUE);
1168  return (status < 0) ? FALSE : TRUE;
1169 }
1170 
1178 BOOL mcs_recv_channel_join_request(rdpMcs* mcs, const rdpSettings* settings, wStream* s,
1179  UINT16* channelId)
1180 {
1181  UINT16 length = 0;
1182  UINT16 userId = 0;
1183 
1184  if (!mcs || !s || !channelId)
1185  return FALSE;
1186 
1187  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, &length, NULL))
1188  return FALSE;
1189 
1190  if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID))
1191  return FALSE;
1192  if (userId != mcs->userId)
1193  {
1194  if (freerdp_settings_get_bool(settings, FreeRDP_TransportDumpReplay))
1195  mcs->userId = userId;
1196  else
1197  return FALSE;
1198  }
1199  if (!per_read_integer16(s, channelId, 0))
1200  return FALSE;
1201 
1202  return tpkt_ensure_stream_consumed(s, length);
1203 }
1204 
1215 BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId)
1216 {
1217  wStream* s = NULL;
1218  int status = 0;
1219  UINT16 length = 12;
1220 
1221  WINPR_ASSERT(mcs);
1222 
1223  s = Stream_New(NULL, length);
1224 
1225  if (!s)
1226  {
1227  WLog_ERR(TAG, "Stream_New failed!");
1228  return FALSE;
1229  }
1230 
1231  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0);
1232  per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID);
1233  per_write_integer16(s, channelId, 0);
1234  Stream_SealLength(s);
1235  status = transport_write(mcs->transport, s);
1236  Stream_Free(s, TRUE);
1237  return (status < 0) ? FALSE : TRUE;
1238 }
1239 
1246 BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId)
1247 {
1248  UINT16 length = 0;
1249  BYTE result = 0;
1250  UINT16 initiator = 0;
1251  UINT16 requested = 0;
1252 
1253  WINPR_ASSERT(mcs);
1254  WINPR_ASSERT(channelId);
1255 
1256  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, &length, NULL))
1257  return FALSE;
1258 
1259  if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1260  return FALSE;
1261  if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1262  return FALSE;
1263  if (!per_read_integer16(s, &requested, 0)) /* requested (ChannelId) */
1264  return FALSE;
1265  if (!per_read_integer16(s, channelId, 0)) /* channelId */
1266  return FALSE;
1267  return tpkt_ensure_stream_consumed(s, length);
1268 }
1269 
1276 BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId)
1277 {
1278  wStream* s = NULL;
1279  int status = -1;
1280  UINT16 length = 15;
1281 
1282  if (!mcs)
1283  return FALSE;
1284 
1285  s = Stream_New(NULL, length);
1286 
1287  if (!s)
1288  {
1289  WLog_ERR(TAG, "Stream_New failed!");
1290  return FALSE;
1291  }
1292 
1293  if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2))
1294  goto fail;
1295  if (!per_write_enumerated(s, 0, MCS_Result_enum_length)) /* result */
1296  goto fail;
1297  if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1298  goto fail;
1299  if (!per_write_integer16(s, channelId, 0)) /* requested (ChannelId) */
1300  goto fail;
1301  if (!per_write_integer16(s, channelId, 0)) /* channelId */
1302  goto fail;
1303  Stream_SealLength(s);
1304  status = transport_write(mcs->transport, s);
1305 fail:
1306  Stream_Free(s, TRUE);
1307  return (status < 0) ? FALSE : TRUE;
1308 }
1309 
1315 BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason)
1316 {
1317  BYTE b1 = 0;
1318  BYTE b2 = 0;
1319 
1320  WINPR_ASSERT(mcs);
1321  WINPR_ASSERT(s);
1322  WINPR_ASSERT(reason);
1323 
1324  /*
1325  * http://msdn.microsoft.com/en-us/library/cc240872.aspx:
1326  *
1327  * PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
1328  * 21 80
1329  *
1330  * 0x21:
1331  * 0 - --\
1332  * 0 - |
1333  * 1 - | CHOICE: From DomainMCSPDU select disconnectProviderUltimatum (8)
1334  * 0 - | of type DisconnectProviderUltimatum
1335  * 0 - |
1336  * 0 - --/
1337  * 0 - --\
1338  * 1 - |
1339  * | DisconnectProviderUltimatum::reason = rn-user-requested (3)
1340  * 0x80: |
1341  * 1 - --/
1342  * 0 - padding
1343  * 0 - padding
1344  * 0 - padding
1345  * 0 - padding
1346  * 0 - padding
1347  * 0 - padding
1348  * 0 - padding
1349  */
1350 
1351  if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
1352  return FALSE;
1353 
1354  Stream_Rewind_UINT8(s);
1355  Stream_Read_UINT8(s, b1);
1356  Stream_Read_UINT8(s, b2);
1357  *reason = ((b1 & 0x01) << 1) | (b2 >> 7);
1358  return TRUE;
1359 }
1360 
1366 BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
1367 {
1368  wStream* s = NULL;
1369  int status = -1;
1370  UINT16 length = 9;
1371 
1372  WINPR_ASSERT(mcs);
1373 
1374  s = Stream_New(NULL, length);
1375 
1376  if (!s)
1377  goto fail;
1378 
1379  if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1))
1380  goto fail;
1381 
1382  if (!per_write_enumerated(s, 0x80, 0))
1383  goto fail;
1384  status = transport_write(mcs->transport, s);
1385 fail:
1386  Stream_Free(s, TRUE);
1387  return (status < 0) ? FALSE : TRUE;
1388 }
1389 
1390 BOOL mcs_client_begin(rdpMcs* mcs)
1391 {
1392  rdpContext* context = NULL;
1393 
1394  if (!mcs || !mcs->transport)
1395  return FALSE;
1396 
1397  context = transport_get_context(mcs->transport);
1398 
1399  if (!context)
1400  return FALSE;
1401 
1402  /* First transition state, we need this to trigger session recording */
1403  if (!mcs_send_connect_initial(mcs))
1404  {
1405  freerdp_set_last_error_if_not(context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
1406 
1407  WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
1408  return FALSE;
1409  }
1410 
1411  return TRUE;
1412 }
1413 
1420 rdpMcs* mcs_new(rdpTransport* transport)
1421 {
1422  rdpMcs* mcs = NULL;
1423 
1424  mcs = (rdpMcs*)calloc(1, sizeof(rdpMcs));
1425 
1426  if (!mcs)
1427  return NULL;
1428 
1429  mcs->transport = transport;
1430  mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
1431  mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
1432  mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
1433  mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF);
1434  mcs->channelCount = 0;
1435  mcs->channelMaxCount = CHANNEL_MAX_COUNT;
1436  mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
1437  mcs->channels = (rdpMcsChannel*)calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel));
1438 
1439  if (!mcs->channels)
1440  goto out_free;
1441 
1442  return mcs;
1443 out_free:
1444  free(mcs);
1445  return NULL;
1446 }
1447 
1453 void mcs_free(rdpMcs* mcs)
1454 {
1455  if (mcs)
1456  {
1457  free(mcs->channels);
1458  free(mcs);
1459  }
1460 }
1461 
1462 BOOL mcs_server_apply_to_settings(const rdpMcs* mcs, rdpSettings* settings)
1463 {
1464  BOOL rc = FALSE;
1465 
1466  WINPR_ASSERT(mcs);
1467  WINPR_ASSERT(settings);
1468 
1469  if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, mcs->channelCount))
1470  goto fail;
1471 
1472  for (UINT32 x = 0; x < mcs->channelCount; x++)
1473  {
1474  const rdpMcsChannel* current = &mcs->channels[x];
1475  CHANNEL_DEF def = { 0 };
1476  def.options = current->options;
1477  memcpy(def.name, current->Name, sizeof(def.name));
1478  if (!freerdp_settings_set_pointer_array(settings, FreeRDP_ChannelDefArray, x, &def))
1479  goto fail;
1480  }
1481 
1482  rc = TRUE;
1483 fail:
1484  if (!rc)
1485  WLog_WARN(TAG, "failed to apply settings");
1486 
1487  return rc;
1488 }
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_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.