Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/core/mcs.c
Line
Count
Source (jump to first uncovered line)
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
#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
40
/**
41
 * T.125 MCS is defined in:
42
 *
43
 * http://www.itu.int/rec/T-REC-T.125-199802-I/
44
 * ITU-T T.125 Multipoint Communication Service Protocol Specification
45
 */
46
47
/**
48
 * Connect-Initial ::= [APPLICATION 101] IMPLICIT SEQUENCE
49
 * {
50
 *  callingDomainSelector   OCTET_STRING,
51
 *  calledDomainSelector    OCTET_STRING,
52
 *  upwardFlag      BOOLEAN,
53
 *  targetParameters    DomainParameters,
54
 *  minimumParameters   DomainParameters,
55
 *  maximumParameters   DomainParameters,
56
 *  userData      OCTET_STRING
57
 * }
58
 *
59
 * DomainParameters ::= SEQUENCE
60
 * {
61
 *  maxChannelIds     INTEGER (0..MAX),
62
 *  maxUserIds      INTEGER (0..MAX),
63
 *  maxTokenIds     INTEGER (0..MAX),
64
 *  numPriorities     INTEGER (0..MAX),
65
 *  minThroughput     INTEGER (0..MAX),
66
 *  maxHeight     INTEGER (0..MAX),
67
 *  maxMCSPDUsize     INTEGER (0..MAX),
68
 *  protocolVersion     INTEGER (0..MAX)
69
 * }
70
 *
71
 * Connect-Response ::= [APPLICATION 102] IMPLICIT SEQUENCE
72
 * {
73
 *  result        Result,
74
 *  calledConnectId     INTEGER (0..MAX),
75
 *  domainParameters    DomainParameters,
76
 *  userData      OCTET_STRING
77
 * }
78
 *
79
 * Result ::= ENUMERATED
80
 * {
81
 *  rt-successful     (0),
82
 *  rt-domain-merging   (1),
83
 *  rt-domain-not-hierarchical  (2),
84
 *  rt-no-such-channel    (3),
85
 *  rt-no-such-domain   (4),
86
 *  rt-no-such-user     (5),
87
 *  rt-not-admitted     (6),
88
 *  rt-other-user-id    (7),
89
 *  rt-parameters-unacceptable  (8),
90
 *  rt-token-not-available    (9),
91
 *  rt-token-not-possessed    (10),
92
 *  rt-too-many-channels    (11),
93
 *  rt-too-many-tokens    (12),
94
 *  rt-too-many-users   (13),
95
 *  rt-unspecified-failure    (14),
96
 *  rt-user-rejected    (15)
97
 * }
98
 *
99
 * ErectDomainRequest ::= [APPLICATION 1] IMPLICIT SEQUENCE
100
 * {
101
 *  subHeight     INTEGER (0..MAX),
102
 *  subInterval     INTEGER (0..MAX)
103
 * }
104
 *
105
 * AttachUserRequest ::= [APPPLICATION 10] IMPLICIT SEQUENCE
106
 * {
107
 * }
108
 *
109
 * AttachUserConfirm ::= [APPLICATION 11] IMPLICIT SEQUENCE
110
 * {
111
 *  result        Result,
112
 *  initiator     UserId OPTIONAL
113
 * }
114
 *
115
 * ChannelJoinRequest ::= [APPLICATION 14] IMPLICIT SEQUENCE
116
 * {
117
 *  initiator     UserId,
118
 *  channelId     ChannelId
119
 * }
120
 *
121
 * ChannelJoinConfirm ::= [APPLICATION 15] IMPLICIT SEQUENCE
122
 * {
123
 *  result        Result,
124
 *  initiator     UserId,
125
 *  requested     ChannelId,
126
 *  channelId     ChannelId OPTIONAL
127
 * }
128
 *
129
 * SendDataRequest ::= [APPLICATION 25] IMPLICIT SEQUENCE
130
 * {
131
 *  initiator     UserId,
132
 *  channelId     ChannelId,
133
 *  dataPriority      DataPriority,
134
 *  segmentation      Segmentation,
135
 *  userData      OCTET_STRING
136
 * }
137
 *
138
 * DataPriority ::= CHOICE
139
 * {
140
 *  top       NULL,
141
 *  high        NULL,
142
 *  medium        NULL,
143
 *  low       NULL,
144
 *  ...
145
 * }
146
 *
147
 * Segmentation ::= BIT_STRING
148
 * {
149
 *  begin       (0),
150
 *  end       (1)
151
 * } (SIZE(2))
152
 *
153
 * SendDataIndication ::= SEQUENCE
154
 * {
155
 *  initiator     UserId,
156
 *  channelId     ChannelId,
157
 *  reliability     BOOLEAN,
158
 *  domainReferenceID   INTEGER (0..65535) OPTIONAL,
159
 *  dataPriority      DataPriority,
160
 *  segmentation      Segmentation,
161
 *  userData      OCTET_STRING,
162
 *  totalDataSize     INTEGER OPTIONAL,
163
 *  nonStandard     SEQUENCE OF NonStandardParameter OPTIONAL,
164
 *  ...
165
 * }
166
 *
167
 */
