1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * T.125 Multipoint Communication Service (MCS) Protocol
4 *
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 * Copyright 2015 Thincast Technologies GmbH
7 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8 * Copyright 2017 Armin Novak <armin.novak@thincast.com>
9 * Copyright 2017 Thincast Technologies GmbH
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <winpr/crt.h>
29 #include <freerdp/log.h>
30
31 #include "gcc.h"
32
33 #include "mcs.h"
34 #include "tpdu.h"
35 #include "tpkt.h"
36 #include "client.h"
37 #include "connection.h"
38
39 #define TAG FREERDP_TAG("core")
40
41 /**
42 * T.125 MCS is defined in:
43 *
44 * http://www.itu.int/rec/T-REC-T.125-199802-I/
45 * ITU-T T.125 Multipoint Communication Service Protocol Specification
46 */
47
48 /**
49 * Connect-Initial ::= [APPLICATION 101] IMPLICIT SEQUENCE
50 * {
51 * callingDomainSelector OCTET_STRING,
52 * calledDomainSelector OCTET_STRING,
53 * upwardFlag BOOLEAN,
54 * targetParameters DomainParameters,
55 * minimumParameters DomainParameters,
56 * maximumParameters DomainParameters,
57 * userData OCTET_STRING
58 * }
59 *
60 * DomainParameters ::= SEQUENCE
61 * {
62 * maxChannelIds INTEGER (0..MAX),
63 * maxUserIds INTEGER (0..MAX),
64 * maxTokenIds INTEGER (0..MAX),
65 * numPriorities INTEGER (0..MAX),
66 * minThroughput INTEGER (0..MAX),
67 * maxHeight INTEGER (0..MAX),
68 * maxMCSPDUsize INTEGER (0..MAX),
69 * protocolVersion INTEGER (0..MAX)
70 * }
71 *
72 * Connect-Response ::= [APPLICATION 102] IMPLICIT SEQUENCE
73 * {
74 * result Result,
75 * calledConnectId INTEGER (0..MAX),
76 * domainParameters DomainParameters,
77 * userData OCTET_STRING
78 * }
79 *
80 * Result ::= ENUMERATED
81 * {
82 * rt-successful (0),
83 * rt-domain-merging (1),
84 * rt-domain-not-hierarchical (2),
85 * rt-no-such-channel (3),
86 * rt-no-such-domain (4),
87 * rt-no-such-user (5),
88 * rt-not-admitted (6),
89 * rt-other-user-id (7),
90 * rt-parameters-unacceptable (8),
91 * rt-token-not-available (9),
92 * rt-token-not-possessed (10),
93 * rt-too-many-channels (11),
94 * rt-too-many-tokens (12),
95 * rt-too-many-users (13),
96 * rt-unspecified-failure (14),
97 * rt-user-rejected (15)
98 * }
99 *
100 * ErectDomainRequest ::= [APPLICATION 1] IMPLICIT SEQUENCE
101 * {
102 * subHeight INTEGER (0..MAX),
103 * subInterval INTEGER (0..MAX)
104 * }
105 *
106 * AttachUserRequest ::= [APPPLICATION 10] IMPLICIT SEQUENCE
107 * {
108 * }
109 *
110 * AttachUserConfirm ::= [APPLICATION 11] IMPLICIT SEQUENCE
111 * {
112 * result Result,
113 * initiator UserId OPTIONAL
114 * }
115 *
116 * ChannelJoinRequest ::= [APPLICATION 14] IMPLICIT SEQUENCE
117 * {
118 * initiator UserId,
119 * channelId ChannelId
120 * }
121 *
122 * ChannelJoinConfirm ::= [APPLICATION 15] IMPLICIT SEQUENCE
123 * {
124 * result Result,
125 * initiator UserId,
126 * requested ChannelId,
127 * channelId ChannelId OPTIONAL
128 * }
129 *
130 * SendDataRequest ::= [APPLICATION 25] IMPLICIT SEQUENCE
131 * {
132 * initiator UserId,
133 * channelId ChannelId,
134 * dataPriority DataPriority,
135 * segmentation Segmentation,
136 * userData OCTET_STRING
137 * }
138 *
139 * DataPriority ::= CHOICE
140 * {
141 * top NULL,
142 * high NULL,
143 * medium NULL,
144 * low NULL,
145 * ...
146 * }
147 *
148 * Segmentation ::= BIT_STRING
149 * {
150 * begin (0),
151 * end (1)
152 * } (SIZE(2))
153 *
154 * SendDataIndication ::= SEQUENCE
155 * {
156 * initiator UserId,
157 * channelId ChannelId,
158 * reliability BOOLEAN,
159 * domainReferenceID INTEGER (0..65535) OPTIONAL,
160 * dataPriority DataPriority,
161 * segmentation Segmentation,
162 * userData OCTET_STRING,
163 * totalDataSize INTEGER OPTIONAL,
164 * nonStandard SEQUENCE OF NonStandardParameter OPTIONAL,
165 * ...
166 * }
167 *
168 */
169
170 static const BYTE callingDomainSelector[1] = "\x01";
171 static const BYTE calledDomainSelector[1] = "\x01";
172
173 /*
174 static const char* const mcs_result_enumerated[] =
175 {
176 "rt-successful",
177 "rt-domain-merging",
178 "rt-domain-not-hierarchical",
179 "rt-no-such-channel",
180 "rt-no-such-domain",
181 "rt-no-such-user",
182 "rt-not-admitted",
183 "rt-other-user-id",
184 "rt-parameters-unacceptable",
185 "rt-token-not-available",
186 "rt-token-not-possessed",
187 "rt-too-many-channels",
188 "rt-too-many-tokens",
189 "rt-too-many-users",
190 "rt-unspecified-failure",
191 "rt-user-rejected"
192 };
193 */
194
195 static BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters,
196 DomainParameters* minimumParameters,
197 DomainParameters* maximumParameters,
198 DomainParameters* pOutParameters);
199
200 static BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData);
201 static BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData);
202 static BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU,
203 UINT16* length);
204
mcs_initialize_client_channels(rdpMcs * mcs,rdpSettings * settings)205 static int mcs_initialize_client_channels(rdpMcs* mcs, rdpSettings* settings)
206 {
207 UINT32 index;
208
209 if (!mcs || !settings)
210 return -1;
211
212 mcs->channelCount = settings->ChannelCount;
213
214 if (mcs->channelCount > mcs->channelMaxCount)
215 mcs->channelCount = mcs->channelMaxCount;
216
217 ZeroMemory(mcs->channels, sizeof(rdpMcsChannel) * mcs->channelMaxCount);
218
219 for (index = 0; index < mcs->channelCount; index++)
220 {
221 CopyMemory(mcs->channels[index].Name, settings->ChannelDefArray[index].name, 8);
222 mcs->channels[index].options = settings->ChannelDefArray[index].options;
223 }
224
225 return 0;
226 }
227
228 /**
229 * Read a DomainMCSPDU header.
230 * @param s stream
231 * @param domainMCSPDU DomainMCSPDU type
232 * @param length TPKT length
233 * @return
234 */
235
mcs_read_domain_mcspdu_header(wStream * s,enum DomainMCSPDU * domainMCSPDU,UINT16 * length)236 BOOL mcs_read_domain_mcspdu_header(wStream* s, enum DomainMCSPDU* domainMCSPDU, UINT16* length)
237 {
238 UINT16 li;
239 BYTE choice;
240 enum DomainMCSPDU MCSPDU;
241
242 if (!s || !domainMCSPDU || !length)
243 return FALSE;
244
245 if (!tpkt_read_header(s, length))
246 return FALSE;
247
248 if (!tpdu_read_data(s, &li, *length))
249 return FALSE;
250
251 MCSPDU = *domainMCSPDU;
252
253 if (!per_read_choice(s, &choice))
254 return FALSE;
255
256 *domainMCSPDU = (choice >> 2);
257
258 if (*domainMCSPDU != MCSPDU)
259 return FALSE;
260
261 return TRUE;
262 }
263
264 /**
265 * Write a DomainMCSPDU header.
266 * @param s stream
267 * @param domainMCSPDU DomainMCSPDU type
268 * @param length TPKT length
269 */
270
mcs_write_domain_mcspdu_header(wStream * s,enum DomainMCSPDU domainMCSPDU,UINT16 length,BYTE options)271 void mcs_write_domain_mcspdu_header(wStream* s, enum DomainMCSPDU domainMCSPDU, UINT16 length,
272 BYTE options)
273 {
274 tpkt_write_header(s, length);
275 tpdu_write_data(s);
276 per_write_choice(s, (BYTE)((domainMCSPDU << 2) | options));
277 }
278
279 /**
280 * Initialize MCS Domain Parameters.
281 * @param domainParameters domain parameters
282 * @param maxChannelIds max channel ids
283 * @param maxUserIds max user ids
284 * @param maxTokenIds max token ids
285 * @param maxMCSPDUsize max MCS PDU size
286 */
287
mcs_init_domain_parameters(DomainParameters * domainParameters,UINT32 maxChannelIds,UINT32 maxUserIds,UINT32 maxTokenIds,UINT32 maxMCSPDUsize)288 static BOOL mcs_init_domain_parameters(DomainParameters* domainParameters, UINT32 maxChannelIds,
289 UINT32 maxUserIds, UINT32 maxTokenIds, UINT32 maxMCSPDUsize)
290 {
291 if (!domainParameters)
292 return FALSE;
293
294 domainParameters->maxChannelIds = maxChannelIds;
295 domainParameters->maxUserIds = maxUserIds;
296 domainParameters->maxTokenIds = maxTokenIds;
297 domainParameters->maxMCSPDUsize = maxMCSPDUsize;
298 domainParameters->numPriorities = 1;
299 domainParameters->minThroughput = 0;
300 domainParameters->maxHeight = 1;
301 domainParameters->protocolVersion = 2;
302 return TRUE;
303 }
304
305 /**
306 * Read MCS Domain Parameters.
307 * @param s stream
308 * @param domainParameters domain parameters
309 */
310
mcs_read_domain_parameters(wStream * s,DomainParameters * domainParameters)311 static BOOL mcs_read_domain_parameters(wStream* s, DomainParameters* domainParameters)
312 {
313 size_t length;
314
315 if (!s || !domainParameters)
316 return FALSE;
317
318 return ber_read_sequence_tag(s, &length) &&
319 ber_read_integer(s, &(domainParameters->maxChannelIds)) &&
320 ber_read_integer(s, &(domainParameters->maxUserIds)) &&
321 ber_read_integer(s, &(domainParameters->maxTokenIds)) &&
322 ber_read_integer(s, &(domainParameters->numPriorities)) &&
323 ber_read_integer(s, &(domainParameters->minThroughput)) &&
324 ber_read_integer(s, &(domainParameters->maxHeight)) &&
325 ber_read_integer(s, &(domainParameters->maxMCSPDUsize)) &&
326 ber_read_integer(s, &(domainParameters->protocolVersion));
327 }
328
329 /**
330 * Write MCS Domain Parameters.
331 * @param s stream
332 * @param domainParameters domain parameters
333 */
334
mcs_write_domain_parameters(wStream * s,DomainParameters * domainParameters)335 static BOOL mcs_write_domain_parameters(wStream* s, DomainParameters* domainParameters)
336 {
337 size_t length;
338 wStream* tmps;
339
340 if (!s || !domainParameters)
341 return FALSE;
342
343 tmps = Stream_New(NULL, Stream_Capacity(s));
344
345 if (!tmps)
346 {
347 WLog_ERR(TAG, "Stream_New failed!");
348 return FALSE;
349 }
350
351 ber_write_integer(tmps, domainParameters->maxChannelIds);
352 ber_write_integer(tmps, domainParameters->maxUserIds);
353 ber_write_integer(tmps, domainParameters->maxTokenIds);
354 ber_write_integer(tmps, domainParameters->numPriorities);
355 ber_write_integer(tmps, domainParameters->minThroughput);
356 ber_write_integer(tmps, domainParameters->maxHeight);
357 ber_write_integer(tmps, domainParameters->maxMCSPDUsize);
358 ber_write_integer(tmps, domainParameters->protocolVersion);
359 length = Stream_GetPosition(tmps);
360 ber_write_sequence_tag(s, length);
361 Stream_Write(s, Stream_Buffer(tmps), length);
362 Stream_Free(tmps, TRUE);
363 return TRUE;
364 }
365
366 #ifdef DEBUG_MCS
367 /**
368 * Print MCS Domain Parameters.
369 * @param domainParameters domain parameters
370 */
371
mcs_print_domain_parameters(DomainParameters * domainParameters)372 static void mcs_print_domain_parameters(DomainParameters* domainParameters)
373 {
374 WLog_INFO(TAG, "DomainParameters {");
375
376 if (domainParameters)
377 {
378 WLog_INFO(TAG, "\tmaxChannelIds:%" PRIu32 "", domainParameters->maxChannelIds);
379 WLog_INFO(TAG, "\tmaxUserIds:%" PRIu32 "", domainParameters->maxUserIds);
380 WLog_INFO(TAG, "\tmaxTokenIds:%" PRIu32 "", domainParameters->maxTokenIds);
381 WLog_INFO(TAG, "\tnumPriorities:%" PRIu32 "", domainParameters->numPriorities);
382 WLog_INFO(TAG, "\tminThroughput:%" PRIu32 "", domainParameters->minThroughput);
383 WLog_INFO(TAG, "\tmaxHeight:%" PRIu32 "", domainParameters->maxHeight);
384 WLog_INFO(TAG, "\tmaxMCSPDUsize:%" PRIu32 "", domainParameters->maxMCSPDUsize);
385 WLog_INFO(TAG, "\tprotocolVersion:%" PRIu32 "", domainParameters->protocolVersion);
386 }
387 else
388 WLog_INFO(TAG, "\tdomainParameters=%p", domainParameters);
389
390 WLog_INFO(TAG, "}");
391 }
392 #endif
393
394 /**
395 * Merge MCS Domain Parameters.
396 * @param domainParameters target parameters
397 * @param domainParameters minimum parameters
398 * @param domainParameters maximum parameters
399 * @param domainParameters output parameters
400 */
401
mcs_merge_domain_parameters(DomainParameters * targetParameters,DomainParameters * minimumParameters,DomainParameters * maximumParameters,DomainParameters * pOutParameters)402 BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters,
403 DomainParameters* minimumParameters,
404 DomainParameters* maximumParameters,
405 DomainParameters* pOutParameters)
406 {
407 /* maxChannelIds */
408 if (!targetParameters || !minimumParameters || !maximumParameters || !pOutParameters)
409 return FALSE;
410
411 if (targetParameters->maxChannelIds >= 4)
412 {
413 pOutParameters->maxChannelIds = targetParameters->maxChannelIds;
414 }
415 else if (maximumParameters->maxChannelIds >= 4)
416 {
417 pOutParameters->maxChannelIds = 4;
418 }
419 else
420 {
421 return FALSE;
422 }
423
424 /* maxUserIds */
425
426 if (targetParameters->maxUserIds >= 3)
427 {
428 pOutParameters->maxUserIds = targetParameters->maxUserIds;
429 }
430 else if (maximumParameters->maxUserIds >= 3)
431 {
432 pOutParameters->maxUserIds = 3;
433 }
434 else
435 {
436 return FALSE;
437 }
438
439 /* maxTokenIds */
440 pOutParameters->maxTokenIds = targetParameters->maxTokenIds;
441
442 /* numPriorities */
443
444 if (minimumParameters->numPriorities <= 1)
445 {
446 pOutParameters->numPriorities = 1;
447 }
448 else
449 {
450 return FALSE;
451 }
452
453 /* minThroughput */
454 pOutParameters->minThroughput = targetParameters->minThroughput;
455
456 /* maxHeight */
457
458 if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1))
459 {
460 pOutParameters->maxHeight = 1;
461 }
462 else
463 {
464 return FALSE;
465 }
466
467 /* maxMCSPDUsize */
468
469 if (targetParameters->maxMCSPDUsize >= 1024)
470 {
471 if (targetParameters->maxMCSPDUsize <= 65528)
472 {
473 pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize;
474 }
475 else if ((minimumParameters->maxMCSPDUsize >= 124) &&
476 (minimumParameters->maxMCSPDUsize <= 65528))
477 {
478 pOutParameters->maxMCSPDUsize = 65528;
479 }
480 else
481 {
482 return FALSE;
483 }
484 }
485 else
486 {
487 if (maximumParameters->maxMCSPDUsize >= 124)
488 {
489 pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize;
490 }
491 else
492 {
493 return FALSE;
494 }
495 }
496
497 /* protocolVersion */
498
499 if ((targetParameters->protocolVersion == 2) ||
500 ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2)))
501 {
502 pOutParameters->protocolVersion = 2;
503 }
504 else
505 {
506 return FALSE;
507 }
508
509 return TRUE;
510 }
511
512 /**
513 * Read an MCS Connect Initial PDU.\n
514 * @msdn{cc240508}
515 * @param mcs MCS module
516 * @param s stream
517 */
518
mcs_recv_connect_initial(rdpMcs * mcs,wStream * s)519 BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
520 {
521 UINT16 li;
522 size_t length;
523 BOOL upwardFlag;
524 UINT16 tlength;
525
526 if (!mcs || !s)
527 return FALSE;
528
529 if (!tpkt_read_header(s, &tlength))
530 return FALSE;
531
532 if (!tpdu_read_data(s, &li, tlength))
533 return FALSE;
534
535 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
536 return FALSE;
537
538 /* callingDomainSelector (OCTET_STRING) */
539 if (!ber_read_octet_string_tag(s, &length) || (Stream_GetRemainingLength(s)) < length)
540 return FALSE;
541
542 Stream_Seek(s, length);
543
544 /* calledDomainSelector (OCTET_STRING) */
545 if (!ber_read_octet_string_tag(s, &length) || (Stream_GetRemainingLength(s)) < length)
546 return FALSE;
547
548 Stream_Seek(s, length);
549
550 /* upwardFlag (BOOLEAN) */
551 if (!ber_read_BOOL(s, &upwardFlag))
552 return FALSE;
553
554 /* targetParameters (DomainParameters) */
555 if (!mcs_read_domain_parameters(s, &mcs->targetParameters))
556 return FALSE;
557
558 /* minimumParameters (DomainParameters) */
559 if (!mcs_read_domain_parameters(s, &mcs->minimumParameters))
560 return FALSE;
561
562 /* maximumParameters (DomainParameters) */
563 if (!mcs_read_domain_parameters(s, &mcs->maximumParameters))
564 return FALSE;
565
566 if (!ber_read_octet_string_tag(s, &length) || (Stream_GetRemainingLength(s)) < length)
567 return FALSE;
568
569 if (!gcc_read_conference_create_request(s, mcs))
570 return FALSE;
571
572 if (!mcs_merge_domain_parameters(&mcs->targetParameters, &mcs->minimumParameters,
573 &mcs->maximumParameters, &mcs->domainParameters))
574 return FALSE;
575
576 return tpkt_ensure_stream_consumed(s, tlength);
577 }
578
579 /**
580 * Write an MCS Connect Initial PDU.\n
581 * @msdn{cc240508}
582 * @param s stream
583 * @param mcs MCS module
584 * @param user_data GCC Conference Create Request
585 */
586
mcs_write_connect_initial(wStream * s,rdpMcs * mcs,wStream * userData)587 BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData)
588 {
589 size_t length;
590 wStream* tmps;
591 BOOL ret = FALSE;
592
593 if (!s || !mcs || !userData)
594 return FALSE;
595
596 tmps = Stream_New(NULL, Stream_Capacity(s));
597
598 if (!tmps)
599 {
600 WLog_ERR(TAG, "Stream_New failed!");
601 return FALSE;
602 }
603
604 /* callingDomainSelector (OCTET_STRING) */
605 ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector));
606 /* calledDomainSelector (OCTET_STRING) */
607 ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector));
608 /* upwardFlag (BOOLEAN) */
609 ber_write_BOOL(tmps, TRUE);
610
611 /* targetParameters (DomainParameters) */
612 if (!mcs_write_domain_parameters(tmps, &mcs->targetParameters))
613 goto out;
614
615 /* minimumParameters (DomainParameters) */
616 if (!mcs_write_domain_parameters(tmps, &mcs->minimumParameters))
617 goto out;
618
619 /* maximumParameters (DomainParameters) */
620 if (!mcs_write_domain_parameters(tmps, &mcs->maximumParameters))
621 goto out;
622
623 /* userData (OCTET_STRING) */
624 ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
625 length = Stream_GetPosition(tmps);
626 /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
627 ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
628 Stream_Write(s, Stream_Buffer(tmps), length);
629 ret = TRUE;
630 out:
631 Stream_Free(tmps, TRUE);
632 return ret;
633 }
634
635 /**
636 * Write an MCS Connect Response PDU.\n
637 * @msdn{cc240508}
638 * @param s stream
639 * @param mcs MCS module
640 * @param user_data GCC Conference Create Response
641 */
642
mcs_write_connect_response(wStream * s,rdpMcs * mcs,wStream * userData)643 BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData)
644 {
645 size_t length;
646 wStream* tmps;
647 BOOL ret = FALSE;
648
649 if (!s || !mcs || !userData)
650 return FALSE;
651
652 tmps = Stream_New(NULL, Stream_Capacity(s));
653
654 if (!tmps)
655 {
656 WLog_ERR(TAG, "Stream_New failed!");
657 return FALSE;
658 }
659
660 ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
661 ber_write_integer(tmps, 0); /* calledConnectId */
662
663 if (!mcs_write_domain_parameters(tmps, &(mcs->domainParameters)))
664 goto out;
665
666 /* userData (OCTET_STRING) */
667 ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
668 length = Stream_GetPosition(tmps);
669 ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
670 Stream_Write(s, Stream_Buffer(tmps), length);
671 ret = TRUE;
672 out:
673 Stream_Free(tmps, TRUE);
674 return ret;
675 }
676
677 /**
678 * Send MCS Connect Initial.\n
679 * @msdn{cc240508}
680 * @param mcs mcs module
681 */
682
mcs_send_connect_initial(rdpMcs * mcs)683 BOOL mcs_send_connect_initial(rdpMcs* mcs)
684 {
685 int status = -1;
686 size_t length;
687 wStream* s = NULL;
688 size_t bm, em;
689 wStream* gcc_CCrq = NULL;
690 wStream* client_data = NULL;
691
692 if (!mcs)
693 return FALSE;
694
695 mcs_initialize_client_channels(mcs, mcs->settings);
696 client_data = Stream_New(NULL, 512);
697
698 if (!client_data)
699 {
700 WLog_ERR(TAG, "Stream_New failed!");
701 return FALSE;
702 }
703
704 if (!gcc_write_client_data_blocks(client_data, mcs))
705 goto out;
706
707 gcc_CCrq = Stream_New(NULL, 1024);
708
709 if (!gcc_CCrq)
710 {
711 WLog_ERR(TAG, "Stream_New failed!");
712 goto out;
713 }
714
715 gcc_write_conference_create_request(gcc_CCrq, client_data);
716 length = Stream_GetPosition(gcc_CCrq) + 7;
717 s = Stream_New(NULL, 1024 + length);
718
719 if (!s)
720 {
721 WLog_ERR(TAG, "Stream_New failed!");
722 goto out;
723 }
724
725 bm = Stream_GetPosition(s);
726 Stream_Seek(s, 7);
727
728 if (!mcs_write_connect_initial(s, mcs, gcc_CCrq))
729 {
730 WLog_ERR(TAG, "mcs_write_connect_initial failed!");
731 goto out;
732 }
733
734 em = Stream_GetPosition(s);
735 length = (em - bm);
736 if (length > UINT16_MAX)
737 goto out;
738 Stream_SetPosition(s, bm);
739 if (!tpkt_write_header(s, (UINT16)length))
740 goto out;
741 tpdu_write_data(s);
742 Stream_SetPosition(s, em);
743 Stream_SealLength(s);
744 status = transport_write(mcs->transport, s);
745 out:
746 Stream_Free(s, TRUE);
747 Stream_Free(gcc_CCrq, TRUE);
748 Stream_Free(client_data, TRUE);
749 return (status < 0 ? FALSE : TRUE);
750 }
751
752 /**
753 * Read MCS Connect Response.\n
754 * @msdn{cc240501}
755 * @param mcs mcs module
756 */
757
mcs_recv_connect_response(rdpMcs * mcs,wStream * s)758 BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
759 {
760 size_t length;
761 UINT16 tlength;
762 BYTE result;
763 UINT16 li;
764 UINT32 calledConnectId;
765
766 if (!mcs || !s)
767 return FALSE;
768
769 if (!tpkt_read_header(s, &tlength))
770 return FALSE;
771
772 if (!tpdu_read_data(s, &li, tlength))
773 return FALSE;
774
775 if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
776 !ber_read_enumerated(s, &result, MCS_Result_enum_length) ||
777 !ber_read_integer(s, &calledConnectId) ||
778 !mcs_read_domain_parameters(s, &(mcs->domainParameters)) ||
779 !ber_read_octet_string_tag(s, &length))
780 {
781 return FALSE;
782 }
783
784 if (!gcc_read_conference_create_response(s, mcs))
785 {
786 WLog_ERR(TAG, "gcc_read_conference_create_response failed");
787 return FALSE;
788 }
789
790 return tpkt_ensure_stream_consumed(s, tlength);
791 }
792
793 /**
794 * Send MCS Connect Response.\n
795 * @msdn{cc240501}
796 * @param mcs mcs module
797 */
798
mcs_send_connect_response(rdpMcs * mcs)799 BOOL mcs_send_connect_response(rdpMcs* mcs)
800 {
801 size_t length;
802 int status = -1;
803 wStream* s = NULL;
804 size_t bm, em;
805 wStream* gcc_CCrsp = NULL;
806 wStream* server_data = NULL;
807
808 if (!mcs)
809 return FALSE;
810
811 server_data = Stream_New(NULL, 512);
812
813 if (!server_data)
814 {
815 WLog_ERR(TAG, "Stream_New failed!");
816 return FALSE;
817 }
818
819 if (!gcc_write_server_data_blocks(server_data, mcs))
820 goto out;
821
822 gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data));
823
824 if (!gcc_CCrsp)
825 {
826 WLog_ERR(TAG, "Stream_New failed!");
827 goto out;
828 }
829
830 gcc_write_conference_create_response(gcc_CCrsp, server_data);
831 length = Stream_GetPosition(gcc_CCrsp) + 7;
832 s = Stream_New(NULL, length + 1024);
833
834 if (!s)
835 {
836 WLog_ERR(TAG, "Stream_New failed!");
837 goto out;
838 }
839
840 bm = Stream_GetPosition(s);
841 Stream_Seek(s, 7);
842
843 if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
844 goto out;
845
846 em = Stream_GetPosition(s);
847 length = (em - bm);
848 if (length > UINT16_MAX)
849 goto out;
850 Stream_SetPosition(s, bm);
851 if (!tpkt_write_header(s, (UINT16)length))
852 goto out;
853 tpdu_write_data(s);
854 Stream_SetPosition(s, em);
855 Stream_SealLength(s);
856 status = transport_write(mcs->transport, s);
857 out:
858 Stream_Free(s, TRUE);
859 Stream_Free(gcc_CCrsp, TRUE);
860 Stream_Free(server_data, TRUE);
861 return (status < 0) ? FALSE : TRUE;
862 }
863
864 /**
865 * Read MCS Erect Domain Request.\n
866 * @msdn{cc240523}
867 * @param mcs
868 * @param s stream
869 */
870
mcs_recv_erect_domain_request(rdpMcs * mcs,wStream * s)871 BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
872 {
873 UINT16 length;
874 UINT32 subHeight;
875 UINT32 subInterval;
876 enum DomainMCSPDU MCSPDU;
877
878 if (!mcs || !s)
879 return FALSE;
880
881 MCSPDU = DomainMCSPDU_ErectDomainRequest;
882
883 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
884 return FALSE;
885
886 if (!per_read_integer(s, &subHeight)) /* subHeight (INTEGER) */
887 return FALSE;
888
889 if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
890 return FALSE;
891
892 return tpkt_ensure_stream_consumed(s, length);
893 }
894
895 /**
896 * Send MCS Erect Domain Request.\n
897 * @msdn{cc240523}
898 * @param mcs
899 */
900
mcs_send_erect_domain_request(rdpMcs * mcs)901 BOOL mcs_send_erect_domain_request(rdpMcs* mcs)
902 {
903 wStream* s;
904 int status;
905 UINT16 length = 12;
906
907 if (!mcs)
908 return FALSE;
909
910 s = Stream_New(NULL, length);
911
912 if (!s)
913 {
914 WLog_ERR(TAG, "Stream_New failed!");
915 return FALSE;
916 }
917
918 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0);
919 per_write_integer(s, 0); /* subHeight (INTEGER) */
920 per_write_integer(s, 0); /* subInterval (INTEGER) */
921 Stream_SealLength(s);
922 status = transport_write(mcs->transport, s);
923 Stream_Free(s, TRUE);
924 return (status < 0) ? FALSE : TRUE;
925 }
926
927 /**
928 * Read MCS Attach User Request.\n
929 * @msdn{cc240524}
930 * @param mcs mcs module
931 * @param s stream
932 */
933
mcs_recv_attach_user_request(rdpMcs * mcs,wStream * s)934 BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s)
935 {
936 UINT16 length;
937 enum DomainMCSPDU MCSPDU;
938
939 if (!mcs || !s)
940 return FALSE;
941
942 MCSPDU = DomainMCSPDU_AttachUserRequest;
943 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
944 return FALSE;
945 return tpkt_ensure_stream_consumed(s, length);
946 }
947
948 /**
949 * Send MCS Attach User Request.\n
950 * @msdn{cc240524}
951 * @param mcs mcs module
952 */
953
mcs_send_attach_user_request(rdpMcs * mcs)954 BOOL mcs_send_attach_user_request(rdpMcs* mcs)
955 {
956 wStream* s;
957 int status;
958 UINT16 length = 8;
959
960 if (!mcs)
961 return FALSE;
962
963 s = Stream_New(NULL, length);
964
965 if (!s)
966 {
967 WLog_ERR(TAG, "Stream_New failed!");
968 return FALSE;
969 }
970
971 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0);
972 Stream_SealLength(s);
973 status = transport_write(mcs->transport, s);
974 Stream_Free(s, TRUE);
975 return (status < 0) ? FALSE : TRUE;
976 }
977
978 /**
979 * Read MCS Attach User Confirm.\n
980 * @msdn{cc240525}
981 * @param mcs mcs module
982 */
983
mcs_recv_attach_user_confirm(rdpMcs * mcs,wStream * s)984 BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
985 {
986 BYTE result;
987 UINT16 length;
988 enum DomainMCSPDU MCSPDU;
989
990 if (!mcs || !s)
991 return FALSE;
992
993 MCSPDU = DomainMCSPDU_AttachUserConfirm;
994 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
995 return FALSE;
996 if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
997 return FALSE;
998 if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
999 return FALSE;
1000 return tpkt_ensure_stream_consumed(s, length);
1001 }
1002
1003 /**
1004 * Send MCS Attach User Confirm.\n
1005 * @msdn{cc240525}
1006 * @param mcs mcs module
1007 */
1008
mcs_send_attach_user_confirm(rdpMcs * mcs)1009 BOOL mcs_send_attach_user_confirm(rdpMcs* mcs)
1010 {
1011 wStream* s;
1012 int status;
1013 UINT16 length = 11;
1014
1015 if (!mcs)
1016 return FALSE;
1017
1018 s = Stream_New(NULL, length);
1019
1020 if (!s)
1021 {
1022 WLog_ERR(TAG, "Stream_New failed!");
1023 return FALSE;
1024 }
1025
1026 mcs->userId = mcs->baseChannelId++;
1027 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2);
1028 per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
1029 per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
1030 Stream_SealLength(s);
1031 status = transport_write(mcs->transport, s);
1032 Stream_Free(s, TRUE);
1033 return (status < 0) ? FALSE : TRUE;
1034 }
1035
1036 /**
1037 * Read MCS Channel Join Request.\n
1038 * @msdn{cc240526}
1039 * @param mcs mcs module
1040 * @param s stream
1041 */
1042
mcs_recv_channel_join_request(rdpMcs * mcs,wStream * s,UINT16 * channelId)1043 BOOL mcs_recv_channel_join_request(rdpMcs* mcs, wStream* s, UINT16* channelId)
1044 {
1045 UINT16 length;
1046 UINT16 userId;
1047 enum DomainMCSPDU MCSPDU;
1048
1049 if (!mcs || !s || !channelId)
1050 return FALSE;
1051
1052 MCSPDU = DomainMCSPDU_ChannelJoinRequest;
1053 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
1054 return FALSE;
1055
1056 if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID) && (userId == mcs->userId))
1057 return FALSE;
1058 if (!per_read_integer16(s, channelId, 0))
1059 return FALSE;
1060
1061 return tpkt_ensure_stream_consumed(s, length);
1062 }
1063
1064 /**
1065 * Send MCS Channel Join Request.\n
1066 * @msdn{cc240526}
1067 * @param mcs mcs module
1068 * @param channel_id channel id
1069 */
1070
mcs_send_channel_join_request(rdpMcs * mcs,UINT16 channelId)1071 BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId)
1072 {
1073 wStream* s;
1074 int status;
1075 UINT16 length = 12;
1076
1077 if (!mcs)
1078 return FALSE;
1079
1080 s = Stream_New(NULL, length);
1081
1082 if (!s)
1083 {
1084 WLog_ERR(TAG, "Stream_New failed!");
1085 return FALSE;
1086 }
1087
1088 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0);
1089 per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID);
1090 per_write_integer16(s, channelId, 0);
1091 Stream_SealLength(s);
1092 status = transport_write(mcs->transport, s);
1093 Stream_Free(s, TRUE);
1094 return (status < 0) ? FALSE : TRUE;
1095 }
1096
1097 /**
1098 * Read MCS Channel Join Confirm.\n
1099 * @msdn{cc240527}
1100 * @param mcs mcs module
1101 */
1102
mcs_recv_channel_join_confirm(rdpMcs * mcs,wStream * s,UINT16 * channelId)1103 BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId)
1104 {
1105 BOOL status;
1106 UINT16 length;
1107 BYTE result;
1108 UINT16 initiator;
1109 UINT16 requested;
1110 enum DomainMCSPDU MCSPDU;
1111
1112 if (!mcs || !s || !channelId)
1113 return FALSE;
1114
1115 status = TRUE;
1116 MCSPDU = DomainMCSPDU_ChannelJoinConfirm;
1117 if (!mcs_read_domain_mcspdu_header(s, &MCSPDU, &length))
1118 return FALSE;
1119
1120 if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1121 return FALSE;
1122 if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1123 return FALSE;
1124 if (!per_read_integer16(s, &requested, 0)) /* requested (ChannelId) */
1125 return FALSE;
1126 if (!per_read_integer16(s, channelId, 0)) /* channelId */
1127 return FALSE;
1128 return tpkt_ensure_stream_consumed(s, length);
1129 }
1130
1131 /**
1132 * Send MCS Channel Join Confirm.\n
1133 * @msdn{cc240527}
1134 * @param mcs mcs module
1135 */
1136
mcs_send_channel_join_confirm(rdpMcs * mcs,UINT16 channelId)1137 BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId)
1138 {
1139 wStream* s;
1140 int status;
1141 UINT16 length = 15;
1142
1143 if (!mcs)
1144 return FALSE;
1145
1146 s = Stream_New(NULL, length);
1147
1148 if (!s)
1149 {
1150 WLog_ERR(TAG, "Stream_New failed!");
1151 return FALSE;
1152 }
1153
1154 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2);
1155 per_write_enumerated(s, 0, MCS_Result_enum_length); /* result */
1156 per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
1157 per_write_integer16(s, channelId, 0); /* requested (ChannelId) */
1158 per_write_integer16(s, channelId, 0); /* channelId */
1159 Stream_SealLength(s);
1160 status = transport_write(mcs->transport, s);
1161 Stream_Free(s, TRUE);
1162 return (status < 0) ? FALSE : TRUE;
1163 }
1164
1165 /**
1166 * Receive MCS Disconnect Provider Ultimatum PDU.\n
1167 * @param mcs mcs module
1168 */
1169
mcs_recv_disconnect_provider_ultimatum(rdpMcs * mcs,wStream * s,int * reason)1170 BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason)
1171 {
1172 BYTE b1, b2;
1173
1174 if (!mcs || !s || !reason)
1175 return FALSE;
1176
1177 /*
1178 * http://msdn.microsoft.com/en-us/library/cc240872.aspx:
1179 *
1180 * PER encoded (ALIGNED variant of BASIC-PER) PDU contents:
1181 * 21 80
1182 *
1183 * 0x21:
1184 * 0 - --\
1185 * 0 - |
1186 * 1 - | CHOICE: From DomainMCSPDU select disconnectProviderUltimatum (8)
1187 * 0 - | of type DisconnectProviderUltimatum
1188 * 0 - |
1189 * 0 - --/
1190 * 0 - --\
1191 * 1 - |
1192 * | DisconnectProviderUltimatum::reason = rn-user-requested (3)
1193 * 0x80: |
1194 * 1 - --/
1195 * 0 - padding
1196 * 0 - padding
1197 * 0 - padding
1198 * 0 - padding
1199 * 0 - padding
1200 * 0 - padding
1201 * 0 - padding
1202 */
1203
1204 if (Stream_GetRemainingLength(s) < 1)
1205 return FALSE;
1206
1207 Stream_Rewind_UINT8(s);
1208 Stream_Read_UINT8(s, b1);
1209 Stream_Read_UINT8(s, b2);
1210 *reason = ((b1 & 0x01) << 1) | (b2 >> 7);
1211 return TRUE;
1212 }
1213
1214 /**
1215 * Send MCS Disconnect Provider Ultimatum PDU.\n
1216 * @param mcs mcs module
1217 */
1218
mcs_send_disconnect_provider_ultimatum(rdpMcs * mcs)1219 BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
1220 {
1221 wStream* s;
1222 int status;
1223 UINT16 length = 9;
1224
1225 if (!mcs)
1226 return FALSE;
1227
1228 s = Stream_New(NULL, length);
1229
1230 if (!s)
1231 {
1232 WLog_ERR(TAG, "Stream_New failed!");
1233 return FALSE;
1234 }
1235
1236 mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1);
1237 per_write_enumerated(s, 0x80, 0);
1238 status = transport_write(mcs->transport, s);
1239 Stream_Free(s, TRUE);
1240 return (status < 0) ? FALSE : TRUE;
1241 }
1242
mcs_client_begin(rdpMcs * mcs)1243 BOOL mcs_client_begin(rdpMcs* mcs)
1244 {
1245 rdpContext* context;
1246
1247 if (!mcs || !mcs->transport)
1248 return FALSE;
1249
1250 context = mcs->transport->context;
1251
1252 if (!context)
1253 return FALSE;
1254
1255 if (!mcs_send_connect_initial(mcs))
1256 {
1257 freerdp_set_last_error_if_not(context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
1258
1259 WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
1260 return FALSE;
1261 }
1262
1263 rdp_client_transition_to_state(context->rdp, CONNECTION_STATE_MCS_CONNECT);
1264 return TRUE;
1265 }
1266
1267 /**
1268 * Instantiate new MCS module.
1269 * @param transport transport
1270 * @return new MCS module
1271 */
1272
mcs_new(rdpTransport * transport)1273 rdpMcs* mcs_new(rdpTransport* transport)
1274 {
1275 rdpMcs* mcs;
1276
1277 if (!transport)
1278 return NULL;
1279
1280 mcs = (rdpMcs*)calloc(1, sizeof(rdpMcs));
1281
1282 if (!mcs)
1283 return NULL;
1284
1285 mcs->transport = transport;
1286 mcs->settings = transport->settings;
1287 mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
1288 mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
1289 mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
1290 mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF);
1291 mcs->channelCount = 0;
1292 mcs->channelMaxCount = CHANNEL_MAX_COUNT;
1293 mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
1294 mcs->channels = (rdpMcsChannel*)calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel));
1295
1296 if (!mcs->channels)
1297 goto out_free;
1298
1299 return mcs;
1300 out_free:
1301 free(mcs);
1302 return NULL;
1303 }
1304
1305 /**
1306 * Free MCS module.
1307 * @param mcs MCS module to be freed
1308 */
1309
mcs_free(rdpMcs * mcs)1310 void mcs_free(rdpMcs* mcs)
1311 {
1312 if (mcs)
1313 {
1314 free(mcs->channels);
1315 free(mcs);
1316 }
1317 }
1318