FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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 MCS_TAG FREERDP_TAG("core")
39
169static const BYTE callingDomainSelector[1] = "\x01";
170static const BYTE calledDomainSelector[1] = "\x01";
171
172/*
173static 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
194const 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
291static BOOL mcs_merge_domain_parameters(wLog* log, DomainParameters* targetParameters,
292 DomainParameters* minimumParameters,
293 DomainParameters* maximumParameters,
294 DomainParameters* pOutParameters);
295
296static BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData);
297static BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData);
298static BOOL mcs_read_domain_mcspdu_header(wLog* log, wStream* s, DomainMCSPDU domainMCSPDU,
299 UINT16* length, DomainMCSPDU* actual);
300
301static 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
335BOOL mcs_read_domain_mcspdu_header(wLog* log, 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_Print(log, WLOG_ERROR, "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
378BOOL 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
401static 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
424static 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
448static BOOL mcs_write_domain_parameters(wLog* log, 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_Print(log, WLOG_ERROR, "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
485static 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
517BOOL mcs_merge_domain_parameters(wLog* log, 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_Print(log, WLOG_ERROR, "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_Print(log, WLOG_ERROR, "invalid maxUserIds [%" PRIu32 ", %" PRIu32 "]",
554 targetParameters->maxUserIds, 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_Print(log, WLOG_ERROR, "invalid numPriorities [%" PRIu32 "]",
570 maximumParameters->numPriorities);
571 return FALSE;
572 }
573
574 /* minThroughput */
575 pOutParameters->minThroughput = targetParameters->minThroughput;
576
577 /* maxHeight */
578
579 if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1))
580 {
581 pOutParameters->maxHeight = 1;
582 }
583 else
584 {
585 WLog_Print(log, WLOG_ERROR, "invalid maxHeight [%" PRIu32 ", %" PRIu32 "]",
586 targetParameters->maxHeight, minimumParameters->maxHeight);
587 return FALSE;
588 }
589
590 /* maxMCSPDUsize */
591
592 if (targetParameters->maxMCSPDUsize >= 1024)
593 {
594 if (targetParameters->maxMCSPDUsize <= 65528)
595 {
596 pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize;
597 }
598 else if ((minimumParameters->maxMCSPDUsize >= 124) &&
599 (minimumParameters->maxMCSPDUsize <= 65528))
600 {
601 pOutParameters->maxMCSPDUsize = 65528;
602 }
603 else
604 {
605 WLog_Print(log, WLOG_ERROR, "invalid maxMCSPDUsize [%" PRIu32 ", %" PRIu32 "]",
606 targetParameters->maxMCSPDUsize, minimumParameters->maxMCSPDUsize);
607 return FALSE;
608 }
609 }
610 else
611 {
612 if (maximumParameters->maxMCSPDUsize >= 124)
613 {
614 pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize;
615 }
616 else
617 {
618 WLog_Print(log, WLOG_ERROR, "invalid maxMCSPDUsize [%" PRIu32 "]",
619 maximumParameters->maxMCSPDUsize);
620 return FALSE;
621 }
622 }
623
624 /* protocolVersion */
625
626 if ((targetParameters->protocolVersion == 2) ||
627 ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2)))
628 {
629 pOutParameters->protocolVersion = 2;
630 }
631 else
632 {
633 WLog_Print(log, WLOG_ERROR,
634 "invalid protocolVersion [%" PRIu32 ", %" PRIu32 ", %" PRIu32 "]",
635 targetParameters->protocolVersion, minimumParameters->protocolVersion,
636 maximumParameters->protocolVersion);
637 return FALSE;
638 }
639
640 return TRUE;
641}
642
650BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
651{
652 UINT16 li = 0;
653 size_t length = 0;
654 BOOL upwardFlag = FALSE;
655 UINT16 tlength = 0;
656
657 WINPR_ASSERT(mcs);
658 WINPR_ASSERT(s);
659
660 if (!tpkt_read_header(s, &tlength))
661 return FALSE;
662
663 if (!tpdu_read_data(s, &li, tlength))
664 return FALSE;
665
666 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
667 return FALSE;
668
669 /* callingDomainSelector (OCTET_STRING) */
670 if (!ber_read_octet_string_tag(s, &length) ||
671 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
672 return FALSE;
673
674 Stream_Seek(s, length);
675
676 /* calledDomainSelector (OCTET_STRING) */
677 if (!ber_read_octet_string_tag(s, &length) ||
678 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
679 return FALSE;
680
681 Stream_Seek(s, length);
682
683 /* upwardFlag (BOOLEAN) */
684 if (!ber_read_BOOL(s, &upwardFlag))
685 return FALSE;
686
687 /* targetParameters (DomainParameters) */
688 if (!mcs_read_domain_parameters(s, &mcs->targetParameters))
689 return FALSE;
690
691 /* minimumParameters (DomainParameters) */
692 if (!mcs_read_domain_parameters(s, &mcs->minimumParameters))
693 return FALSE;
694
695 /* maximumParameters (DomainParameters) */
696 if (!mcs_read_domain_parameters(s, &mcs->maximumParameters))
697 return FALSE;
698
699 if (!ber_read_octet_string_tag(s, &length) ||
700 (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, length)))
701 return FALSE;
702
703 if (!gcc_read_conference_create_request(s, mcs))
704 return FALSE;
705
706 if (!mcs_merge_domain_parameters(mcs->log, &mcs->targetParameters, &mcs->minimumParameters,
707 &mcs->maximumParameters, &mcs->domainParameters))
708 return FALSE;
709
710 return tpkt_ensure_stream_consumed(mcs->log, s, tlength);
711}
712
721BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData)
722{
723 size_t length = 0;
724 wStream* tmps = NULL;
725 BOOL ret = FALSE;
726
727 if (!s || !mcs || !userData)
728 return FALSE;
729
730 tmps = Stream_New(NULL, Stream_Capacity(s));
731
732 if (!tmps)
733 {
734 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
735 return FALSE;
736 }
737
738 /* callingDomainSelector (OCTET_STRING) */
739 ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector));
740 /* calledDomainSelector (OCTET_STRING) */
741 ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector));
742 /* upwardFlag (BOOLEAN) */
743 ber_write_BOOL(tmps, TRUE);
744
745 /* targetParameters (DomainParameters) */
746 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->targetParameters))
747 goto out;
748
749 /* minimumParameters (DomainParameters) */
750 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->minimumParameters))
751 goto out;
752
753 /* maximumParameters (DomainParameters) */
754 if (!mcs_write_domain_parameters(mcs->log, tmps, &mcs->maximumParameters))
755 goto out;
756
757 /* userData (OCTET_STRING) */
758 ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
759 length = Stream_GetPosition(tmps);
760 /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
761 ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
762 Stream_Write(s, Stream_Buffer(tmps), length);
763 ret = TRUE;
764out:
765 Stream_Free(tmps, TRUE);
766 return ret;
767}
768
779BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData)
780{
781 size_t length = 0;
782 wStream* tmps = NULL;
783 BOOL ret = FALSE;
784
785 if (!s || !mcs || !userData)
786 return FALSE;
787
788 tmps = Stream_New(NULL, Stream_Capacity(s));
789
790 if (!tmps)
791 {
792 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
793 return FALSE;
794 }
795
796 ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
797 ber_write_integer(tmps, 0); /* calledConnectId */
798
799 if (!mcs_write_domain_parameters(mcs->log, tmps, &(mcs->domainParameters)))
800 goto out;
801
802 /* userData (OCTET_STRING) */
803 ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
804 length = Stream_GetPosition(tmps);
805 ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
806 Stream_Write(s, Stream_Buffer(tmps), length);
807 ret = TRUE;
808out:
809 Stream_Free(tmps, TRUE);
810 return ret;
811}
812
819static BOOL mcs_send_connect_initial(rdpMcs* mcs)
820{
821 int status = -1;
822 size_t length = 0;
823 wStream* s = NULL;
824 size_t bm = 0;
825 size_t em = 0;
826 wStream* gcc_CCrq = NULL;
827 wStream* client_data = NULL;
828 rdpContext* context = NULL;
829
830 if (!mcs)
831 return FALSE;
832
833 context = transport_get_context(mcs->transport);
834 WINPR_ASSERT(context);
835
836 mcs_initialize_client_channels(mcs, context->settings);
837 client_data = Stream_New(NULL, 512);
838
839 if (!client_data)
840 {
841 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
842 return FALSE;
843 }
844
845 if (!gcc_write_client_data_blocks(client_data, mcs))
846 goto out;
847 gcc_CCrq = Stream_New(NULL, 1024);
848
849 if (!gcc_CCrq)
850 {
851 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
852 goto out;
853 }
854
855 if (!gcc_write_conference_create_request(gcc_CCrq, client_data))
856 goto out;
857 length = Stream_GetPosition(gcc_CCrq) + 7;
858 s = Stream_New(NULL, 1024 + length);
859
860 if (!s)
861 {
862 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
863 goto out;
864 }
865
866 bm = Stream_GetPosition(s);
867 Stream_Seek(s, 7);
868
869 if (!mcs_write_connect_initial(s, mcs, gcc_CCrq))
870 {
871 WLog_Print(mcs->log, WLOG_ERROR, "mcs_write_connect_initial failed!");
872 goto out;
873 }
874
875 em = Stream_GetPosition(s);
876 length = (em - bm);
877 if (length > UINT16_MAX)
878 goto out;
879 Stream_SetPosition(s, bm);
880 if (!tpkt_write_header(s, (UINT16)length))
881 goto out;
882 if (!tpdu_write_data(s))
883 goto out;
884 Stream_SetPosition(s, em);
885 Stream_SealLength(s);
886 status = transport_write(mcs->transport, s);
887out:
888 Stream_Free(s, TRUE);
889 Stream_Free(gcc_CCrq, TRUE);
890 Stream_Free(client_data, TRUE);
891 return (status < 0 ? FALSE : TRUE);
892}
893
900BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
901{
902 size_t length = 0;
903 UINT16 tlength = 0;
904 BYTE result = 0;
905 UINT16 li = 0;
906 UINT32 calledConnectId = 0;
907
908 if (!mcs || !s)
909 return FALSE;
910
911 if (!tpkt_read_header(s, &tlength))
912 return FALSE;
913
914 if (!tpdu_read_data(s, &li, tlength))
915 return FALSE;
916
917 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
918 !ber_read_enumerated(s, &result, MCS_Result_enum_length) ||
919 !ber_read_integer(s, &calledConnectId) ||
920 !mcs_read_domain_parameters(s, &(mcs->domainParameters)) ||
921 !ber_read_octet_string_tag(s, &length))
922 {
923 return FALSE;
924 }
925
926 if (!gcc_read_conference_create_response(s, mcs))
927 {
928 WLog_Print(mcs->log, WLOG_ERROR, "gcc_read_conference_create_response failed");
929 return FALSE;
930 }
931
932 return tpkt_ensure_stream_consumed(mcs->log, s, tlength);
933}
934
941BOOL mcs_send_connect_response(rdpMcs* mcs)
942{
943 size_t length = 0;
944 int status = -1;
945 wStream* s = NULL;
946 size_t bm = 0;
947 size_t em = 0;
948 wStream* gcc_CCrsp = NULL;
949 wStream* server_data = NULL;
950
951 if (!mcs)
952 return FALSE;
953
954 server_data = Stream_New(NULL, 512);
955
956 if (!server_data)
957 {
958 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
959 return FALSE;
960 }
961
962 if (!gcc_write_server_data_blocks(server_data, mcs))
963 goto out;
964
965 gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data));
966
967 if (!gcc_CCrsp)
968 {
969 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
970 goto out;
971 }
972
973 if (!gcc_write_conference_create_response(gcc_CCrsp, server_data))
974 goto out;
975 length = Stream_GetPosition(gcc_CCrsp) + 7;
976 s = Stream_New(NULL, length + 1024);
977
978 if (!s)
979 {
980 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
981 goto out;
982 }
983
984 bm = Stream_GetPosition(s);
985 Stream_Seek(s, 7);
986
987 if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
988 goto out;
989
990 em = Stream_GetPosition(s);
991 length = (em - bm);
992 if (length > UINT16_MAX)
993 goto out;
994 Stream_SetPosition(s, bm);
995 if (!tpkt_write_header(s, (UINT16)length))
996 goto out;
997 if (!tpdu_write_data(s))
998 goto out;
999 Stream_SetPosition(s, em);
1000 Stream_SealLength(s);
1001 status = transport_write(mcs->transport, s);
1002out:
1003 Stream_Free(s, TRUE);
1004 Stream_Free(gcc_CCrsp, TRUE);
1005 Stream_Free(server_data, TRUE);
1006 return (status < 0) ? FALSE : TRUE;
1007}
1008
1016BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
1017{
1018 UINT16 length = 0;
1019 UINT32 subHeight = 0;
1020 UINT32 subInterval = 0;
1021
1022 WINPR_ASSERT(mcs);
1023 WINPR_ASSERT(s);
1024
1025 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ErectDomainRequest, &length, NULL))
1026 return FALSE;
1027
1028 if (!per_read_integer(s, &subHeight)) /* subHeight (INTEGER) */
1029 return FALSE;
1030
1031 if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
1032 return FALSE;
1033
1034 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1035}
1036
1043BOOL mcs_send_erect_domain_request(rdpMcs* mcs)
1044{
1045 wStream* s = NULL;
1046 int status = 0;
1047 UINT16 length = 12;
1048
1049 if (!mcs)
1050 return FALSE;
1051
1052 s = Stream_New(NULL, length);
1053
1054 if (!s)
1055 {
1056 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
1057 return FALSE;
1058 }
1059
1060 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0);
1061 per_write_integer(s, 0); /* subHeight (INTEGER) */
1062 per_write_integer(s, 0); /* subInterval (INTEGER) */
1063 Stream_SealLength(s);
1064 status = transport_write(mcs->transport, s);
1065 Stream_Free(s, TRUE);
1066 return (status < 0) ? FALSE : TRUE;
1067}
1068
1076BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s)
1077{
1078 UINT16 length = 0;
1079
1080 if (!mcs || !s)
1081 return FALSE;
1082
1083 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_AttachUserRequest, &length, NULL))
1084 return FALSE;
1085 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1086}
1087
1094BOOL mcs_send_attach_user_request(rdpMcs* mcs)
1095{
1096 wStream* s = NULL;
1097 int status = 0;
1098 UINT16 length = 8;
1099
1100 if (!mcs)
1101 return FALSE;
1102
1103 s = Stream_New(NULL, length);
1104
1105 if (!s)
1106 {
1107 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
1108 return FALSE;
1109 }
1110
1111 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0);
1112 Stream_SealLength(s);
1113 status = transport_write(mcs->transport, s);
1114 Stream_Free(s, TRUE);
1115 return (status < 0) ? FALSE : TRUE;
1116}
1117
1124BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
1125{
1126 BYTE result = 0;
1127 UINT16 length = 0;
1128
1129 if (!mcs || !s)
1130 return FALSE;
1131
1132 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_AttachUserConfirm, &length, NULL))
1133 return FALSE;
1134 if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1135 return FALSE;
1136 if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1137 return FALSE;
1138 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1139}
1140
1147BOOL mcs_send_attach_user_confirm(rdpMcs* mcs)
1148{
1149 wStream* s = NULL;
1150 int status = 0;
1151 UINT16 length = 11;
1152
1153 if (!mcs)
1154 return FALSE;
1155
1156 s = Stream_New(NULL, length);
1157
1158 if (!s)
1159 {
1160 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
1161 return FALSE;
1162 }
1163
1164 mcs->userId = mcs->baseChannelId++;
1165 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2);
1166 per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
1167 per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
1168 Stream_SealLength(s);
1169 status = transport_write(mcs->transport, s);
1170 Stream_Free(s, TRUE);
1171 return (status < 0) ? FALSE : TRUE;
1172}
1173
1181BOOL mcs_recv_channel_join_request(rdpMcs* mcs, const rdpSettings* settings, wStream* s,
1182 UINT16* channelId)
1183{
1184 UINT16 length = 0;
1185 UINT16 userId = 0;
1186
1187 if (!mcs || !s || !channelId)
1188 return FALSE;
1189
1190 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ChannelJoinRequest, &length, NULL))
1191 return FALSE;
1192
1193 if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID))
1194 return FALSE;
1195 if (userId != mcs->userId)
1196 {
1197 if (freerdp_settings_get_bool(settings, FreeRDP_TransportDumpReplay))
1198 mcs->userId = userId;
1199 else
1200 return FALSE;
1201 }
1202 if (!per_read_integer16(s, channelId, 0))
1203 return FALSE;
1204
1205 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1206}
1207
1218BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId)
1219{
1220 wStream* s = NULL;
1221 int status = 0;
1222 UINT16 length = 12;
1223
1224 WINPR_ASSERT(mcs);
1225
1226 s = Stream_New(NULL, length);
1227
1228 if (!s)
1229 {
1230 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
1231 return FALSE;
1232 }
1233
1234 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0);
1235 per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID);
1236 per_write_integer16(s, channelId, 0);
1237 Stream_SealLength(s);
1238 status = transport_write(mcs->transport, s);
1239 Stream_Free(s, TRUE);
1240 return (status < 0) ? FALSE : TRUE;
1241}
1242
1249BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId)
1250{
1251 UINT16 length = 0;
1252 BYTE result = 0;
1253 UINT16 initiator = 0;
1254 UINT16 requested = 0;
1255
1256 WINPR_ASSERT(mcs);
1257 WINPR_ASSERT(channelId);
1258
1259 if (!mcs_read_domain_mcspdu_header(mcs->log, s, DomainMCSPDU_ChannelJoinConfirm, &length, NULL))
1260 return FALSE;
1261
1262 if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1263 return FALSE;
1264 if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1265 return FALSE;
1266 if (!per_read_integer16(s, &requested, 0)) /* requested (ChannelId) */
1267 return FALSE;
1268 if (!per_read_integer16(s, channelId, 0)) /* channelId */
1269 return FALSE;
1270 return tpkt_ensure_stream_consumed(mcs->log, s, length);
1271}
1272
1279BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId)
1280{
1281 wStream* s = NULL;
1282 int status = -1;
1283 UINT16 length = 15;
1284
1285 if (!mcs)
1286 return FALSE;
1287
1288 s = Stream_New(NULL, length);
1289
1290 if (!s)
1291 {
1292 WLog_Print(mcs->log, WLOG_ERROR, "Stream_New failed!");
1293 return FALSE;
1294 }
1295
1296 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2))
1297 goto fail;
1298 if (!per_write_enumerated(s, 0, MCS_Result_enum_length)) /* result */
1299 goto fail;
1300 if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1301 goto fail;
1302 if (!per_write_integer16(s, channelId, 0)) /* requested (ChannelId) */
1303 goto fail;
1304 if (!per_write_integer16(s, channelId, 0)) /* channelId */
1305 goto fail;
1306 Stream_SealLength(s);
1307 status = transport_write(mcs->transport, s);
1308fail:
1309 Stream_Free(s, TRUE);
1310 return (status < 0) ? FALSE : TRUE;
1311}
1312
1318BOOL mcs_recv_disconnect_provider_ultimatum(WINPR_ATTR_UNUSED rdpMcs* mcs, wStream* s, int* reason)
1319{
1320 BYTE b1 = 0;
1321 BYTE b2 = 0;
1322
1323 WINPR_ASSERT(mcs);
1324 WINPR_ASSERT(s);
1325 WINPR_ASSERT(reason);
1326
1327 /*
1328 * http://msdn.microsoft.com/en-us/library/cc240872.aspx:
1329 *
1330 * PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
1331 * 21 80
1332 *
1333 * 0x21:
1334 * 0 - --\
1335 * 0 - |
1336 * 1 - | CHOICE: From DomainMCSPDU select disconnectProviderUltimatum (8)
1337 * 0 - | of type DisconnectProviderUltimatum
1338 * 0 - |
1339 * 0 - --/
1340 * 0 - --\
1341 * 1 - |
1342 * | DisconnectProviderUltimatum::reason = rn-user-requested (3)
1343 * 0x80: |
1344 * 1 - --/
1345 * 0 - padding
1346 * 0 - padding
1347 * 0 - padding
1348 * 0 - padding
1349 * 0 - padding
1350 * 0 - padding
1351 * 0 - padding
1352 */
1353
1354 if (!Stream_CheckAndLogRequiredLengthWLog(mcs->log, s, 1))
1355 return FALSE;
1356
1357 Stream_Rewind_UINT8(s);
1358 Stream_Read_UINT8(s, b1);
1359 Stream_Read_UINT8(s, b2);
1360 *reason = ((b1 & 0x01) << 1) | (b2 >> 7);
1361 return TRUE;
1362}
1363
1369BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs, enum Disconnect_Ultimatum reason)
1370{
1371 wStream* s = NULL;
1372 int status = -1;
1373 UINT16 length = 9;
1374
1375 WINPR_ASSERT(mcs);
1376
1377 s = Stream_New(NULL, length);
1378
1379 if (!s)
1380 goto fail;
1381
1382 if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1))
1383 goto fail;
1384
1385 if (!per_write_enumerated(s, 0x80, WINPR_ASSERTING_INT_CAST(BYTE, reason)))
1386 goto fail;
1387 status = transport_write(mcs->transport, s);
1388fail:
1389 WLog_Print(mcs->log, WLOG_DEBUG, "sending DisconnectProviderUltimatum(%s)",
1390 freerdp_disconnect_reason_string((int)reason));
1391 Stream_Free(s, TRUE);
1392 return (status < 0) ? FALSE : TRUE;
1393}
1394
1395BOOL mcs_client_begin(rdpMcs* mcs)
1396{
1397 rdpContext* context = NULL;
1398
1399 if (!mcs || !mcs->transport)
1400 return FALSE;
1401
1402 context = transport_get_context(mcs->transport);
1403
1404 if (!context)
1405 return FALSE;
1406
1407 /* First transition state, we need this to trigger session recording */
1408 if (!mcs_send_connect_initial(mcs))
1409 {
1410 freerdp_set_last_error_if_not(context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
1411
1412 WLog_Print(mcs->log, WLOG_ERROR, "Error: unable to send MCS Connect Initial");
1413 return FALSE;
1414 }
1415
1416 return TRUE;
1417}
1418
1425rdpMcs* mcs_new(rdpTransport* transport)
1426{
1427 rdpMcs* mcs = NULL;
1428
1429 mcs = (rdpMcs*)calloc(1, sizeof(rdpMcs));
1430
1431 if (!mcs)
1432 return NULL;
1433 mcs->log = WLog_Get(MCS_TAG);
1434 WINPR_ASSERT(mcs->log);
1435
1436 mcs->transport = transport;
1437 mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
1438 mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
1439 mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
1440 mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF);
1441 mcs->channelCount = 0;
1442 mcs->channelMaxCount = CHANNEL_MAX_COUNT;
1443 mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
1444 mcs->channels = (rdpMcsChannel*)calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel));
1445
1446 if (!mcs->channels)
1447 goto out_free;
1448
1449 return mcs;
1450out_free:
1451 free(mcs);
1452 return NULL;
1453}
1454
1460void mcs_free(rdpMcs* mcs)
1461{
1462 if (mcs)
1463 {
1464 free(mcs->channels);
1465 free(mcs);
1466 }
1467}
1468
1469BOOL mcs_server_apply_to_settings(const rdpMcs* mcs, rdpSettings* settings)
1470{
1471 BOOL rc = FALSE;
1472
1473 WINPR_ASSERT(mcs);
1474 WINPR_ASSERT(settings);
1475
1476 if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, mcs->channelCount))
1477 goto fail;
1478
1479 for (UINT32 x = 0; x < mcs->channelCount; x++)
1480 {
1481 const rdpMcsChannel* current = &mcs->channels[x];
1482 CHANNEL_DEF def = { 0 };
1483 def.options = current->options;
1484 memcpy(def.name, current->Name, sizeof(def.name));
1485 if (!freerdp_settings_set_pointer_array(settings, FreeRDP_ChannelDefArray, x, &def))
1486 goto fail;
1487 }
1488
1489 rc = TRUE;
1490fail:
1491 if (!rc)
1492 WLog_Print(mcs->log, WLOG_WARN, "failed to apply settings");
1493
1494 return rc;
1495}
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.