168
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
118
{
196
118
  switch (pdu)
197
118
  {
198
10
    case DomainMCSPDU_PlumbDomainIndication:
199
10
      return "DomainMCSPDU_PlumbDomainIndication";
200
1
    case DomainMCSPDU_ErectDomainRequest:
201
1
      return "DomainMCSPDU_ErectDomainRequest";
202
1
    case DomainMCSPDU_MergeChannelsRequest:
203
1
      return "DomainMCSPDU_MergeChannelsRequest";
204
2
    case DomainMCSPDU_MergeChannelsConfirm:
205
2
      return "DomainMCSPDU_MergeChannelsConfirm";
206
1
    case DomainMCSPDU_PurgeChannelsIndication:
207
1
      return "DomainMCSPDU_PurgeChannelsIndication";
208
1
    case DomainMCSPDU_MergeTokensRequest:
209
1
      return "DomainMCSPDU_MergeTokensRequest";
210
1
    case DomainMCSPDU_MergeTokensConfirm:
211
1
      return "DomainMCSPDU_MergeTokensConfirm";
212
0
    case DomainMCSPDU_PurgeTokensIndication:
213
0
      return "DomainMCSPDU_PurgeTokensIndication";
214
0
    case DomainMCSPDU_DisconnectProviderUltimatum:
215
0
      return "DomainMCSPDU_DisconnectProviderUltimatum";
216
0
    case DomainMCSPDU_RejectMCSPDUUltimatum:
217
0
      return "DomainMCSPDU_RejectMCSPDUUltimatum";
218
0
    case DomainMCSPDU_AttachUserRequest:
219
0
      return "DomainMCSPDU_AttachUserRequest";
220
1
    case DomainMCSPDU_AttachUserConfirm:
221
1
      return "DomainMCSPDU_AttachUserConfirm";
222
0
    case DomainMCSPDU_DetachUserRequest:
223
0
      return "DomainMCSPDU_DetachUserRequest";
224
0
    case DomainMCSPDU_DetachUserIndication:
225
0
      return "DomainMCSPDU_DetachUserIndication";
226
0
    case DomainMCSPDU_ChannelJoinRequest:
227
0
      return "DomainMCSPDU_ChannelJoinRequest";
228
1
    case DomainMCSPDU_ChannelJoinConfirm:
229
1
      return "DomainMCSPDU_ChannelJoinConfirm";
230
0
    case DomainMCSPDU_ChannelLeaveRequest:
231
0
      return "DomainMCSPDU_ChannelLeaveRequest";
232
1
    case DomainMCSPDU_ChannelConveneRequest:
233
1
      return "DomainMCSPDU_ChannelConveneRequest";
234
0
    case DomainMCSPDU_ChannelConveneConfirm:
235
0
      return "DomainMCSPDU_ChannelConveneConfirm";
236
1
    case DomainMCSPDU_ChannelDisbandRequest:
237
1
      return "DomainMCSPDU_ChannelDisbandRequest";
238
0
    case DomainMCSPDU_ChannelDisbandIndication:
239
0
      return "DomainMCSPDU_ChannelDisbandIndication";
240
2
    case DomainMCSPDU_ChannelAdmitRequest:
241
2
      return "DomainMCSPDU_ChannelAdmitRequest";
242
1
    case DomainMCSPDU_ChannelAdmitIndication:
243
1
      return "DomainMCSPDU_ChannelAdmitIndication";
244
1
    case DomainMCSPDU_ChannelExpelRequest:
245
1
      return "DomainMCSPDU_ChannelExpelRequest";
246
1
    case DomainMCSPDU_ChannelExpelIndication:
247
1
      return "DomainMCSPDU_ChannelExpelIndication";
248
30
    case DomainMCSPDU_SendDataRequest:
249
30
      return "DomainMCSPDU_SendDataRequest";
250
30
    case DomainMCSPDU_SendDataIndication:
251
30
      return "DomainMCSPDU_SendDataIndication";
252
0
    case DomainMCSPDU_UniformSendDataRequest:
253
0
      return "DomainMCSPDU_UniformSendDataRequest";
254
0
    case DomainMCSPDU_UniformSendDataIndication:
255
0
      return "DomainMCSPDU_UniformSendDataIndication";
256
0
    case DomainMCSPDU_TokenGrabRequest:
257
0
      return "DomainMCSPDU_TokenGrabRequest";
258
1
    case DomainMCSPDU_TokenGrabConfirm:
259
1
      return "DomainMCSPDU_TokenGrabConfirm";
260
7
    case DomainMCSPDU_TokenInhibitRequest:
261
7
      return "DomainMCSPDU_TokenInhibitRequest";
262
0
    case DomainMCSPDU_TokenInhibitConfirm:
263
0
      return "DomainMCSPDU_TokenInhibitConfirm";
264
1
    case DomainMCSPDU_TokenGiveRequest:
265
1
      return "DomainMCSPDU_TokenGiveRequest";
266
0
    case DomainMCSPDU_TokenGiveIndication:
267
0
      return "DomainMCSPDU_TokenGiveIndication";
268
0
    case DomainMCSPDU_TokenGiveResponse:
269
0
      return "DomainMCSPDU_TokenGiveResponse";
270
0
    case DomainMCSPDU_TokenGiveConfirm:
271
0
      return "DomainMCSPDU_TokenGiveConfirm";
272
2
    case DomainMCSPDU_TokenPleaseRequest:
273
2
      return "DomainMCSPDU_TokenPleaseRequest";
274
0
    case DomainMCSPDU_TokenPleaseConfirm:
275
0
      return "DomainMCSPDU_TokenPleaseConfirm";
276
1
    case DomainMCSPDU_TokenReleaseRequest:
277
1
      return "DomainMCSPDU_TokenReleaseRequest";
278
0
    case DomainMCSPDU_TokenReleaseConfirm:
279
0
      return "DomainMCSPDU_TokenReleaseConfirm";
280
2
    case DomainMCSPDU_TokenTestRequest:
281
2
      return "DomainMCSPDU_TokenTestRequest";
282
0
    case DomainMCSPDU_TokenTestConfirm:
283
0
      return "DomainMCSPDU_TokenTestConfirm";
284
0
    case DomainMCSPDU_enum_length:
285
0
      return "DomainMCSPDU_enum_length";
286
18
    default:
287
18
      return "DomainMCSPDU_UNKNOWN";
288
118
  }
289
118
}
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
0
{
303
0
  if (!mcs || !settings)
304
0
    return -1;
305
306
0
  mcs->channelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount);
307
308
0
  if (mcs->channelCount > mcs->channelMaxCount)
309
0
    mcs->channelCount = mcs->channelMaxCount;
310
311
0
  ZeroMemory(mcs->channels, sizeof(rdpMcsChannel) * mcs->channelMaxCount);
312
313
0
  for (UINT32 index = 0; index < mcs->channelCount; index++)
314
0
  {
315
0
    const CHANNEL_DEF* defchannel =
316
0
        freerdp_settings_get_pointer_array(settings, FreeRDP_ChannelDefArray, index);
317
0
    rdpMcsChannel* cur = &mcs->channels[index];
318
0
    WINPR_ASSERT(defchannel);
319
0
    CopyMemory(cur->Name, defchannel->name, CHANNEL_NAME_LEN);
320
0
    cur->options = defchannel->options;
321
0
  }
322
323
0
  return 0;
324
0
}
325
326
/**
327
 * Read a DomainMCSPDU header.
328
 * @param s stream
329
 * @param domainMCSPDU DomainMCSPDU type
330
 * @param length TPKT length
331
 *
332
 * @return \b TRUE for success, \b FALSE otherwise
333
 */
334
335
BOOL mcs_read_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU, UINT16* length,
336
                                   DomainMCSPDU* actual)
337
0
{
338
0
  UINT16 li = 0;
339
0
  BYTE choice = 0;
340
341
0
  if (actual)
342
0
    *actual = DomainMCSPDU_invalid;
343
344
0
  WINPR_ASSERT(s);
345
0
  WINPR_ASSERT(domainMCSPDU);
346
0
  WINPR_ASSERT(length);
347
348
0
  if (!tpkt_read_header(s, length))
349
0
    return FALSE;
350
351
0
  if (!tpdu_read_data(s, &li, *length))
352
0
    return FALSE;
353
354
0
  if (!per_read_choice(s, &choice))
355
0
    return FALSE;
356
357
0
  const DomainMCSPDU MCSPDU = (choice >> 2);
358
0
  if (actual)
359
0
    *actual = MCSPDU;
360
361
0
  if (domainMCSPDU != MCSPDU)
362
0
  {
363
0
    WLog_ERR(TAG, "Expected MCS %s, got %s", mcs_domain_pdu_string(domainMCSPDU),
364
0
             mcs_domain_pdu_string(MCSPDU));
365
0
    return FALSE;
366
0
  }
367
368
0
  return TRUE;
369
0
}
370
371
/**
372
 * Write a DomainMCSPDU header.
373
 * @param s stream
374
 * @param domainMCSPDU DomainMCSPDU type
375
 * @param length TPKT length
376
 */
377
378
BOOL mcs_write_domain_mcspdu_header(wStream* s, DomainMCSPDU domainMCSPDU, UINT16 length,
379
                                    BYTE options)
380
3.12k
{
381
3.12k
  WINPR_ASSERT(s);
382
3.12k
  WINPR_ASSERT((options & ~0x03) == 0);
383
3.12k
  WINPR_ASSERT((domainMCSPDU & ~0x3F) == 0);
384
385
3.12k
  if (!tpkt_write_header(s, length))
386
0
    return FALSE;
387
3.12k
  if (!tpdu_write_data(s))
388
0
    return FALSE;
389
3.12k
  return per_write_choice(s, (BYTE)((domainMCSPDU << 2) | options));
390
3.12k
}
391
392
/**
393
 * Initialize MCS Domain Parameters.
394
 * @param domainParameters domain parameters
395
 * @param maxChannelIds max channel ids
396
 * @param maxUserIds max user ids
397
 * @param maxTokenIds max token ids
398
 * @param maxMCSPDUsize max MCS PDU size
399
 */
400
401
static BOOL mcs_init_domain_parameters(DomainParameters* domainParameters, UINT32 maxChannelIds,
402
                                       UINT32 maxUserIds, UINT32 maxTokenIds, UINT32 maxMCSPDUsize)
403
179k
{
404
179k
  if (!domainParameters)
405
0
    return FALSE;
406
407
179k
  domainParameters->maxChannelIds = maxChannelIds;
408
179k
  domainParameters->maxUserIds = maxUserIds;
409
179k
  domainParameters->maxTokenIds = maxTokenIds;
410
179k
  domainParameters->maxMCSPDUsize = maxMCSPDUsize;
411
179k
  domainParameters->numPriorities = 1;
412
179k
  domainParameters->minThroughput = 0;
413
179k
  domainParameters->maxHeight = 1;
414
179k
  domainParameters->protocolVersion = 2;
415
179k
  return TRUE;
416
179k
}
417
418
/**
419
 * Read MCS Domain Parameters.
420
 * @param s stream
421
 * @param domainParameters domain parameters
422
 */
423
424
static BOOL mcs_read_domain_parameters(wStream* s, DomainParameters* domainParameters)
425
752
{
426
752
  size_t length = 0;
427
428
752
  if (!s || !domainParameters)
429
0
    return FALSE;
430
431
752
  return ber_read_sequence_tag(s, &length) &&
432
752
         ber_read_integer(s, &(domainParameters->maxChannelIds)) &&
433
752
         ber_read_integer(s, &(domainParameters->maxUserIds)) &&
434
752
         ber_read_integer(s, &(domainParameters->maxTokenIds)) &&
435
752
         ber_read_integer(s, &(domainParameters->numPriorities)) &&
436
752
         ber_read_integer(s, &(domainParameters->minThroughput)) &&
437
752
         ber_read_integer(s, &(domainParameters->maxHeight)) &&
438
752
         ber_read_integer(s, &(domainParameters->maxMCSPDUsize)) &&
439
752
         ber_read_integer(s, &(domainParameters->protocolVersion));
440
752
}
441
442
/**
443
 * Write MCS Domain Parameters.
444
 * @param s stream
445
 * @param domainParameters domain parameters
446
 */
447
448
static BOOL mcs_write_domain_parameters(wStream* s, DomainParameters* domainParameters)
449
0
{
450
0
  size_t length = 0;
451
0
  wStream* tmps = NULL;
452
453
0
  if (!s || !domainParameters)
454
0
    return FALSE;
455
456
0
  tmps = Stream_New(NULL, Stream_Capacity(s));
457
458
0
  if (!tmps)
459
0
  {
460
0
    WLog_ERR(TAG, "Stream_New failed!");
461
0
    return FALSE;
462
0
  }
463
464
0
  ber_write_integer(tmps, domainParameters->maxChannelIds);
465
0
  ber_write_integer(tmps, domainParameters->maxUserIds);
466
0
  ber_write_integer(tmps, domainParameters->maxTokenIds);
467
0
  ber_write_integer(tmps, domainParameters->numPriorities);
468
0
  ber_write_integer(tmps, domainParameters->minThroughput);
469
0
  ber_write_integer(tmps, domainParameters->maxHeight);
470
0
  ber_write_integer(tmps, domainParameters->maxMCSPDUsize);
471
0
  ber_write_integer(tmps, domainParameters->protocolVersion);
472
0
  length = Stream_GetPosition(tmps);
473
0
  ber_write_sequence_tag(s, length);
474
0
  Stream_Write(s, Stream_Buffer(tmps), length);
475
0
  Stream_Free(tmps, TRUE);
476
0
  return TRUE;
477
0
}
478
479
#ifdef DEBUG_MCS
480
/**
481
 * Print MCS Domain Parameters.
482
 * @param domainParameters domain parameters
483
 */
484
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
507
/**
508
 * Merge MCS Domain Parameters.
509
 * @param targetParameters target parameters
510
 * @param minimumParameters minimum parameters
511
 * @param maximumParameters maximum parameters
512
 * @param pOutParameters output parameters
513
 *
514
 * @return \b TRUE for success, \b FALSE otherwise
515
 */
516
517
BOOL mcs_merge_domain_parameters(DomainParameters* targetParameters,
518
                                 DomainParameters* minimumParameters,
519
                                 DomainParameters* maximumParameters,
520
                                 DomainParameters* pOutParameters)
521
0
{
522
  /* maxChannelIds */
523
0
  if (!targetParameters || !minimumParameters || !maximumParameters || !pOutParameters)
524
0
    return FALSE;
525
526
0
  if (targetParameters->maxChannelIds >= 4)
527
0
  {
528
0
    pOutParameters->maxChannelIds = targetParameters->maxChannelIds;
529
0
  }
530
0
  else if (maximumParameters->maxChannelIds >= 4)
531
0
  {
532
0
    pOutParameters->maxChannelIds = 4;
533
0
  }
534
0
  else
535
0
  {
536
0
    WLog_ERR(TAG, "invalid maxChannelIds [%" PRIu32 ", %" PRIu32 "]",
537
0
             targetParameters->maxChannelIds, maximumParameters->maxChannelIds);
538
0
    return FALSE;
539
0
  }
540
541
  /* maxUserIds */
542
543
0
  if (targetParameters->maxUserIds >= 3)
544
0
  {
545
0
    pOutParameters->maxUserIds = targetParameters->maxUserIds;
546
0
  }
547
0
  else if (maximumParameters->maxUserIds >= 3)
548
0
  {
549
0
    pOutParameters->maxUserIds = 3;
550
0
  }
551
0
  else
552
0
  {
553
0
    WLog_ERR(TAG, "invalid maxUserIds [%" PRIu32 ", %" PRIu32 "]", targetParameters->maxUserIds,
554
0
             maximumParameters->maxUserIds);
555
0
    return FALSE;
556
0
  }
557
558
  /* maxTokenIds */
559
0
  pOutParameters->maxTokenIds = targetParameters->maxTokenIds;
560
561
  /* numPriorities */
562
563
0
  if (minimumParameters->numPriorities <= 1)
564
0
  {
565
0
    pOutParameters->numPriorities = 1;
566
0
  }
567
0
  else
568
0
  {
569
0
    WLog_ERR(TAG, "invalid numPriorities [%" PRIu32 "]", maximumParameters->numPriorities);
570
0
    return FALSE;
571
0
  }
572
573
  /* minThroughput */
574
0
  pOutParameters->minThroughput = targetParameters->minThroughput;
575
576
  /* maxHeight */
577
578
0
  if ((targetParameters->maxHeight == 1) || (minimumParameters->maxHeight <= 1))
579
0
  {
580
0
    pOutParameters->maxHeight = 1;
581
0
  }
582
0
  else
583
0
  {
584
0
    WLog_ERR(TAG, "invalid maxHeight [%" PRIu32 ", %" PRIu32 "]", targetParameters->maxHeight,
585
0
             minimumParameters->maxHeight);
586
0
    return FALSE;
587
0
  }
588
589
  /* maxMCSPDUsize */
590
591
0
  if (targetParameters->maxMCSPDUsize >= 1024)
592
0
  {
593
0
    if (targetParameters->maxMCSPDUsize <= 65528)
594
0
    {
595
0
      pOutParameters->maxMCSPDUsize = targetParameters->maxMCSPDUsize;
596
0
    }
597
0
    else if ((minimumParameters->maxMCSPDUsize >= 124) &&
598
0
             (minimumParameters->maxMCSPDUsize <= 65528))
599
0
    {
600
0
      pOutParameters->maxMCSPDUsize = 65528;
601
0
    }
602
0
    else
603
0
    {
604
0
      WLog_ERR(TAG, "invalid maxMCSPDUsize [%" PRIu32 ", %" PRIu32 "]",
605
0
               targetParameters->maxMCSPDUsize, minimumParameters->maxMCSPDUsize);
606
0
      return FALSE;
607
0
    }
608
0
  }
609
0
  else
610
0
  {
611
0
    if (maximumParameters->maxMCSPDUsize >= 124)
612
0
    {
613
0
      pOutParameters->maxMCSPDUsize = maximumParameters->maxMCSPDUsize;
614
0
    }
615
0
    else
616
0
    {
617
0
      WLog_ERR(TAG, "invalid maxMCSPDUsize [%" PRIu32 "]", maximumParameters->maxMCSPDUsize);
618
0
      return FALSE;
619
0
    }
620
0
  }
621
622
  /* protocolVersion */
623
624
0
  if ((targetParameters->protocolVersion == 2) ||
625
0
      ((minimumParameters->protocolVersion <= 2) && (maximumParameters->protocolVersion >= 2)))
626
0
  {
627
0
    pOutParameters->protocolVersion = 2;
628
0
  }
629
0
  else
630
0
  {
631
0
    WLog_ERR(TAG, "invalid protocolVersion [%" PRIu32 ", %" PRIu32 ", %" PRIu32 "]",
632
0
             targetParameters->protocolVersion, minimumParameters->protocolVersion,
633
0
             maximumParameters->protocolVersion);
634
0
    return FALSE;
635
0
  }
636
637
0
  return TRUE;
638
0
}
639
640
/**
641
 * Read an MCS Connect Initial PDU.
642
 * msdn{cc240508}
643
 * @param mcs MCS module
644
 * @param s stream
645
 */
646
647
BOOL mcs_recv_connect_initial(rdpMcs* mcs, wStream* s)
648
14.9k
{
649
14.9k
  UINT16 li = 0;
650
14.9k
  size_t length = 0;
651
14.9k
  BOOL upwardFlag = FALSE;
652
14.9k
  UINT16 tlength = 0;
653
654
14.9k
  WINPR_ASSERT(mcs);
655
14.9k
  WINPR_ASSERT(s);
656
657
14.9k
  if (!tpkt_read_header(s, &tlength))
658
581
    return FALSE;
659
660
14.3k
  if (!tpdu_read_data(s, &li, tlength))
661
13.4k
    return FALSE;
662
663
945
  if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
664
489
    return FALSE;
665
666
  /* callingDomainSelector (OCTET_STRING) */
667
456
  if (!ber_read_octet_string_tag(s, &length) ||
668
456
      (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
669
57
    return FALSE;
670
671
399
  Stream_Seek(s, length);
672
673
  /* calledDomainSelector (OCTET_STRING) */
674
399
  if (!ber_read_octet_string_tag(s, &length) ||
675
399
      (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
676
31
    return FALSE;
677
678
368
  Stream_Seek(s, length);
679
680
  /* upwardFlag (BOOLEAN) */
681
368
  if (!ber_read_BOOL(s, &upwardFlag))
682
82
    return FALSE;
683
684
  /* targetParameters (DomainParameters) */
685
286
  if (!mcs_read_domain_parameters(s, &mcs->targetParameters))
686
185
    return FALSE;
687
688
  /* minimumParameters (DomainParameters) */
689
101
  if (!mcs_read_domain_parameters(s, &mcs->minimumParameters))
690
20
    return FALSE;
691
692
  /* maximumParameters (DomainParameters) */
693
81
  if (!mcs_read_domain_parameters(s, &mcs->maximumParameters))
694
17
    return FALSE;
695
696
64
  if (!ber_read_octet_string_tag(s, &length) ||
697
64
      (!Stream_CheckAndLogRequiredLength(TAG, s, length)))
698
2
    return FALSE;
699
700
62
  if (!gcc_read_conference_create_request(s, mcs))
701
62
    return FALSE;
702
703
0
  if (!mcs_merge_domain_parameters(&mcs->targetParameters, &mcs->minimumParameters,
704
0
                                   &mcs->maximumParameters, &mcs->domainParameters))
705
0
    return FALSE;
706
707
0
  return tpkt_ensure_stream_consumed(s, tlength);
708
0
}
709
710
/**
711
 * Write an MCS Connect Initial PDU.
712
 * msdn{cc240508}
713
 * @param s stream
714
 * @param mcs MCS module
715
 * @param userData GCC Conference Create Request
716
 */
717
718
BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData)
719
0
{
720
0
  size_t length = 0;
721
0
  wStream* tmps = NULL;
722
0
  BOOL ret = FALSE;
723
724
0
  if (!s || !mcs || !userData)
725
0
    return FALSE;
726
727
0
  tmps = Stream_New(NULL, Stream_Capacity(s));
728
729
0
  if (!tmps)
730
0
  {
731
0
    WLog_ERR(TAG, "Stream_New failed!");
732
0
    return FALSE;
733
0
  }
734
735
  /* callingDomainSelector (OCTET_STRING) */
736
0
  ber_write_octet_string(tmps, callingDomainSelector, sizeof(callingDomainSelector));
737
  /* calledDomainSelector (OCTET_STRING) */
738
0
  ber_write_octet_string(tmps, calledDomainSelector, sizeof(calledDomainSelector));
739
  /* upwardFlag (BOOLEAN) */
740
0
  ber_write_BOOL(tmps, TRUE);
741
742
  /* targetParameters (DomainParameters) */
743
0
  if (!mcs_write_domain_parameters(tmps, &mcs->targetParameters))
744
0
    goto out;
745
746
  /* minimumParameters (DomainParameters) */
747
0
  if (!mcs_write_domain_parameters(tmps, &mcs->minimumParameters))
748
0
    goto out;
749
750
  /* maximumParameters (DomainParameters) */
751
0
  if (!mcs_write_domain_parameters(tmps, &mcs->maximumParameters))
752
0
    goto out;
753
754
  /* userData (OCTET_STRING) */
755
0
  ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
756
0
  length = Stream_GetPosition(tmps);
757
  /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
758
0
  ber_write_application_tag(s, MCS_TYPE_CONNECT_INITIAL, length);
759
0
  Stream_Write(s, Stream_Buffer(tmps), length);
760
0
  ret = TRUE;
761
0
out:
762
0
  Stream_Free(tmps, TRUE);
763
0
  return ret;
764
0
}
765
766
/**
767
 * Write an MCS Connect Response PDU.
768
 * msdn{cc240508}
769
 * @param s stream
770
 * @param mcs MCS module
771
 * @param userData GCC Conference Create Response
772
 *
773
 * @return \b TRUE for success, \b FALSE otherwise
774
 */
775
776
BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData)
777
0
{
778
0
  size_t length = 0;
779
0
  wStream* tmps = NULL;
780
0
  BOOL ret = FALSE;
781
782
0
  if (!s || !mcs || !userData)
783
0
    return FALSE;
784
785
0
  tmps = Stream_New(NULL, Stream_Capacity(s));
786
787
0
  if (!tmps)
788
0
  {
789
0
    WLog_ERR(TAG, "Stream_New failed!");
790
0
    return FALSE;
791
0
  }
792
793
0
  ber_write_enumerated(tmps, 0, MCS_Result_enum_length);
794
0
  ber_write_integer(tmps, 0); /* calledConnectId */
795
796
0
  if (!mcs_write_domain_parameters(tmps, &(mcs->domainParameters)))
797
0
    goto out;
798
799
  /* userData (OCTET_STRING) */
800
0
  ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
801
0
  length = Stream_GetPosition(tmps);
802
0
  ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
803
0
  Stream_Write(s, Stream_Buffer(tmps), length);
804
0
  ret = TRUE;
805
0
out:
806
0
  Stream_Free(tmps, TRUE);
807
0
  return ret;
808
0
}
809
810
/**
811
 * Send MCS Connect Initial.
812
 * msdn{cc240508}
813
 * @param mcs mcs module
814
 */
815
816
static BOOL mcs_send_connect_initial(rdpMcs* mcs)
817
0
{
818
0
  int status = -1;
819
0
  size_t length = 0;
820
0
  wStream* s = NULL;
821
0
  size_t bm = 0;
822
0
  size_t em = 0;
823
0
  wStream* gcc_CCrq = NULL;
824
0
  wStream* client_data = NULL;
825
0
  rdpContext* context = NULL;
826
827
0
  if (!mcs)
828
0
    return FALSE;
829
830
0
  context = transport_get_context(mcs->transport);
831
0
  WINPR_ASSERT(context);
832
833
0
  mcs_initialize_client_channels(mcs, context->settings);
834
0
  client_data = Stream_New(NULL, 512);
835
836
0
  if (!client_data)
837
0
  {
838
0
    WLog_ERR(TAG, "Stream_New failed!");
839
0
    return FALSE;
840
0
  }
841
842
0
  if (!gcc_write_client_data_blocks(client_data, mcs))
843
0
    goto out;
844
0
  gcc_CCrq = Stream_New(NULL, 1024);
845
846
0
  if (!gcc_CCrq)
847
0
  {
848
0
    WLog_ERR(TAG, "Stream_New failed!");
849
0
    goto out;
850
0
  }
851
852
0
  if (!gcc_write_conference_create_request(gcc_CCrq, client_data))
853
0
    goto out;
854
0
  length = Stream_GetPosition(gcc_CCrq) + 7;
855
0
  s = Stream_New(NULL, 1024 + length);
856
857
0
  if (!s)
858
0
  {
859
0
    WLog_ERR(TAG, "Stream_New failed!");
860
0
    goto out;
861
0
  }
862
863
0
  bm = Stream_GetPosition(s);
864
0
  Stream_Seek(s, 7);
865
866
0
  if (!mcs_write_connect_initial(s, mcs, gcc_CCrq))
867
0
  {
868
0
    WLog_ERR(TAG, "mcs_write_connect_initial failed!");
869
0
    goto out;
870
0
  }
871
872
0
  em = Stream_GetPosition(s);
873
0
  length = (em - bm);
874
0
  if (length > UINT16_MAX)
875
0
    goto out;
876
0
  Stream_SetPosition(s, bm);
877
0
  if (!tpkt_write_header(s, (UINT16)length))
878
0
    goto out;
879
0
  if (!tpdu_write_data(s))
880
0
    goto out;
881
0
  Stream_SetPosition(s, em);
882
0
  Stream_SealLength(s);
883
0
  status = transport_write(mcs->transport, s);
884
0
out:
885
0
  Stream_Free(s, TRUE);
886
0
  Stream_Free(gcc_CCrq, TRUE);
887
0
  Stream_Free(client_data, TRUE);
888
0
  return (status < 0 ? FALSE : TRUE);
889
0
}
890
891
/**
892
 * Read MCS Connect Response.
893
 * msdn{cc240501}
894
 * @param mcs mcs module
895
 */
896
897
BOOL mcs_recv_connect_response(rdpMcs* mcs, wStream* s)
898
14.9k
{
899
14.9k
  size_t length = 0;
900
14.9k
  UINT16 tlength = 0;
901
14.9k
  BYTE result = 0;
902
14.9k
  UINT16 li = 0;
903
14.9k
  UINT32 calledConnectId = 0;
904
905
14.9k
  if (!mcs || !s)
906
0
    return FALSE;
907
908
14.9k
  if (!tpkt_read_header(s, &tlength))
909
581
    return FALSE;
910
911
14.3k
  if (!tpdu_read_data(s, &li, tlength))
912
13.4k
    return FALSE;
913
914
945
  if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, &length) ||
915
945
      !ber_read_enumerated(s, &result, MCS_Result_enum_length) ||
916
945
      !ber_read_integer(s, &calledConnectId) ||
917
945
      !mcs_read_domain_parameters(s, &(mcs->domainParameters)) ||
918
945
      !ber_read_octet_string_tag(s, &length))
919
850
  {
920
850
    return FALSE;
921
850
  }
922
923
95
  if (!gcc_read_conference_create_response(s, mcs))
924
95
  {
925
95
    WLog_ERR(TAG, "gcc_read_conference_create_response failed");
926
95
    return FALSE;
927
95
  }
928
929
0
  return tpkt_ensure_stream_consumed(s, tlength);
930
95
}
931
932
/**
933
 * Send MCS Connect Response.
934
 * msdn{cc240501}
935
 * @param mcs mcs module
936
 */
937
938
BOOL mcs_send_connect_response(rdpMcs* mcs)
939
0
{
940
0
  size_t length = 0;
941
0
  int status = -1;
942
0
  wStream* s = NULL;
943
0
  size_t bm = 0;
944
0
  size_t em = 0;
945
0
  wStream* gcc_CCrsp = NULL;
946
0
  wStream* server_data = NULL;
947
948
0
  if (!mcs)
949
0
    return FALSE;
950
951
0
  server_data = Stream_New(NULL, 512);
952
953
0
  if (!server_data)
954
0
  {
955
0
    WLog_ERR(TAG, "Stream_New failed!");
956
0
    return FALSE;
957
0
  }
958
959
0
  if (!gcc_write_server_data_blocks(server_data, mcs))
960
0
    goto out;
961
962
0
  gcc_CCrsp = Stream_New(NULL, 512 + Stream_Capacity(server_data));
963
964
0
  if (!gcc_CCrsp)
965
0
  {
966
0
    WLog_ERR(TAG, "Stream_New failed!");
967
0
    goto out;
968
0
  }
969
970
0
  if (!gcc_write_conference_create_response(gcc_CCrsp, server_data))
971
0
    goto out;
972
0
  length = Stream_GetPosition(gcc_CCrsp) + 7;
973
0
  s = Stream_New(NULL, length + 1024);
974
975
0
  if (!s)
976
0
  {
977
0
    WLog_ERR(TAG, "Stream_New failed!");
978
0
    goto out;
979
0
  }
980
981
0
  bm = Stream_GetPosition(s);
982
0
  Stream_Seek(s, 7);
983
984
0
  if (!mcs_write_connect_response(s, mcs, gcc_CCrsp))
985
0
    goto out;
986
987
0
  em = Stream_GetPosition(s);
988
0
  length = (em - bm);
989
0
  if (length > UINT16_MAX)
990
0
    goto out;
991
0
  Stream_SetPosition(s, bm);
992
0
  if (!tpkt_write_header(s, (UINT16)length))
993
0
    goto out;
994
0
  if (!tpdu_write_data(s))
995
0
    goto out;
996
0
  Stream_SetPosition(s, em);
997
0
  Stream_SealLength(s);
998
0
  status = transport_write(mcs->transport, s);
999
0
out:
1000
0
  Stream_Free(s, TRUE);
1001
0
  Stream_Free(gcc_CCrsp, TRUE);
1002
0
  Stream_Free(server_data, TRUE);
1003
0
  return (status < 0) ? FALSE : TRUE;
1004
0
}
1005
1006
/**
1007
 * Read MCS Erect Domain Request.
1008
 * msdn{cc240523}
1009
 * @param mcs MCS module to use
1010
 * @param s stream
1011
 */
1012
1013
BOOL mcs_recv_erect_domain_request(rdpMcs* mcs, wStream* s)
1014
0
{
1015
0
  UINT16 length = 0;
1016
0
  UINT32 subHeight = 0;
1017
0
  UINT32 subInterval = 0;
1018
1019
0
  WINPR_ASSERT(mcs);
1020
0
  WINPR_ASSERT(s);
1021
1022
0
  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, &length, NULL))
1023
0
    return FALSE;
1024
1025
0
  if (!per_read_integer(s, &subHeight)) /* subHeight (INTEGER) */
1026
0
    return FALSE;
1027
1028
0
  if (!per_read_integer(s, &subInterval)) /* subInterval (INTEGER) */
1029
0
    return FALSE;
1030
1031
0
  return tpkt_ensure_stream_consumed(s, length);
1032
0
}
1033
1034
/**
1035
 * Send MCS Erect Domain Request.
1036
 * msdn{cc240523}
1037
 * @param mcs MCS module to use
1038
 */
1039
1040
BOOL mcs_send_erect_domain_request(rdpMcs* mcs)
1041
0
{
1042
0
  wStream* s = NULL;
1043
0
  int status = 0;
1044
0
  UINT16 length = 12;
1045
1046
0
  if (!mcs)
1047
0
    return FALSE;
1048
1049
0
  s = Stream_New(NULL, length);
1050
1051
0
  if (!s)
1052
0
  {
1053
0
    WLog_ERR(TAG, "Stream_New failed!");
1054
0
    return FALSE;
1055
0
  }
1056
1057
0
  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length, 0);
1058
0
  per_write_integer(s, 0); /* subHeight (INTEGER) */
1059
0
  per_write_integer(s, 0); /* subInterval (INTEGER) */
1060
0
  Stream_SealLength(s);
1061
0
  status = transport_write(mcs->transport, s);
1062
0
  Stream_Free(s, TRUE);
1063
0
  return (status < 0) ? FALSE : TRUE;
1064
0
}
1065
1066
/**
1067
 * Read MCS Attach User Request.
1068
 * msdn{cc240524}
1069
 * @param mcs mcs module
1070
 * @param s stream
1071
 */
1072
1073
BOOL mcs_recv_attach_user_request(rdpMcs* mcs, wStream* s)
1074
0
{
1075
0
  UINT16 length = 0;
1076
1077
0
  if (!mcs || !s)
1078
0
    return FALSE;
1079
1080
0
  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, &length, NULL))
1081
0
    return FALSE;
1082
0
  return tpkt_ensure_stream_consumed(s, length);
1083
0
}
1084
1085
/**
1086
 * Send MCS Attach User Request.
1087
 * msdn{cc240524}
1088
 * @param mcs mcs module
1089
 */
1090
1091
BOOL mcs_send_attach_user_request(rdpMcs* mcs)
1092
0
{
1093
0
  wStream* s = NULL;
1094
0
  int status = 0;
1095
0
  UINT16 length = 8;
1096
1097
0
  if (!mcs)
1098
0
    return FALSE;
1099
1100
0
  s = Stream_New(NULL, length);
1101
1102
0
  if (!s)
1103
0
  {
1104
0
    WLog_ERR(TAG, "Stream_New failed!");
1105
0
    return FALSE;
1106
0
  }
1107
1108
0
  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length, 0);
1109
0
  Stream_SealLength(s);
1110
0
  status = transport_write(mcs->transport, s);
1111
0
  Stream_Free(s, TRUE);
1112
0
  return (status < 0) ? FALSE : TRUE;
1113
0
}
1114
1115
/**
1116
 * Read MCS Attach User Confirm.
1117
 * msdn{cc240525}
1118
 * @param mcs mcs module
1119
 */
1120
1121
BOOL mcs_recv_attach_user_confirm(rdpMcs* mcs, wStream* s)
1122
0
{
1123
0
  BYTE result = 0;
1124
0
  UINT16 length = 0;
1125
1126
0
  if (!mcs || !s)
1127
0
    return FALSE;
1128
1129
0
  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, &length, NULL))
1130
0
    return FALSE;
1131
0
  if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1132
0
    return FALSE;
1133
0
  if (!per_read_integer16(s, &(mcs->userId), MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1134
0
    return FALSE;
1135
0
  return tpkt_ensure_stream_consumed(s, length);
1136
0
}
1137
1138
/**
1139
 * Send MCS Attach User Confirm.
1140
 * msdn{cc240525}
1141
 * @param mcs mcs module
1142
 */
1143
1144
BOOL mcs_send_attach_user_confirm(rdpMcs* mcs)
1145
0
{
1146
0
  wStream* s = NULL;
1147
0
  int status = 0;
1148
0
  UINT16 length = 11;
1149
1150
0
  if (!mcs)
1151
0
    return FALSE;
1152
1153
0
  s = Stream_New(NULL, length);
1154
1155
0
  if (!s)
1156
0
  {
1157
0
    WLog_ERR(TAG, "Stream_New failed!");
1158
0
    return FALSE;
1159
0
  }
1160
1161
0
  mcs->userId = mcs->baseChannelId++;
1162
0
  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserConfirm, length, 2);
1163
0
  per_write_enumerated(s, 0, MCS_Result_enum_length);       /* result */
1164
0
  per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */
1165
0
  Stream_SealLength(s);
1166
0
  status = transport_write(mcs->transport, s);
1167
0
  Stream_Free(s, TRUE);
1168
0
  return (status < 0) ? FALSE : TRUE;
1169
0
}
1170
1171
/**
1172
 * Read MCS Channel Join Request.
1173
 * msdn{cc240526}
1174
 * @param mcs mcs module
1175
 * @param s stream
1176
 */
1177
1178
BOOL mcs_recv_channel_join_request(rdpMcs* mcs, const rdpSettings* settings, wStream* s,
1179
                                   UINT16* channelId)
1180
0
{
1181
0
  UINT16 length = 0;
1182
0
  UINT16 userId = 0;
1183
1184
0
  if (!mcs || !s || !channelId)
1185
0
    return FALSE;
1186
1187
0
  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, &length, NULL))
1188
0
    return FALSE;
1189
1190
0
  if (!per_read_integer16(s, &userId, MCS_BASE_CHANNEL_ID))
1191
0
    return FALSE;
1192
0
  if (userId != mcs->userId)
1193
0
  {
1194
0
    if (freerdp_settings_get_bool(settings, FreeRDP_TransportDumpReplay))
1195
0
      mcs->userId = userId;
1196
0
    else
1197
0
      return FALSE;
1198
0
  }
1199
0
  if (!per_read_integer16(s, channelId, 0))
1200
0
    return FALSE;
1201
1202
0
  return tpkt_ensure_stream_consumed(s, length);
1203
0
}
1204
1205
/**
1206
 * Send MCS Channel Join Request.
1207
 * msdn{cc240526}
1208
 *
1209
 * @param mcs mcs module
1210
 * @param channelId channel id
1211
 *
1212
 * @return \b TRUE for success, \b FALSE otherwise
1213
 */
1214
1215
BOOL mcs_send_channel_join_request(rdpMcs* mcs, UINT16 channelId)
1216
0
{
1217
0
  wStream* s = NULL;
1218
0
  int status = 0;
1219
0
  UINT16 length = 12;
1220
1221
0
  WINPR_ASSERT(mcs);
1222
1223
0
  s = Stream_New(NULL, length);
1224
1225
0
  if (!s)
1226
0
  {
1227
0
    WLog_ERR(TAG, "Stream_New failed!");
1228
0
    return FALSE;
1229
0
  }
1230
1231
0
  mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length, 0);
1232
0
  per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID);
1233
0
  per_write_integer16(s, channelId, 0);
1234
0
  Stream_SealLength(s);
1235
0
  status = transport_write(mcs->transport, s);
1236
0
  Stream_Free(s, TRUE);
1237
0
  return (status < 0) ? FALSE : TRUE;
1238
0
}
1239
1240
/**
1241
 * Read MCS Channel Join Confirm.
1242
 * msdn{cc240527}
1243
 * @param mcs mcs module
1244
 */
1245
1246
BOOL mcs_recv_channel_join_confirm(rdpMcs* mcs, wStream* s, UINT16* channelId)
1247
0
{
1248
0
  UINT16 length = 0;
1249
0
  BYTE result = 0;
1250
0
  UINT16 initiator = 0;
1251
0
  UINT16 requested = 0;
1252
1253
0
  WINPR_ASSERT(mcs);
1254
0
  WINPR_ASSERT(channelId);
1255
1256
0
  if (!mcs_read_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, &length, NULL))
1257
0
    return FALSE;
1258
1259
0
  if (!per_read_enumerated(s, &result, MCS_Result_enum_length)) /* result */
1260
0
    return FALSE;
1261
0
  if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1262
0
    return FALSE;
1263
0
  if (!per_read_integer16(s, &requested, 0)) /* requested (ChannelId) */
1264
0
    return FALSE;
1265
0
  if (!per_read_integer16(s, channelId, 0)) /* channelId */
1266
0
    return FALSE;
1267
0
  return tpkt_ensure_stream_consumed(s, length);
1268
0
}
1269
1270
/**
1271
 * Send MCS Channel Join Confirm.
1272
 * msdn{cc240527}
1273
 * @param mcs mcs module
1274
 */
1275
1276
BOOL mcs_send_channel_join_confirm(rdpMcs* mcs, UINT16 channelId)
1277
0
{
1278
0
  wStream* s = NULL;
1279
0
  int status = -1;
1280
0
  UINT16 length = 15;
1281
1282
0
  if (!mcs)
1283
0
    return FALSE;
1284
1285
0
  s = Stream_New(NULL, length);
1286
1287
0
  if (!s)
1288
0
  {
1289
0
    WLog_ERR(TAG, "Stream_New failed!");
1290
0
    return FALSE;
1291
0
  }
1292
1293
0
  if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinConfirm, length, 2))
1294
0
    goto fail;
1295
0
  if (!per_write_enumerated(s, 0, MCS_Result_enum_length)) /* result */
1296
0
    goto fail;
1297
0
  if (!per_write_integer16(s, mcs->userId, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
1298
0
    goto fail;
1299
0
  if (!per_write_integer16(s, channelId, 0)) /* requested (ChannelId) */
1300
0
    goto fail;
1301
0
  if (!per_write_integer16(s, channelId, 0)) /* channelId */
1302
0
    goto fail;
1303
0
  Stream_SealLength(s);
1304
0
  status = transport_write(mcs->transport, s);
1305
0
fail:
1306
0
  Stream_Free(s, TRUE);
1307
0
  return (status < 0) ? FALSE : TRUE;
1308
0
}
1309
1310
/**
1311
 * Receive MCS Disconnect Provider Ultimatum PDU.
1312
 * @param mcs mcs module
1313
 */
1314
1315
BOOL mcs_recv_disconnect_provider_ultimatum(rdpMcs* mcs, wStream* s, int* reason)
1316
562
{
1317
562
  BYTE b1 = 0;
1318
562
  BYTE b2 = 0;
1319
1320
562
  WINPR_ASSERT(mcs);
1321
562
  WINPR_ASSERT(s);
1322
562
  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
562
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
1352
2
    return FALSE;
1353
1354
560
  Stream_Rewind_UINT8(s);
1355
560
  Stream_Read_UINT8(s, b1);
1356
560
  Stream_Read_UINT8(s, b2);
1357
560
  *reason = ((b1 & 0x01) << 1) | (b2 >> 7);
1358
560
  return TRUE;
1359
562
}
1360
1361
/**
1362
 * Send MCS Disconnect Provider Ultimatum PDU.
1363
 * @param mcs mcs module
1364
 */
1365
1366
BOOL mcs_send_disconnect_provider_ultimatum(rdpMcs* mcs)
1367
0
{
1368
0
  wStream* s = NULL;
1369
0
  int status = -1;
1370
0
  UINT16 length = 9;
1371
1372
0
  WINPR_ASSERT(mcs);
1373
1374
0
  s = Stream_New(NULL, length);
1375
1376
0
  if (!s)
1377
0
    goto fail;
1378
1379
0
  if (!mcs_write_domain_mcspdu_header(s, DomainMCSPDU_DisconnectProviderUltimatum, length, 1))
1380
0
    goto fail;
1381
1382
0
  if (!per_write_enumerated(s, 0x80, 0))
1383
0
    goto fail;
1384
0
  status = transport_write(mcs->transport, s);
1385
0
fail:
1386
0
  Stream_Free(s, TRUE);
1387
0
  return (status < 0) ? FALSE : TRUE;
1388
0
}
1389
1390
BOOL mcs_client_begin(rdpMcs* mcs)
1391
0
{
1392
0
  rdpContext* context = NULL;
1393
1394
0
  if (!mcs || !mcs->transport)
1395
0
    return FALSE;
1396
1397
0
  context = transport_get_context(mcs->transport);
1398
1399
0
  if (!context)
1400
0
    return FALSE;
1401
1402
  /* First transition state, we need this to trigger session recording */
1403
0
  if (!mcs_send_connect_initial(mcs))
1404
0
  {
1405
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR);
1406
1407
0
    WLog_ERR(TAG, "Error: unable to send MCS Connect Initial");
1408
0
    return FALSE;
1409
0
  }
1410
1411
0
  return TRUE;
1412
0
}
1413
1414
/**
1415
 * Instantiate new MCS module.
1416
 * @param transport transport
1417
 * @return new MCS module
1418
 */
1419
1420
rdpMcs* mcs_new(rdpTransport* transport)
1421
44.9k
{
1422
44.9k
  rdpMcs* mcs = NULL;
1423
1424
44.9k
  mcs = (rdpMcs*)calloc(1, sizeof(rdpMcs));
1425
1426
44.9k
  if (!mcs)
1427
0
    return NULL;
1428
1429
44.9k
  mcs->transport = transport;
1430
44.9k
  mcs_init_domain_parameters(&mcs->targetParameters, 34, 2, 0, 0xFFFF);
1431
44.9k
  mcs_init_domain_parameters(&mcs->minimumParameters, 1, 1, 1, 0x420);
1432
44.9k
  mcs_init_domain_parameters(&mcs->maximumParameters, 0xFFFF, 0xFC17, 0xFFFF, 0xFFFF);
1433
44.9k
  mcs_init_domain_parameters(&mcs->domainParameters, 0, 0, 0, 0xFFFF);
1434
44.9k
  mcs->channelCount = 0;
1435
44.9k
  mcs->channelMaxCount = CHANNEL_MAX_COUNT;
1436
44.9k
  mcs->baseChannelId = MCS_GLOBAL_CHANNEL_ID + 1;
1437
44.9k
  mcs->channels = (rdpMcsChannel*)calloc(mcs->channelMaxCount, sizeof(rdpMcsChannel));
1438
1439
44.9k
  if (!mcs->channels)
1440
0
    goto out_free;
1441
1442
44.9k
  return mcs;
1443
0
out_free:
1444
0
  free(mcs);
1445
0
  return NULL;
1446
44.9k
}
1447
1448
/**
1449
 * Free MCS module.
1450
 * @param mcs MCS module to be freed
1451
 */
1452
1453
void mcs_free(rdpMcs* mcs)
1454
44.9k
{
1455
44.9k
  if (mcs)
1456
44.9k
  {
1457
44.9k
    free(mcs->channels);
1458
44.9k
    free(mcs);
1459
44.9k
  }
1460
44.9k
}
1461
1462
BOOL mcs_server_apply_to_settings(const rdpMcs* mcs, rdpSettings* settings)
1463
0
{
1464
0
  BOOL rc = FALSE;
1465
1466
0
  WINPR_ASSERT(mcs);
1467
0
  WINPR_ASSERT(settings);
1468
1469
0
  if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, mcs->channelCount))
1470
0
    goto fail;
1471
1472
0
  for (UINT32 x = 0; x < mcs->channelCount; x++)
1473
0
  {
1474
0
    const rdpMcsChannel* current = &mcs->channels[x];
1475
0
    CHANNEL_DEF def = { 0 };
1476
0
    def.options = current->options;
1477
0
    memcpy(def.name, current->Name, sizeof(def.name));
1478
0
    if (!freerdp_settings_set_pointer_array(settings, FreeRDP_ChannelDefArray, x, &def))
1479
0
      goto fail;
1480
0
  }
1481
1482
0
  rc = TRUE;
1483
0
fail:
1484
0
  if (!rc)
1485
0
    WLog_WARN(TAG, "failed to apply settings");
1486
1487
0
  return rc;
1488
0
}