Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/core/rdp.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * RDP Core
4
 *
5
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2014 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
#include <freerdp/config.h>
22
23
#include "settings.h"
24
25
#include <winpr/crt.h>
26
#include <winpr/string.h>
27
#include <winpr/synch.h>
28
#include <winpr/assert.h>
29
30
#include "rdp.h"
31
32
#include "state.h"
33
#include "info.h"
34
#include "utils.h"
35
#include "mcs.h"
36
#include "redirection.h"
37
38
#include <freerdp/codec/bulk.h>
39
#include <freerdp/crypto/per.h>
40
#include <freerdp/log.h>
41
#include <freerdp/buildflags.h>
42
43
14.9k
#define RDP_TAG FREERDP_TAG("core.rdp")
44
45
static const char* DATA_PDU_TYPE_STRINGS[80] = {
46
  "?",
47
  "?",      /* 0x00 - 0x01 */
48
  "Update", /* 0x02 */
49
  "?",
50
  "?",
51
  "?",
52
  "?",
53
  "?",
54
  "?",
55
  "?",
56
  "?", /* 0x03 - 0x0A */
57
  "?",
58
  "?",
59
  "?",
60
  "?",
61
  "?",
62
  "?",
63
  "?",
64
  "?",
65
  "?",       /* 0x0B - 0x13 */
66
  "Control", /* 0x14 */
67
  "?",
68
  "?",
69
  "?",
70
  "?",
71
  "?",
72
  "?",       /* 0x15 - 0x1A */
73
  "Pointer", /* 0x1B */
74
  "Input",   /* 0x1C */
75
  "?",
76
  "?",                            /* 0x1D - 0x1E */
77
  "Synchronize",                  /* 0x1F */
78
  "?",                            /* 0x20 */
79
  "Refresh Rect",                 /* 0x21 */
80
  "Play Sound",                   /* 0x22 */
81
  "Suppress Output",              /* 0x23 */
82
  "Shutdown Request",             /* 0x24 */
83
  "Shutdown Denied",              /* 0x25 */
84
  "Save Session Info",            /* 0x26 */
85
  "Font List",                    /* 0x27 */
86
  "Font Map",                     /* 0x28 */
87
  "Set Keyboard Indicators",      /* 0x29 */
88
  "?",                            /* 0x2A */
89
  "Bitmap Cache Persistent List", /* 0x2B */
90
  "Bitmap Cache Error",           /* 0x2C */
91
  "Set Keyboard IME Status",      /* 0x2D */
92
  "Offscreen Cache Error",        /* 0x2E */
93
  "Set Error Info",               /* 0x2F */
94
  "Draw Nine Grid Error",         /* 0x30 */
95
  "Draw GDI+ Error",              /* 0x31 */
96
  "ARC Status",                   /* 0x32 */
97
  "?",
98
  "?",
99
  "?",              /* 0x33 - 0x35 */
100
  "Status Info",    /* 0x36 */
101
  "Monitor Layout", /* 0x37 */
102
  "FrameAcknowledge",
103
  "?",
104
  "?", /* 0x38 - 0x40 */
105
  "?",
106
  "?",
107
  "?",
108
  "?",
109
  "?",
110
  "?" /* 0x41 - 0x46 */
111
};
112
113
#define rdp_check_monitor_layout_pdu_state(rdp, expected) \
114
0
  rdp_check_monitor_layout_pdu_state_(rdp, expected, __FILE__, __func__, __LINE__)
115
116
static BOOL rdp_check_monitor_layout_pdu_state_(const rdpRdp* rdp, BOOL expected, const char* file,
117
                                                const char* fkt, size_t line)
118
0
{
119
0
  WINPR_ASSERT(rdp);
120
0
  if (expected != rdp->monitor_layout_pdu)
121
0
  {
122
0
    const DWORD log_level = WLOG_ERROR;
123
0
    if (WLog_IsLevelActive(rdp->log, log_level))
124
0
    {
125
0
      WLog_PrintMessage(rdp->log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
126
0
                        "Expected rdp->monitor_layout_pdu == %s",
127
0
                        expected ? "TRUE" : "FALSE");
128
0
    }
129
0
    return FALSE;
130
0
  }
131
0
  return TRUE;
132
0
}
133
134
#define rdp_set_monitor_layout_pdu_state(rdp, expected) \
135
72
  rdp_set_monitor_layout_pdu_state_(rdp, expected, __FILE__, __func__, __LINE__)
136
static BOOL rdp_set_monitor_layout_pdu_state_(rdpRdp* rdp, BOOL value, const char* file,
137
                                              const char* fkt, size_t line)
138
72
{
139
140
72
  WINPR_ASSERT(rdp);
141
72
  if (value && (value == rdp->monitor_layout_pdu))
142
3
  {
143
3
    const DWORD log_level = WLOG_WARN;
144
3
    if (WLog_IsLevelActive(rdp->log, log_level))
145
3
    {
146
3
      WLog_PrintMessage(rdp->log, WLOG_MESSAGE_TEXT, log_level, line, file, fkt,
147
3
                        "rdp->monitor_layout_pdu == %s, expected FALSE",
148
3
                        value ? "TRUE" : "FALSE");
149
3
    }
150
3
    return FALSE;
151
3
  }
152
69
  rdp->monitor_layout_pdu = value;
153
69
  return TRUE;
154
72
}
155
156
const char* data_pdu_type_to_string(UINT8 type)
157
1.66k
{
158
1.66k
  if (type >= ARRAYSIZE(DATA_PDU_TYPE_STRINGS))
159
248
    return "???";
160
1.41k
  return DATA_PDU_TYPE_STRINGS[type];
161
1.66k
}
162
163
static BOOL rdp_read_flow_control_pdu(rdpRdp* rdp, wStream* s, UINT16* type, UINT16* channel_id);
164
static BOOL rdp_write_share_control_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 type,
165
                                           UINT16 channel_id);
166
static BOOL rdp_write_share_data_header(rdpRdp* rdp, wStream* s, UINT16 length, BYTE type,
167
                                        UINT32 share_id);
168
169
/**
170
 * @brief Read RDP Security Header.
171
 * msdn{cc240579}
172
 *
173
 * @param s stream
174
 * @param flags security flags
175
 *
176
 * @return \b TRUE for success, \b FALSE otherwise
177
 */
178
179
BOOL rdp_read_security_header(rdpRdp* rdp, wStream* s, UINT16* flags, UINT16* length)
180
16.2k
{
181
16.2k
  char buffer[256] = { 0 };
182
16.2k
  WINPR_ASSERT(s);
183
16.2k
  WINPR_ASSERT(flags);
184
16.2k
  WINPR_ASSERT(rdp);
185
186
  /* Basic Security Header */
187
16.2k
  if ((length && (*length < 4)))
188
14.9k
  {
189
14.9k
    WLog_Print(rdp->log, WLOG_WARN,
190
14.9k
               "invalid security header length, have %" PRIu16 ", must be >= 4", *length);
191
14.9k
    return FALSE;
192
14.9k
  }
193
1.24k
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
194
2
    return FALSE;
195
196
1.24k
  Stream_Read_UINT16(s, *flags); /* flags */
197
1.24k
  Stream_Seek(s, 2);             /* flagsHi (unused) */
198
1.24k
  WLog_Print(rdp->log, WLOG_TRACE, "%s",
199
1.24k
             rdp_security_flag_string(*flags, buffer, sizeof(buffer)));
200
1.24k
  if (length)
201
1.24k
    *length -= 4;
202
203
1.24k
  return TRUE;
204
1.24k
}
205
206
/**
207
 * Write RDP Security Header.
208
 * msdn{cc240579}
209
 * @param s stream
210
 * @param flags security flags
211
 *
212
 * @return \b TRUE for success, \b FALSE otherwise
213
 */
214
215
BOOL rdp_write_security_header(rdpRdp* rdp, wStream* s, UINT16 flags)
216
3.12k
{
217
3.12k
  char buffer[256] = { 0 };
218
3.12k
  WINPR_ASSERT(s);
219
3.12k
  WINPR_ASSERT(rdp);
220
221
3.12k
  if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 4))
222
0
    return FALSE;
223
224
3.12k
  WLog_Print(rdp->log, WLOG_TRACE, "%s", rdp_security_flag_string(flags, buffer, sizeof(buffer)));
225
  /* Basic Security Header */
226
3.12k
  Stream_Write_UINT16(s, flags); /* flags */
227
3.12k
  Stream_Write_UINT16(s, 0);     /* flagsHi (unused) */
228
3.12k
  return TRUE;
229
3.12k
}
230
231
BOOL rdp_read_share_control_header(rdpRdp* rdp, wStream* s, UINT16* tpktLength,
232
                                   UINT16* remainingLength, UINT16* type, UINT16* channel_id)
233
14.9k
{
234
14.9k
  UINT16 len = 0;
235
14.9k
  UINT16 tmp = 0;
236
237
14.9k
  WINPR_ASSERT(rdp);
238
14.9k
  WINPR_ASSERT(s);
239
14.9k
  WINPR_ASSERT(type);
240
14.9k
  WINPR_ASSERT(channel_id);
241
242
14.9k
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 2))
243
783
    return FALSE;
244
245
  /* Share Control Header */
246
14.1k
  Stream_Read_UINT16(s, len); /* totalLength */
247
248
  /* If length is 0x8000 then we actually got a flow control PDU that we should ignore
249
   http://msdn.microsoft.com/en-us/library/cc240576.aspx */
250
14.1k
  if (len == 0x8000)
251
136
  {
252
136
    if (!rdp_read_flow_control_pdu(rdp, s, type, channel_id))
253
20
      return FALSE;
254
116
    *channel_id = 0;
255
116
    if (tpktLength)
256
116
      *tpktLength = 8; /* Flow control PDU is 8 bytes */
257
116
    if (remainingLength)
258
116
      *remainingLength = 0;
259
260
116
    char buffer[128] = { 0 };
261
116
    WLog_Print(rdp->log, WLOG_DEBUG,
262
116
               "[Flow control PDU] type=%s, tpktLength=%" PRIuz ", remainingLength=%" PRIuz,
263
116
               pdu_type_to_str(*type, buffer, sizeof(buffer)), tpktLength ? *tpktLength : 0,
264
116
               remainingLength ? *remainingLength : 0);
265
116
    return TRUE;
266
136
  }
267
268
14.0k
  if (len < 4U)
269
8.29k
  {
270
8.29k
    WLog_Print(rdp->log, WLOG_ERROR,
271
8.29k
               "Invalid share control header, length is %" PRIu16 ", must be >4", len);
272
8.29k
    return FALSE;
273
8.29k
  }
274
275
5.76k
  if (tpktLength)
276
5.76k
    *tpktLength = len;
277
278
5.76k
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 2))
279
124
    return FALSE;
280
281
5.63k
  Stream_Read_UINT16(s, tmp); /* pduType */
282
5.63k
  *type = tmp & 0x0F;         /* type is in the 4 least significant bits */
283
284
5.63k
  size_t remLen = len - 4;
285
5.63k
  if (len > 5)
286
5.53k
  {
287
5.53k
    if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 2))
288
74
      return FALSE;
289
290
5.45k
    Stream_Read_UINT16(s, *channel_id); /* pduSource */
291
5.45k
    remLen = len - 6;
292
5.45k
  }
293
107
  else
294
107
    *channel_id = 0; /* Windows XP can send such short DEACTIVATE_ALL PDUs. */
295
296
5.56k
  char buffer[128] = { 0 };
297
5.56k
  WLog_Print(rdp->log, WLOG_DEBUG, "type=%s, tpktLength=%" PRIuz ", remainingLength=%" PRIuz,
298
5.56k
             pdu_type_to_str(*type, buffer, sizeof(buffer)), len, remLen);
299
5.56k
  if (remainingLength)
300
5.56k
    *remainingLength = remLen;
301
5.56k
  return Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, remLen);
302
5.63k
}
303
304
BOOL rdp_write_share_control_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 type,
305
                                    UINT16 channel_id)
306
0
{
307
0
  WINPR_ASSERT(s);
308
0
  WINPR_ASSERT(rdp);
309
310
0
  if (length < RDP_PACKET_HEADER_MAX_LENGTH)
311
0
    return FALSE;
312
0
  if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 6))
313
0
    return FALSE;
314
0
  length -= RDP_PACKET_HEADER_MAX_LENGTH;
315
  /* Share Control Header */
316
0
  Stream_Write_UINT16(s, length);      /* totalLength */
317
0
  Stream_Write_UINT16(s, type | 0x10); /* pduType */
318
0
  Stream_Write_UINT16(s, channel_id);  /* pduSource */
319
0
  return TRUE;
320
0
}
321
322
BOOL rdp_read_share_data_header(rdpRdp* rdp, wStream* s, UINT16* length, BYTE* type,
323
                                UINT32* shareId, BYTE* compressedType, UINT16* compressedLength)
324
24.7k
{
325
24.7k
  WINPR_ASSERT(s);
326
24.7k
  WINPR_ASSERT(rdp);
327
328
24.7k
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 12))
329
8.54k
    return FALSE;
330
331
  /* Share Data Header */
332
16.1k
  Stream_Read_UINT32(s, *shareId);          /* shareId (4 bytes) */
333
16.1k
  Stream_Seek_UINT8(s);                     /* pad1 (1 byte) */
334
16.1k
  Stream_Seek_UINT8(s);                     /* streamId (1 byte) */
335
16.1k
  Stream_Read_UINT16(s, *length);           /* uncompressedLength (2 bytes) */
336
16.1k
  Stream_Read_UINT8(s, *type);              /* pduType2, Data PDU Type (1 byte) */
337
16.1k
  Stream_Read_UINT8(s, *compressedType);    /* compressedType (1 byte) */
338
16.1k
  Stream_Read_UINT16(s, *compressedLength); /* compressedLength (2 bytes) */
339
16.1k
  return TRUE;
340
24.7k
}
341
342
BOOL rdp_write_share_data_header(rdpRdp* rdp, wStream* s, UINT16 length, BYTE type, UINT32 share_id)
343
0
{
344
0
  const size_t headerLen = RDP_PACKET_HEADER_MAX_LENGTH + RDP_SHARE_CONTROL_HEADER_LENGTH +
345
0
                           RDP_SHARE_DATA_HEADER_LENGTH;
346
347
0
  WINPR_ASSERT(s);
348
0
  WINPR_ASSERT(rdp);
349
350
0
  if (length < headerLen)
351
0
    return FALSE;
352
0
  length -= headerLen;
353
0
  if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, (s), 12))
354
0
    return FALSE;
355
356
  /* Share Data Header */
357
0
  Stream_Write_UINT32(s, share_id);  /* shareId (4 bytes) */
358
0
  Stream_Write_UINT8(s, 0);          /* pad1 (1 byte) */
359
0
  Stream_Write_UINT8(s, STREAM_LOW); /* streamId (1 byte) */
360
0
  Stream_Write_UINT16(s, length);    /* uncompressedLength (2 bytes) */
361
0
  Stream_Write_UINT8(s, type);       /* pduType2, Data PDU Type (1 byte) */
362
0
  Stream_Write_UINT8(s, 0);          /* compressedType (1 byte) */
363
0
  Stream_Write_UINT16(s, 0);         /* compressedLength (2 bytes) */
364
0
  return TRUE;
365
0
}
366
367
static BOOL rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header)
368
3.12k
{
369
3.12k
  WINPR_ASSERT(rdp);
370
3.12k
  WINPR_ASSERT(s);
371
372
3.12k
  if (rdp->do_crypt)
373
0
  {
374
0
    if (!Stream_SafeSeek(s, 12))
375
0
      return FALSE;
376
377
0
    if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
378
0
    {
379
0
      if (!Stream_SafeSeek(s, 4))
380
0
        return FALSE;
381
0
    }
382
383
0
    rdp->sec_flags |= SEC_ENCRYPT;
384
385
0
    if (rdp->do_secure_checksum)
386
0
      rdp->sec_flags |= SEC_SECURE_CHECKSUM;
387
0
  }
388
3.12k
  else if (rdp->sec_flags != 0 || sec_header)
389
3.12k
  {
390
3.12k
    if (!Stream_SafeSeek(s, 4))
391
0
      return FALSE;
392
3.12k
  }
393
394
3.12k
  return TRUE;
395
3.12k
}
396
397
wStream* rdp_send_stream_init(rdpRdp* rdp)
398
0
{
399
0
  wStream* s = NULL;
400
401
0
  WINPR_ASSERT(rdp);
402
0
  WINPR_ASSERT(rdp->transport);
403
404
0
  s = transport_send_stream_init(rdp->transport, 4096);
405
406
0
  if (!s)
407
0
    return NULL;
408
409
0
  if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
410
0
    goto fail;
411
412
0
  if (!rdp_security_stream_init(rdp, s, FALSE))
413
0
    goto fail;
414
415
0
  return s;
416
0
fail:
417
0
  Stream_Release(s);
418
0
  return NULL;
419
0
}
420
421
wStream* rdp_send_stream_pdu_init(rdpRdp* rdp)
422
0
{
423
0
  wStream* s = rdp_send_stream_init(rdp);
424
425
0
  if (!s)
426
0
    return NULL;
427
428
0
  if (!Stream_SafeSeek(s, RDP_SHARE_CONTROL_HEADER_LENGTH))
429
0
    goto fail;
430
431
0
  return s;
432
0
fail:
433
0
  Stream_Release(s);
434
0
  return NULL;
435
0
}
436
437
wStream* rdp_data_pdu_init(rdpRdp* rdp)
438
0
{
439
0
  wStream* s = rdp_send_stream_pdu_init(rdp);
440
441
0
  if (!s)
442
0
    return NULL;
443
444
0
  if (!Stream_SafeSeek(s, RDP_SHARE_DATA_HEADER_LENGTH))
445
0
    goto fail;
446
447
0
  return s;
448
0
fail:
449
0
  Stream_Release(s);
450
0
  return NULL;
451
0
}
452
453
BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
454
791
{
455
791
  WINPR_ASSERT(rdp);
456
457
791
  rdp->errorInfo = errorInfo;
458
459
791
  if (rdp->errorInfo != ERRINFO_SUCCESS)
460
776
  {
461
776
    rdpContext* context = rdp->context;
462
776
    WINPR_ASSERT(context);
463
464
776
    rdp_print_errinfo(rdp->errorInfo);
465
466
776
    if (context)
467
776
    {
468
776
      freerdp_set_last_error_log(context, MAKE_FREERDP_ERROR(ERRINFO, errorInfo));
469
470
776
      if (context->pubSub)
471
300
      {
472
300
        ErrorInfoEventArgs e = { 0 };
473
300
        EventArgsInit(&e, "freerdp");
474
300
        e.code = rdp->errorInfo;
475
300
        PubSub_OnErrorInfo(context->pubSub, context, &e);
476
300
      }
477
776
    }
478
0
    else
479
0
      WLog_Print(rdp->log, WLOG_ERROR, "missing context=%p", context);
480
776
  }
481
15
  else
482
15
  {
483
15
    freerdp_set_last_error_log(rdp->context, FREERDP_ERROR_SUCCESS);
484
15
  }
485
486
791
  return TRUE;
487
791
}
488
489
wStream* rdp_message_channel_pdu_init(rdpRdp* rdp)
490
3.12k
{
491
3.12k
  wStream* s = NULL;
492
493
3.12k
  WINPR_ASSERT(rdp);
494
495
3.12k
  s = transport_send_stream_init(rdp->transport, 4096);
496
497
3.12k
  if (!s)
498
0
    return NULL;
499
500
3.12k
  if (!Stream_SafeSeek(s, RDP_PACKET_HEADER_MAX_LENGTH))
501
0
    goto fail;
502
503
3.12k
  if (!rdp_security_stream_init(rdp, s, TRUE))
504
0
    goto fail;
505
506
3.12k
  return s;
507
0
fail:
508
0
  Stream_Release(s);
509
0
  return NULL;
510
3.12k
}
511
512
/**
513
 * Read an RDP packet header.
514
 * @param rdp rdp module
515
 * @param s stream
516
 * @param length RDP packet length
517
 * @param channelId channel id
518
 *
519
 * @return \b TRUE for success, \b FALSE otherwise
520
 */
521
522
BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId)
523
44.9k
{
524
44.9k
  BYTE li = 0;
525
44.9k
  BYTE byte = 0;
526
44.9k
  BYTE code = 0;
527
44.9k
  BYTE choice = 0;
528
44.9k
  UINT16 initiator = 0;
529
530
44.9k
  WINPR_ASSERT(rdp);
531
44.9k
  WINPR_ASSERT(rdp->settings);
532
44.9k
  WINPR_ASSERT(s);
533
44.9k
  DomainMCSPDU MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataRequest
534
44.9k
                                                    : DomainMCSPDU_SendDataIndication;
535
536
44.9k
  *channelId = 0; /* Initialize in case of early abort */
537
44.9k
  if (!tpkt_read_header(s, length))
538
10.8k
    return FALSE;
539
540
34.0k
  if (!tpdu_read_header(s, &code, &li, *length))
541
32.1k
    return FALSE;
542
543
1.93k
  if (code != X224_TPDU_DATA)
544
1.03k
  {
545
1.03k
    if (code == X224_TPDU_DISCONNECT_REQUEST)
546
889
    {
547
889
      WLog_Print(rdp->log, WLOG_WARN, "Received X224_TPDU_DISCONNECT_REQUEST, terminating");
548
889
      utils_abort_connect(rdp);
549
889
      return TRUE;
550
889
    }
551
552
149
    WLog_Print(rdp->log, WLOG_WARN,
553
149
               "Unexpected X224 TPDU type %s [%08" PRIx32 "] instead of %s",
554
149
               tpdu_type_to_string(code), code, tpdu_type_to_string(X224_TPDU_DATA));
555
149
    return FALSE;
556
1.03k
  }
557
558
892
  if (!per_read_choice(s, &choice))
559
7
    return FALSE;
560
561
885
  const DomainMCSPDU domainMCSPDU = (DomainMCSPDU)(choice >> 2);
562
563
885
  if (domainMCSPDU != MCSPDU)
564
623
  {
565
623
    if (domainMCSPDU != DomainMCSPDU_DisconnectProviderUltimatum)
566
59
    {
567
59
      WLog_Print(rdp->log, WLOG_WARN, "Received %s instead of %s",
568
59
                 mcs_domain_pdu_string(domainMCSPDU), mcs_domain_pdu_string(MCSPDU));
569
59
      return FALSE;
570
59
    }
571
623
  }
572
573
826
  MCSPDU = domainMCSPDU;
574
575
826
  if (*length < 8U)
576
7
  {
577
7
    WLog_Print(rdp->log, WLOG_WARN, "TPDU invalid length, got %" PRIu16 ", expected at least 8",
578
7
               *length);
579
7
    return FALSE;
580
7
  }
581
582
819
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, *length - 8))
583
0
    return FALSE;
584
585
819
  if (MCSPDU == DomainMCSPDU_DisconnectProviderUltimatum)
586
562
  {
587
562
    int reason = 0;
588
562
    TerminateEventArgs e = { 0 };
589
590
562
    if (!mcs_recv_disconnect_provider_ultimatum(rdp->mcs, s, &reason))
591
2
      return FALSE;
592
593
560
    rdpContext* context = rdp->context;
594
560
    WINPR_ASSERT(context);
595
560
    context->disconnectUltimatum = reason;
596
597
560
    if (rdp->errorInfo == ERRINFO_SUCCESS)
598
527
    {
599
      /**
600
       * Some servers like Windows Server 2008 R2 do not send the error info pdu
601
       * when the user logs off like they should. Map DisconnectProviderUltimatum
602
       * to a ERRINFO_LOGOFF_BY_USER when the errinfo code is ERRINFO_SUCCESS.
603
       */
604
527
      if (reason == Disconnect_Ultimatum_provider_initiated)
605
8
        rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
606
519
      else if (reason == Disconnect_Ultimatum_user_requested)
607
18
        rdp_set_error_info(rdp, ERRINFO_LOGOFF_BY_USER);
608
501
      else
609
501
        rdp_set_error_info(rdp, ERRINFO_RPC_INITIATED_DISCONNECT);
610
527
    }
611
612
560
    WLog_Print(rdp->log, WLOG_DEBUG, "DisconnectProviderUltimatum: reason: %d", reason);
613
560
    utils_abort_connect(rdp);
614
560
    EventArgsInit(&e, "freerdp");
615
560
    e.code = 0;
616
560
    PubSub_OnTerminate(rdp->pubSub, context, &e);
617
560
    return TRUE;
618
560
  }
619
620
257
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 5))
621
4
    return FALSE;
622
623
253
  if (!per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID)) /* initiator (UserId) */
624
29
    return FALSE;
625
626
224
  if (!per_read_integer16(s, channelId, 0)) /* channelId */
627
0
    return FALSE;
628
629
224
  Stream_Read_UINT8(s, byte); /* dataPriority + Segmentation (0x70) */
630
631
224
  if (!per_read_length(s, length)) /* userData (OCTET_STRING) */
632
14
    return FALSE;
633
634
210
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, *length))
635
38
    return FALSE;
636
637
172
  return TRUE;
638
210
}
639
640
/**
641
 * Write an RDP packet header.
642
 * @param rdp rdp module
643
 * @param s stream
644
 * @param length RDP packet length
645
 * @param channelId channel id
646
 *
647
 * @return \b TRUE for success, \b FALSE otherwise
648
 */
649
650
BOOL rdp_write_header(rdpRdp* rdp, wStream* s, UINT16 length, UINT16 channelId)
651
3.12k
{
652
3.12k
  WINPR_ASSERT(rdp);
653
3.12k
  WINPR_ASSERT(rdp->settings);
654
3.12k
  WINPR_ASSERT(s);
655
3.12k
  WINPR_ASSERT(length >= RDP_PACKET_HEADER_MAX_LENGTH);
656
657
3.12k
  DomainMCSPDU MCSPDU = (rdp->settings->ServerMode) ? DomainMCSPDU_SendDataIndication
658
3.12k
                                                    : DomainMCSPDU_SendDataRequest;
659
660
3.12k
  if ((rdp->sec_flags & SEC_ENCRYPT) &&
661
3.12k
      (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS))
662
0
  {
663
0
    const UINT16 body_length = length - RDP_PACKET_HEADER_MAX_LENGTH;
664
0
    const UINT16 pad = 8 - (body_length % 8);
665
666
0
    if (pad != 8)
667
0
      length += pad;
668
0
  }
669
670
3.12k
  if (!mcs_write_domain_mcspdu_header(s, MCSPDU, length, 0))
671
0
    return FALSE;
672
3.12k
  if (!per_write_integer16(s, rdp->mcs->userId, MCS_BASE_CHANNEL_ID)) /* initiator */
673
0
    return FALSE;
674
3.12k
  if (!per_write_integer16(s, channelId, 0)) /* channelId */
675
0
    return FALSE;
676
3.12k
  if (!Stream_EnsureRemainingCapacity(s, 3))
677
0
    return FALSE;
678
3.12k
  Stream_Write_UINT8(s, 0x70); /* dataPriority + segmentation */
679
  /*
680
   * We always encode length in two bytes, even though we could use
681
   * only one byte if length <= 0x7F. It is just easier that way,
682
   * because we can leave room for fixed-length header, store all
683
   * the data first and then store the header.
684
   */
685
3.12k
  length = (length - RDP_PACKET_HEADER_MAX_LENGTH) | 0x8000;
686
3.12k
  Stream_Write_UINT16_BE(s, length); /* userData (OCTET_STRING) */
687
3.12k
  return TRUE;
688
3.12k
}
689
690
static BOOL rdp_security_stream_out(rdpRdp* rdp, wStream* s, int length, UINT32 sec_flags,
691
                                    UINT32* pad)
692
3.12k
{
693
3.12k
  BOOL status = 0;
694
3.12k
  WINPR_ASSERT(rdp);
695
3.12k
  sec_flags |= rdp->sec_flags;
696
3.12k
  *pad = 0;
697
698
3.12k
  if (sec_flags != 0)
699
3.12k
  {
700
3.12k
    if (!rdp_write_security_header(rdp, s, sec_flags))
701
0
      return FALSE;
702
703
3.12k
    if (sec_flags & SEC_ENCRYPT)
704
0
    {
705
0
      BOOL res = FALSE;
706
0
      if (!security_lock(rdp))
707
0
        return FALSE;
708
709
0
      if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
710
0
      {
711
0
        BYTE* data = Stream_PointerAs(s, BYTE) + 12;
712
0
        length = length - (data - Stream_Buffer(s));
713
0
        Stream_Write_UINT16(s, 0x10); /* length */
714
0
        Stream_Write_UINT8(s, 0x1);   /* TSFIPS_VERSION 1*/
715
        /* handle padding */
716
0
        *pad = 8 - (length % 8);
717
718
0
        if (*pad == 8)
719
0
          *pad = 0;
720
721
0
        if (*pad)
722
0
          memset(data + length, 0, *pad);
723
724
0
        Stream_Write_UINT8(s, *pad);
725
726
0
        if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, s, 8))
727
0
          goto unlock;
728
0
        if (!security_hmac_signature(data, length, Stream_Pointer(s), 8, rdp))
729
0
          goto unlock;
730
731
0
        Stream_Seek(s, 8);
732
0
        if (!security_fips_encrypt(data, length + *pad, rdp))
733
0
          goto unlock;
734
0
      }
735
0
      else
736
0
      {
737
0
        const BYTE* data = Stream_PointerAs(s, const BYTE) + 8;
738
0
        length = length - (data - Stream_Buffer(s));
739
740
0
        if (!Stream_CheckAndLogRequiredCapacityWLog(rdp->log, s, 8))
741
0
          goto unlock;
742
0
        if (sec_flags & SEC_SECURE_CHECKSUM)
743
0
          status = security_salted_mac_signature(rdp, data, length, TRUE,
744
0
                                                 Stream_Pointer(s), 8);
745
0
        else
746
0
          status =
747
0
              security_mac_signature(rdp, data, length, Stream_PointerAs(s, BYTE), 8);
748
749
0
        if (!status)
750
0
          goto unlock;
751
752
0
        Stream_Seek(s, 8);
753
754
0
        if (!security_encrypt(Stream_Pointer(s), length, rdp))
755
0
          goto unlock;
756
0
      }
757
0
      res = TRUE;
758
759
0
    unlock:
760
761
0
      if (!security_unlock(rdp))
762
0
        return FALSE;
763
0
      if (!res)
764
0
        return FALSE;
765
0
    }
766
767
3.12k
    rdp->sec_flags = 0;
768
3.12k
  }
769
770
3.12k
  return TRUE;
771
3.12k
}
772
773
static UINT32 rdp_get_sec_bytes(rdpRdp* rdp, UINT16 sec_flags)
774
0
{
775
0
  UINT32 sec_bytes = 0;
776
777
0
  if (rdp->sec_flags & SEC_ENCRYPT)
778
0
  {
779
0
    sec_bytes = 12;
780
781
0
    if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
782
0
      sec_bytes += 4;
783
0
  }
784
0
  else if (rdp->sec_flags != 0 || sec_flags != 0)
785
0
  {
786
0
    sec_bytes = 4;
787
0
  }
788
0
  else
789
0
  {
790
0
    sec_bytes = 0;
791
0
  }
792
793
0
  return sec_bytes;
794
0
}
795
796
/**
797
 * Send an RDP packet.
798
 * @param rdp RDP module
799
 * @param s stream
800
 * @param channel_id channel id
801
 */
802
803
BOOL rdp_send(rdpRdp* rdp, wStream* s, UINT16 channel_id)
804
0
{
805
0
  BOOL rc = FALSE;
806
0
  UINT32 pad = 0;
807
0
  UINT16 length = 0;
808
809
0
  if (!s)
810
0
    return FALSE;
811
812
0
  if (!rdp)
813
0
    goto fail;
814
815
0
  length = Stream_GetPosition(s);
816
0
  Stream_SetPosition(s, 0);
817
0
  if (!rdp_write_header(rdp, s, length, channel_id))
818
0
    goto fail;
819
820
0
  if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
821
0
    goto fail;
822
823
0
  length += pad;
824
0
  Stream_SetPosition(s, length);
825
0
  Stream_SealLength(s);
826
827
0
  if (transport_write(rdp->transport, s) < 0)
828
0
    goto fail;
829
830
0
  rc = TRUE;
831
0
fail:
832
0
  Stream_Release(s);
833
0
  return rc;
834
0
}
835
836
BOOL rdp_send_pdu(rdpRdp* rdp, wStream* s, UINT16 type, UINT16 channel_id)
837
0
{
838
0
  UINT16 length = 0;
839
0
  UINT32 sec_bytes = 0;
840
0
  size_t sec_hold = 0;
841
0
  UINT32 pad = 0;
842
843
0
  if (!rdp || !s)
844
0
    return FALSE;
845
846
0
  length = Stream_GetPosition(s);
847
0
  Stream_SetPosition(s, 0);
848
0
  if (!rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID))
849
0
    return FALSE;
850
0
  sec_bytes = rdp_get_sec_bytes(rdp, 0);
851
0
  sec_hold = Stream_GetPosition(s);
852
0
  Stream_Seek(s, sec_bytes);
853
0
  if (!rdp_write_share_control_header(rdp, s, length - sec_bytes, type, channel_id))
854
0
    return FALSE;
855
0
  Stream_SetPosition(s, sec_hold);
856
857
0
  if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
858
0
    return FALSE;
859
860
0
  length += pad;
861
0
  Stream_SetPosition(s, length);
862
0
  Stream_SealLength(s);
863
864
0
  if (transport_write(rdp->transport, s) < 0)
865
0
    return FALSE;
866
867
0
  return TRUE;
868
0
}
869
870
BOOL rdp_send_data_pdu(rdpRdp* rdp, wStream* s, BYTE type, UINT16 channel_id)
871
0
{
872
0
  BOOL rc = FALSE;
873
0
  size_t length = 0;
874
0
  UINT32 sec_bytes = 0;
875
0
  size_t sec_hold = 0;
876
0
  UINT32 pad = 0;
877
878
0
  if (!s)
879
0
    return FALSE;
880
881
0
  if (!rdp)
882
0
    goto fail;
883
884
0
  length = Stream_GetPosition(s);
885
0
  Stream_SetPosition(s, 0);
886
0
  if (!rdp_write_header(rdp, s, length, MCS_GLOBAL_CHANNEL_ID))
887
0
    goto fail;
888
0
  sec_bytes = rdp_get_sec_bytes(rdp, 0);
889
0
  sec_hold = Stream_GetPosition(s);
890
0
  Stream_Seek(s, sec_bytes);
891
0
  if (!rdp_write_share_control_header(rdp, s, length - sec_bytes, PDU_TYPE_DATA, channel_id))
892
0
    goto fail;
893
0
  if (!rdp_write_share_data_header(rdp, s, length - sec_bytes, type, rdp->settings->ShareId))
894
0
    goto fail;
895
0
  Stream_SetPosition(s, sec_hold);
896
897
0
  if (!rdp_security_stream_out(rdp, s, length, 0, &pad))
898
0
    goto fail;
899
900
0
  length += pad;
901
0
  Stream_SetPosition(s, length);
902
0
  Stream_SealLength(s);
903
0
  WLog_Print(rdp->log, WLOG_DEBUG,
904
0
             "sending data (type=0x%x size=%" PRIuz " channelId=%" PRIu16 ")", type,
905
0
             Stream_Length(s), channel_id);
906
907
0
  rdp->outPackets++;
908
0
  if (transport_write(rdp->transport, s) < 0)
909
0
    goto fail;
910
911
0
  rc = TRUE;
912
0
fail:
913
0
  Stream_Release(s);
914
0
  return rc;
915
0
}
916
917
BOOL rdp_send_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 sec_flags)
918
3.12k
{
919
3.12k
  BOOL rc = FALSE;
920
3.12k
  UINT16 length = 0;
921
3.12k
  UINT32 pad = 0;
922
923
3.12k
  WINPR_ASSERT(rdp);
924
3.12k
  WINPR_ASSERT(s);
925
926
3.12k
  length = Stream_GetPosition(s);
927
3.12k
  Stream_SetPosition(s, 0);
928
3.12k
  if (!rdp_write_header(rdp, s, length, rdp->mcs->messageChannelId))
929
0
    goto fail;
930
931
3.12k
  if (!rdp_security_stream_out(rdp, s, length, sec_flags, &pad))
932
0
    goto fail;
933
934
3.12k
  length += pad;
935
3.12k
  Stream_SetPosition(s, length);
936
3.12k
  Stream_SealLength(s);
937
938
3.12k
  if (transport_write(rdp->transport, s) < 0)
939
3.12k
    goto fail;
940
941
0
  rc = TRUE;
942
3.12k
fail:
943
3.12k
  Stream_Release(s);
944
3.12k
  return rc;
945
0
}
946
947
static BOOL rdp_recv_server_shutdown_denied_pdu(rdpRdp* rdp, wStream* s)
948
19
{
949
19
  return TRUE;
950
19
}
951
952
static BOOL rdp_recv_server_set_keyboard_indicators_pdu(rdpRdp* rdp, wStream* s)
953
94
{
954
94
  UINT16 unitId = 0;
955
94
  UINT16 ledFlags = 0;
956
957
94
  WINPR_ASSERT(rdp);
958
94
  WINPR_ASSERT(s);
959
960
94
  rdpContext* context = rdp->context;
961
94
  WINPR_ASSERT(context);
962
94
  WINPR_ASSERT(context->update);
963
964
94
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
965
30
    return FALSE;
966
967
64
  Stream_Read_UINT16(s, unitId);   /* unitId (2 bytes) */
968
64
  Stream_Read_UINT16(s, ledFlags); /* ledFlags (2 bytes) */
969
64
  return IFCALLRESULT(TRUE, context->update->SetKeyboardIndicators, context, ledFlags);
970
94
}
971
972
static BOOL rdp_recv_server_set_keyboard_ime_status_pdu(rdpRdp* rdp, wStream* s)
973
92
{
974
92
  UINT16 unitId = 0;
975
92
  UINT32 imeState = 0;
976
92
  UINT32 imeConvMode = 0;
977
978
92
  if (!rdp || !rdp->input)
979
0
    return FALSE;
980
981
92
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 10))
982
37
    return FALSE;
983
984
55
  Stream_Read_UINT16(s, unitId);      /* unitId (2 bytes) */
985
55
  Stream_Read_UINT32(s, imeState);    /* imeState (4 bytes) */
986
55
  Stream_Read_UINT32(s, imeConvMode); /* imeConvMode (4 bytes) */
987
55
  IFCALL(rdp->update->SetKeyboardImeStatus, rdp->context, unitId, imeState, imeConvMode);
988
55
  return TRUE;
989
92
}
990
991
static BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s)
992
273
{
993
273
  UINT32 errorInfo = 0;
994
995
273
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
996
9
    return FALSE;
997
998
264
  Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */
999
264
  return rdp_set_error_info(rdp, errorInfo);
1000
273
}
1001
1002
static BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s)
1003
66
{
1004
66
  UINT32 arcStatus = 0;
1005
1006
66
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
1007
23
    return FALSE;
1008
1009
43
  Stream_Read_UINT32(s, arcStatus); /* arcStatus (4 bytes) */
1010
43
  WLog_Print(rdp->log, WLOG_WARN, "AutoReconnectStatus: 0x%08" PRIX32 "", arcStatus);
1011
43
  return TRUE;
1012
66
}
1013
1014
static BOOL rdp_recv_server_status_info_pdu(rdpRdp* rdp, wStream* s)
1015
66
{
1016
66
  UINT32 statusCode = 0;
1017
1018
66
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
1019
41
    return FALSE;
1020
1021
25
  Stream_Read_UINT32(s, statusCode); /* statusCode (4 bytes) */
1022
1023
25
  if (rdp->update->ServerStatusInfo)
1024
0
    return rdp->update->ServerStatusInfo(rdp->context, statusCode);
1025
1026
25
  return TRUE;
1027
25
}
1028
1029
static BOOL rdp_recv_monitor_layout_pdu(rdpRdp* rdp, wStream* s)
1030
123
{
1031
123
  UINT32 monitorCount = 0;
1032
123
  MONITOR_DEF* monitorDefArray = NULL;
1033
123
  BOOL ret = TRUE;
1034
1035
123
  WINPR_ASSERT(rdp);
1036
123
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 4))
1037
23
    return FALSE;
1038
1039
100
  Stream_Read_UINT32(s, monitorCount); /* monitorCount (4 bytes) */
1040
1041
100
  if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(rdp->log, s, monitorCount, 20ull))
1042
28
    return FALSE;
1043
1044
72
  monitorDefArray = (MONITOR_DEF*)calloc(monitorCount, sizeof(MONITOR_DEF));
1045
1046
72
  if (!monitorDefArray)
1047
0
    return FALSE;
1048
1049
5.72k
  for (UINT32 index = 0; index < monitorCount; index++)
1050
5.65k
  {
1051
5.65k
    MONITOR_DEF* monitor = &monitorDefArray[index];
1052
5.65k
    Stream_Read_INT32(s, monitor->left);   /* left (4 bytes) */
1053
5.65k
    Stream_Read_INT32(s, monitor->top);    /* top (4 bytes) */
1054
5.65k
    Stream_Read_INT32(s, monitor->right);  /* right (4 bytes) */
1055
5.65k
    Stream_Read_INT32(s, monitor->bottom); /* bottom (4 bytes) */
1056
5.65k
    Stream_Read_UINT32(s, monitor->flags); /* flags (4 bytes) */
1057
5.65k
  }
1058
1059
72
  IFCALLRET(rdp->update->RemoteMonitors, ret, rdp->context, monitorCount, monitorDefArray);
1060
72
  free(monitorDefArray);
1061
72
  if (!ret)
1062
0
    return FALSE;
1063
72
  return rdp_set_monitor_layout_pdu_state(rdp, TRUE);
1064
72
}
1065
1066
state_run_t rdp_recv_data_pdu(rdpRdp* rdp, wStream* s)
1067
9.74k
{
1068
9.74k
  BYTE type = 0;
1069
9.74k
  wStream* cs = NULL;
1070
9.74k
  UINT16 length = 0;
1071
9.74k
  UINT32 shareId = 0;
1072
9.74k
  BYTE compressedType = 0;
1073
9.74k
  UINT16 compressedLength = 0;
1074
1075
9.74k
  WINPR_ASSERT(rdp);
1076
9.74k
  if (!rdp_read_share_data_header(rdp, s, &length, &type, &shareId, &compressedType,
1077
9.74k
                                  &compressedLength))
1078
6.60k
  {
1079
6.60k
    WLog_Print(rdp->log, WLOG_ERROR, "rdp_read_share_data_header() failed");
1080
6.60k
    return STATE_RUN_FAILED;
1081
6.60k
  }
1082
1083
3.14k
  cs = s;
1084
1085
3.14k
  if (compressedType & PACKET_COMPRESSED)
1086
1.51k
  {
1087
1.51k
    UINT32 DstSize = 0;
1088
1.51k
    const BYTE* pDstData = NULL;
1089
1.51k
    UINT16 SrcSize = compressedLength - 18;
1090
1091
1.51k
    if ((compressedLength < 18) ||
1092
1.51k
        (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, SrcSize)))
1093
141
    {
1094
141
      WLog_Print(rdp->log, WLOG_ERROR,
1095
141
                 "bulk_decompress: not enough bytes for compressedLength %" PRIu16 "",
1096
141
                 compressedLength);
1097
141
      return STATE_RUN_FAILED;
1098
141
    }
1099
1100
1.37k
    if (bulk_decompress(rdp->bulk, Stream_ConstPointer(s), SrcSize, &pDstData, &DstSize,
1101
1.37k
                        compressedType))
1102
1.37k
    {
1103
1.37k
      cs = transport_take_from_pool(rdp->transport, DstSize);
1104
1.37k
      if (!cs)
1105
0
      {
1106
0
        WLog_Print(rdp->log, WLOG_ERROR, "Couldn't take stream from pool");
1107
0
        return STATE_RUN_FAILED;
1108
0
      }
1109
1110
1.37k
      Stream_SetPosition(cs, 0);
1111
1.37k
      Stream_Write(cs, pDstData, DstSize);
1112
1.37k
      Stream_SealLength(cs);
1113
1.37k
      Stream_SetPosition(cs, 0);
1114
1.37k
    }
1115
0
    else
1116
0
    {
1117
0
      WLog_Print(rdp->log, WLOG_ERROR, "bulk_decompress() failed");
1118
0
      return STATE_RUN_FAILED;
1119
0
    }
1120
1121
1.37k
    Stream_Seek(s, SrcSize);
1122
1.37k
  }
1123
1124
3.00k
  WLog_Print(rdp->log, WLOG_DEBUG, "recv %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "",
1125
3.00k
             data_pdu_type_to_string(type), type, length);
1126
1127
3.00k
  switch (type)
1128
3.00k
  {
1129
33
    case DATA_PDU_TYPE_UPDATE:
1130
33
      if (!update_recv(rdp->update, cs))
1131
33
      {
1132
33
        WLog_Print(rdp->log, WLOG_ERROR, "DATA_PDU_TYPE_UPDATE - update_recv() failed");
1133
33
        goto out_fail;
1134
33
      }
1135
1136
0
      break;
1137
1138
67
    case DATA_PDU_TYPE_CONTROL:
1139
67
      if (!rdp_recv_server_control_pdu(rdp, cs))
1140
62
      {
1141
62
        WLog_Print(rdp->log, WLOG_ERROR,
1142
62
                   "DATA_PDU_TYPE_CONTROL - rdp_recv_server_control_pdu() failed");
1143
62
        goto out_fail;
1144
62
      }
1145
1146
5
      break;
1147
1148
47
    case DATA_PDU_TYPE_POINTER:
1149
47
      if (!update_recv_pointer(rdp->update, cs))
1150
47
      {
1151
47
        WLog_Print(rdp->log, WLOG_ERROR,
1152
47
                   "DATA_PDU_TYPE_POINTER - update_recv_pointer() failed");
1153
47
        goto out_fail;
1154
47
      }
1155
1156
0
      break;
1157
1158
46
    case DATA_PDU_TYPE_SYNCHRONIZE:
1159
46
      if (!rdp_recv_server_synchronize_pdu(rdp, cs))
1160
28
      {
1161
28
        WLog_Print(rdp->log, WLOG_ERROR,
1162
28
                   "DATA_PDU_TYPE_SYNCHRONIZE - rdp_recv_synchronize_pdu() failed");
1163
28
        goto out_fail;
1164
28
      }
1165
1166
18
      break;
1167
1168
32
    case DATA_PDU_TYPE_PLAY_SOUND:
1169
32
      if (!update_recv_play_sound(rdp->update, cs))
1170
32
      {
1171
32
        WLog_Print(rdp->log, WLOG_ERROR,
1172
32
                   "DATA_PDU_TYPE_PLAY_SOUND - update_recv_play_sound() failed");
1173
32
        goto out_fail;
1174
32
      }
1175
1176
0
      break;
1177
1178
19
    case DATA_PDU_TYPE_SHUTDOWN_DENIED:
1179
19
      if (!rdp_recv_server_shutdown_denied_pdu(rdp, cs))
1180
0
      {
1181
0
        WLog_Print(
1182
0
            rdp->log, WLOG_ERROR,
1183
0
            "DATA_PDU_TYPE_SHUTDOWN_DENIED - rdp_recv_server_shutdown_denied_pdu() failed");
1184
0
        goto out_fail;
1185
0
      }
1186
1187
19
      break;
1188
1189
286
    case DATA_PDU_TYPE_SAVE_SESSION_INFO:
1190
286
      if (!rdp_recv_save_session_info(rdp, cs))
1191
192
      {
1192
192
        WLog_Print(rdp->log, WLOG_ERROR,
1193
192
                   "DATA_PDU_TYPE_SAVE_SESSION_INFO - rdp_recv_save_session_info() failed");
1194
192
        goto out_fail;
1195
192
      }
1196
1197
94
      break;
1198
1199
101
    case DATA_PDU_TYPE_FONT_MAP:
1200
101
      if (!rdp_recv_font_map_pdu(rdp, cs))
1201
0
      {
1202
0
        WLog_Print(rdp->log, WLOG_ERROR,
1203
0
                   "DATA_PDU_TYPE_FONT_MAP - rdp_recv_font_map_pdu() failed");
1204
0
        goto out_fail;
1205
0
      }
1206
1207
101
      break;
1208
1209
101
    case DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS:
1210
94
      if (!rdp_recv_server_set_keyboard_indicators_pdu(rdp, cs))
1211
30
      {
1212
30
        WLog_Print(rdp->log, WLOG_ERROR,
1213
30
                   "DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS - "
1214
30
                   "rdp_recv_server_set_keyboard_indicators_pdu() failed");
1215
30
        goto out_fail;
1216
30
      }
1217
1218
64
      break;
1219
1220
92
    case DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS:
1221
92
      if (!rdp_recv_server_set_keyboard_ime_status_pdu(rdp, cs))
1222
37
      {
1223
37
        WLog_Print(rdp->log, WLOG_ERROR,
1224
37
                   "DATA_PDU_TYPE_SET_KEYBOARD_IME_STATUS - "
1225
37
                   "rdp_recv_server_set_keyboard_ime_status_pdu() failed");
1226
37
        goto out_fail;
1227
37
      }
1228
1229
55
      break;
1230
1231
273
    case DATA_PDU_TYPE_SET_ERROR_INFO:
1232
273
      if (!rdp_recv_set_error_info_data_pdu(rdp, cs))
1233
9
      {
1234
9
        WLog_Print(
1235
9
            rdp->log, WLOG_ERROR,
1236
9
            "DATA_PDU_TYPE_SET_ERROR_INFO - rdp_recv_set_error_info_data_pdu() failed");
1237
9
        goto out_fail;
1238
9
      }
1239
1240
264
      break;
1241
1242
264
    case DATA_PDU_TYPE_ARC_STATUS:
1243
66
      if (!rdp_recv_server_auto_reconnect_status_pdu(rdp, cs))
1244
23
      {
1245
23
        WLog_Print(rdp->log, WLOG_ERROR,
1246
23
                   "DATA_PDU_TYPE_ARC_STATUS - "
1247
23
                   "rdp_recv_server_auto_reconnect_status_pdu() failed");
1248
23
        goto out_fail;
1249
23
      }
1250
1251
43
      break;
1252
1253
66
    case DATA_PDU_TYPE_STATUS_INFO:
1254
66
      if (!rdp_recv_server_status_info_pdu(rdp, cs))
1255
41
      {
1256
41
        WLog_Print(rdp->log, WLOG_ERROR,
1257
41
                   "DATA_PDU_TYPE_STATUS_INFO - rdp_recv_server_status_info_pdu() failed");
1258
41
        goto out_fail;
1259
41
      }
1260
1261
25
      break;
1262
1263
123
    case DATA_PDU_TYPE_MONITOR_LAYOUT:
1264
123
      if (!rdp_recv_monitor_layout_pdu(rdp, cs))
1265
54
      {
1266
54
        WLog_Print(rdp->log, WLOG_ERROR,
1267
54
                   "DATA_PDU_TYPE_MONITOR_LAYOUT - rdp_recv_monitor_layout_pdu() failed");
1268
54
        goto out_fail;
1269
54
      }
1270
1271
69
      break;
1272
1273
1.66k
    default:
1274
1.66k
      WLog_Print(rdp->log, WLOG_WARN,
1275
1.66k
                 "[UNHANDLED] %s Data PDU (0x%02" PRIX8 "), length: %" PRIu16 "",
1276
1.66k
                 data_pdu_type_to_string(type), type, length);
1277
1.66k
      break;
1278
3.00k
  }
1279
1280
2.41k
  if (cs != s)
1281
973
    Stream_Release(cs);
1282
1283
2.41k
  return STATE_RUN_SUCCESS;
1284
588
out_fail:
1285
1286
588
  if (cs != s)
1287
399
    Stream_Release(cs);
1288
1289
588
  return STATE_RUN_FAILED;
1290
3.00k
}
1291
1292
state_run_t rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s, UINT16 securityFlags)
1293
14.9k
{
1294
14.9k
  WINPR_ASSERT(rdp);
1295
14.9k
  WINPR_ASSERT(s);
1296
1297
14.9k
  if (securityFlags & SEC_AUTODETECT_REQ)
1298
0
  {
1299
    /* Server Auto-Detect Request PDU */
1300
0
    return autodetect_recv_request_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s);
1301
0
  }
1302
1303
14.9k
  if (securityFlags & SEC_AUTODETECT_RSP)
1304
0
  {
1305
    /* Client Auto-Detect Response PDU */
1306
0
    return autodetect_recv_response_packet(rdp->autodetect, RDP_TRANSPORT_TCP, s);
1307
0
  }
1308
1309
14.9k
  if (securityFlags & SEC_HEARTBEAT)
1310
0
  {
1311
    /* Heartbeat PDU */
1312
0
    return rdp_recv_heartbeat_packet(rdp, s);
1313
0
  }
1314
1315
14.9k
  if (securityFlags & SEC_TRANSPORT_REQ)
1316
0
  {
1317
0
    return multitransport_recv_request(rdp->multitransport, s);
1318
0
  }
1319
1320
14.9k
  if (securityFlags & SEC_TRANSPORT_RSP)
1321
0
  {
1322
0
    return multitransport_recv_response(rdp->multitransport, s);
1323
0
  }
1324
1325
14.9k
  if (securityFlags & SEC_LICENSE_PKT)
1326
0
  {
1327
0
    return license_recv(rdp->license, s);
1328
0
  }
1329
1330
14.9k
  if (securityFlags & SEC_LICENSE_ENCRYPT_CS)
1331
0
  {
1332
0
    return license_recv(rdp->license, s);
1333
0
  }
1334
1335
14.9k
  if (securityFlags & SEC_LICENSE_ENCRYPT_SC)
1336
0
  {
1337
0
    return license_recv(rdp->license, s);
1338
0
  }
1339
1340
14.9k
  return STATE_RUN_SUCCESS;
1341
14.9k
}
1342
1343
state_run_t rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s, UINT16 pduType, UINT16 length)
1344
7.99k
{
1345
7.99k
  state_run_t rc = STATE_RUN_FAILED;
1346
7.99k
  WINPR_ASSERT(rdp);
1347
1348
7.99k
  switch (pduType)
1349
7.99k
  {
1350
1.74k
    case PDU_TYPE_DATA:
1351
1.74k
      rc = rdp_recv_data_pdu(rdp, s);
1352
1.74k
      break;
1353
107
    case PDU_TYPE_SERVER_REDIRECTION:
1354
107
      rc = rdp_recv_enhanced_security_redirection_packet(rdp, s);
1355
107
      break;
1356
5
    case PDU_TYPE_FLOW_RESPONSE:
1357
9
    case PDU_TYPE_FLOW_STOP:
1358
11
    case PDU_TYPE_FLOW_TEST:
1359
11
      rc = STATE_RUN_SUCCESS;
1360
11
      break;
1361
6.13k
    default:
1362
6.13k
    {
1363
6.13k
      char buffer1[256] = { 0 };
1364
6.13k
      char buffer2[256] = { 0 };
1365
1366
6.13k
      WLog_Print(rdp->log, WLOG_ERROR, "expected %s, got %s",
1367
6.13k
                 pdu_type_to_str(PDU_TYPE_DEMAND_ACTIVE, buffer1, sizeof(buffer1)),
1368
6.13k
                 pdu_type_to_str(pduType, buffer2, sizeof(buffer2)));
1369
6.13k
      rc = STATE_RUN_FAILED;
1370
6.13k
    }
1371
6.13k
    break;
1372
7.99k
  }
1373
1374
7.99k
  if (!tpkt_ensure_stream_consumed(s, length))
1375
6.55k
    return STATE_RUN_FAILED;
1376
1.44k
  return rc;
1377
7.99k
}
1378
1379
BOOL rdp_read_flow_control_pdu(rdpRdp* rdp, wStream* s, UINT16* type, UINT16* channel_id)
1380
136
{
1381
  /*
1382
   * Read flow control PDU - documented in FlowPDU section in T.128
1383
   * http://www.itu.int/rec/T-REC-T.128-199802-S/en
1384
   * The specification for the PDU has pad8bits listed BEFORE pduTypeFlow.
1385
   * However, so far pad8bits has always been observed to arrive AFTER pduTypeFlow.
1386
   * Switched the order of these two fields to match this observation.
1387
   */
1388
136
  UINT8 pduType = 0;
1389
1390
136
  WINPR_ASSERT(rdp);
1391
136
  WINPR_ASSERT(s);
1392
136
  WINPR_ASSERT(type);
1393
136
  WINPR_ASSERT(channel_id);
1394
1395
136
  if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 6))
1396
20
    return FALSE;
1397
116
  Stream_Read_UINT8(s, pduType); /* pduTypeFlow */
1398
116
  *type = pduType;
1399
116
  Stream_Seek_UINT8(s);               /* pad8bits */
1400
116
  Stream_Seek_UINT8(s);               /* flowIdentifier */
1401
116
  Stream_Seek_UINT8(s);               /* flowNumber */
1402
116
  Stream_Read_UINT16(s, *channel_id); /* pduSource */
1403
116
  return TRUE;
1404
136
}
1405
1406
/**
1407
 * Decrypt an RDP packet.
1408
 *
1409
 * @param rdp RDP module
1410
 * @param s stream
1411
 * @param pLength A pointer to the result variable, must not be NULL
1412
 * @param securityFlags the security flags to apply
1413
 *
1414
 * @return \b TRUE for success, \b FALSE otherwise
1415
 */
1416
1417
BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, UINT16* pLength, UINT16 securityFlags)
1418
2.85k
{
1419
2.85k
  BOOL res = FALSE;
1420
2.85k
  BYTE cmac[8] = { 0 };
1421
2.85k
  BYTE wmac[8] = { 0 };
1422
2.85k
  BOOL status = FALSE;
1423
2.85k
  INT32 length = 0;
1424
1425
2.85k
  WINPR_ASSERT(rdp);
1426
2.85k
  WINPR_ASSERT(rdp->settings);
1427
2.85k
  WINPR_ASSERT(s);
1428
2.85k
  WINPR_ASSERT(pLength);
1429
1430
2.85k
  if (!security_lock(rdp))
1431
0
    return FALSE;
1432
1433
2.85k
  length = *pLength;
1434
2.85k
  if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_NONE)
1435
2.85k
    return TRUE;
1436
1437
0
  if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
1438
0
  {
1439
0
    if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, 12))
1440
0
      goto unlock;
1441
1442
0
    UINT16 len = 0;
1443
0
    Stream_Read_UINT16(s, len); /* 0x10 */
1444
0
    if (len != 0x10)
1445
0
      WLog_Print(rdp->log, WLOG_WARN, "ENCRYPTION_METHOD_FIPS length %" PRIu16 " != 0x10",
1446
0
                 len);
1447
1448
0
    UINT16 version = 0;
1449
0
    Stream_Read_UINT8(s, version); /* 0x1 */
1450
0
    if (version != 1)
1451
0
      WLog_Print(rdp->log, WLOG_WARN, "ENCRYPTION_METHOD_FIPS version %" PRIu16 " != 1",
1452
0
                 version);
1453
1454
0
    BYTE pad = 0;
1455
0
    Stream_Read_UINT8(s, pad);
1456
0
    const BYTE* sig = Stream_ConstPointer(s);
1457
0
    Stream_Seek(s, 8); /* signature */
1458
0
    length -= 12;
1459
0
    const INT32 padLength = length - pad;
1460
1461
0
    if ((length <= 0) || (padLength <= 0) || (padLength > UINT16_MAX))
1462
0
    {
1463
0
      WLog_Print(rdp->log, WLOG_ERROR, "FATAL: invalid pad length %" PRId32, padLength);
1464
0
      goto unlock;
1465
0
    }
1466
1467
0
    if (!security_fips_decrypt(Stream_Pointer(s), length, rdp))
1468
0
      goto unlock;
1469
1470
0
    if (!security_fips_check_signature(Stream_ConstPointer(s), length - pad, sig, 8, rdp))
1471
0
      goto unlock;
1472
1473
0
    Stream_SetLength(s, Stream_Length(s) - pad);
1474
0
    *pLength = (UINT16)padLength;
1475
0
  }
1476
0
  else
1477
0
  {
1478
0
    if (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, sizeof(wmac)))
1479
0
      goto unlock;
1480
1481
0
    Stream_Read(s, wmac, sizeof(wmac));
1482
0
    length -= sizeof(wmac);
1483
1484
0
    if (length <= 0)
1485
0
    {
1486
0
      WLog_Print(rdp->log, WLOG_ERROR, "FATAL: invalid length field");
1487
0
      goto unlock;
1488
0
    }
1489
1490
0
    if (!security_decrypt(Stream_PointerAs(s, BYTE), length, rdp))
1491
0
      goto unlock;
1492
1493
0
    if (securityFlags & SEC_SECURE_CHECKSUM)
1494
0
      status = security_salted_mac_signature(rdp, Stream_ConstPointer(s), length, FALSE, cmac,
1495
0
                                             sizeof(cmac));
1496
0
    else
1497
0
      status =
1498
0
          security_mac_signature(rdp, Stream_ConstPointer(s), length, cmac, sizeof(cmac));
1499
1500
0
    if (!status)
1501
0
      goto unlock;
1502
1503
0
    if (memcmp(wmac, cmac, sizeof(wmac)) != 0)
1504
0
    {
1505
0
      WLog_Print(rdp->log, WLOG_ERROR, "WARNING: invalid packet signature");
1506
      /*
1507
       * Because Standard RDP Security is totally broken,
1508
       * and cannot protect against MITM, don't treat signature
1509
       * verification failure as critical. This at least enables
1510
       * us to work with broken RDP clients and servers that
1511
       * generate invalid signatures.
1512
       */
1513
      // return FALSE;
1514
0
    }
1515
1516
0
    *pLength = length;
1517
0
  }
1518
0
  res = TRUE;
1519
0
unlock:
1520
0
  if (!security_unlock(rdp))
1521
0
    return FALSE;
1522
0
  return res;
1523
0
}
1524
1525
const char* pdu_type_to_str(UINT16 pduType, char* buffer, size_t length)
1526
12.2k
{
1527
12.2k
  const char* str = NULL;
1528
12.2k
  switch (pduType)
1529
12.2k
  {
1530
6.19k
    case PDU_TYPE_DEMAND_ACTIVE:
1531
6.19k
      str = "PDU_TYPE_DEMAND_ACTIVE";
1532
6.19k
      break;
1533
38
    case PDU_TYPE_CONFIRM_ACTIVE:
1534
38
      str = "PDU_TYPE_CONFIRM_ACTIVE";
1535
38
      break;
1536
39
    case PDU_TYPE_DEACTIVATE_ALL:
1537
39
      str = "PDU_TYPE_DEACTIVATE_ALL";
1538
39
      break;
1539
0
    case PDU_TYPE_DATA:
1540
0
      str = "PDU_TYPE_DATA";
1541
0
      break;
1542
0
    case PDU_TYPE_SERVER_REDIRECTION:
1543
0
      str = "PDU_TYPE_SERVER_REDIRECTION";
1544
0
      break;
1545
0
    case PDU_TYPE_FLOW_TEST:
1546
0
      str = "PDU_TYPE_FLOW_TEST";
1547
0
      break;
1548
0
    case PDU_TYPE_FLOW_RESPONSE:
1549
0
      str = "PDU_TYPE_FLOW_RESPONSE";
1550
0
      break;
1551
0
    case PDU_TYPE_FLOW_STOP:
1552
0
      str = "PDU_TYPE_FLOW_STOP";
1553
0
      break;
1554
5.98k
    default:
1555
5.98k
      str = "PDU_TYPE_UNKNOWN";
1556
5.98k
      break;
1557
12.2k
  }
1558
1559
12.2k
  winpr_str_append(str, buffer, length, "");
1560
12.2k
  {
1561
12.2k
    char msg[32] = { 0 };
1562
12.2k
    _snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", pduType);
1563
12.2k
    winpr_str_append(msg, buffer, length, "");
1564
12.2k
  }
1565
12.2k
  return buffer;
1566
12.2k
}
1567
1568
/**
1569
 * Process an RDP packet.
1570
 * @param rdp RDP module
1571
 * @param s stream
1572
 */
1573
1574
static state_run_t rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s)
1575
0
{
1576
0
  state_run_t rc = STATE_RUN_SUCCESS;
1577
0
  UINT16 length = 0;
1578
0
  UINT16 pduType = 0;
1579
0
  UINT16 pduSource = 0;
1580
0
  UINT16 channelId = 0;
1581
0
  UINT16 securityFlags = 0;
1582
0
  freerdp* instance = NULL;
1583
1584
0
  WINPR_ASSERT(rdp);
1585
0
  WINPR_ASSERT(rdp->context);
1586
0
  WINPR_ASSERT(s);
1587
1588
0
  instance = rdp->context->instance;
1589
0
  WINPR_ASSERT(instance);
1590
1591
0
  if (!rdp_read_header(rdp, s, &length, &channelId))
1592
0
    return STATE_RUN_FAILED;
1593
1594
0
  if (freerdp_shall_disconnect_context(rdp->context))
1595
0
    return STATE_RUN_SUCCESS;
1596
1597
0
  if (rdp->autodetect->bandwidthMeasureStarted)
1598
0
  {
1599
0
    rdp->autodetect->bandwidthMeasureByteCount += length;
1600
0
  }
1601
1602
0
  if (rdp->settings->UseRdpSecurityLayer)
1603
0
  {
1604
0
    if (!rdp_read_security_header(rdp, s, &securityFlags, &length))
1605
0
      return STATE_RUN_FAILED;
1606
1607
0
    if (securityFlags & (SEC_ENCRYPT | SEC_REDIRECTION_PKT))
1608
0
    {
1609
0
      if (!rdp_decrypt(rdp, s, &length, securityFlags))
1610
0
        return STATE_RUN_FAILED;
1611
0
    }
1612
1613
0
    if (securityFlags & SEC_REDIRECTION_PKT)
1614
0
    {
1615
      /*
1616
       * [MS-RDPBCGR] 2.2.13.2.1
1617
       *  - no share control header, nor the 2 byte pad
1618
       */
1619
0
      Stream_Rewind(s, 2);
1620
0
      rdp->inPackets++;
1621
1622
0
      rc = rdp_recv_enhanced_security_redirection_packet(rdp, s);
1623
0
      goto out;
1624
0
    }
1625
0
  }
1626
1627
0
  if (channelId == MCS_GLOBAL_CHANNEL_ID)
1628
0
  {
1629
0
    while (Stream_GetRemainingLength(s) > 3)
1630
0
    {
1631
0
      wStream subbuffer;
1632
0
      wStream* sub = NULL;
1633
0
      size_t diff = 0;
1634
0
      UINT16 remain = 0;
1635
1636
0
      if (!rdp_read_share_control_header(rdp, s, NULL, &remain, &pduType, &pduSource))
1637
0
        return STATE_RUN_FAILED;
1638
1639
0
      sub = Stream_StaticInit(&subbuffer, Stream_Pointer(s), remain);
1640
0
      if (!Stream_SafeSeek(s, remain))
1641
0
        return STATE_RUN_FAILED;
1642
1643
0
      rdp->settings->PduSource = pduSource;
1644
0
      rdp->inPackets++;
1645
1646
0
      switch (pduType)
1647
0
      {
1648
0
        case PDU_TYPE_DATA:
1649
0
          rc = rdp_recv_data_pdu(rdp, sub);
1650
0
          if (state_run_failed(rc))
1651
0
            return rc;
1652
0
          break;
1653
1654
0
        case PDU_TYPE_DEACTIVATE_ALL:
1655
0
          if (!rdp_recv_deactivate_all(rdp, sub))
1656
0
          {
1657
0
            WLog_Print(rdp->log, WLOG_ERROR,
1658
0
                       "rdp_recv_tpkt_pdu: rdp_recv_deactivate_all() fail");
1659
0
            return STATE_RUN_FAILED;
1660
0
          }
1661
1662
0
          break;
1663
1664
0
        case PDU_TYPE_SERVER_REDIRECTION:
1665
0
          return rdp_recv_enhanced_security_redirection_packet(rdp, sub);
1666
1667
0
        case PDU_TYPE_FLOW_RESPONSE:
1668
0
        case PDU_TYPE_FLOW_STOP:
1669
0
        case PDU_TYPE_FLOW_TEST:
1670
0
          WLog_Print(rdp->log, WLOG_DEBUG, "flow message 0x%04" PRIX16 "", pduType);
1671
          /* http://msdn.microsoft.com/en-us/library/cc240576.aspx */
1672
0
          if (!Stream_SafeSeek(sub, remain))
1673
0
            return STATE_RUN_FAILED;
1674
0
          break;
1675
1676
0
        default:
1677
0
        {
1678
0
          char buffer[256] = { 0 };
1679
0
          WLog_Print(rdp->log, WLOG_ERROR, "incorrect PDU type: %s",
1680
0
                     pdu_type_to_str(pduType, buffer, sizeof(buffer)));
1681
0
        }
1682
0
        break;
1683
0
      }
1684
1685
0
      diff = Stream_GetRemainingLength(sub);
1686
0
      if (diff > 0)
1687
0
      {
1688
0
        char buffer[256] = { 0 };
1689
0
        WLog_Print(rdp->log, WLOG_WARN,
1690
0
                   "pduType %s not properly parsed, %" PRIdz
1691
0
                   " bytes remaining unhandled. Skipping.",
1692
0
                   pdu_type_to_str(pduType, buffer, sizeof(buffer)), diff);
1693
0
      }
1694
0
    }
1695
0
  }
1696
0
  else if (rdp->mcs->messageChannelId && (channelId == rdp->mcs->messageChannelId))
1697
0
  {
1698
0
    if (!rdp->settings->UseRdpSecurityLayer)
1699
0
      if (!rdp_read_security_header(rdp, s, &securityFlags, NULL))
1700
0
        return STATE_RUN_FAILED;
1701
0
    rdp->inPackets++;
1702
0
    rc = rdp_recv_message_channel_pdu(rdp, s, securityFlags);
1703
0
  }
1704
0
  else
1705
0
  {
1706
0
    rdp->inPackets++;
1707
1708
0
    if (!freerdp_channel_process(instance, s, channelId, length))
1709
0
      return STATE_RUN_FAILED;
1710
0
  }
1711
1712
0
out:
1713
0
  if (!tpkt_ensure_stream_consumed(s, length))
1714
0
    return STATE_RUN_FAILED;
1715
0
  return rc;
1716
0
}
1717
1718
static state_run_t rdp_recv_fastpath_pdu(rdpRdp* rdp, wStream* s)
1719
0
{
1720
0
  UINT16 length = 0;
1721
1722
0
  WINPR_ASSERT(rdp);
1723
0
  rdpFastPath* fastpath = rdp->fastpath;
1724
1725
0
  if (!fastpath_read_header_rdp(fastpath, s, &length))
1726
0
  {
1727
0
    WLog_Print(rdp->log, WLOG_ERROR, "rdp_recv_fastpath_pdu: fastpath_read_header_rdp() fail");
1728
0
    return STATE_RUN_FAILED;
1729
0
  }
1730
1731
0
  if ((length == 0) || (!Stream_CheckAndLogRequiredLengthWLog(rdp->log, s, length)))
1732
0
  {
1733
0
    WLog_Print(rdp->log, WLOG_ERROR, "incorrect FastPath PDU header length %" PRIu16 "",
1734
0
               length);
1735
0
    return STATE_RUN_FAILED;
1736
0
  }
1737
1738
0
  if (rdp->autodetect->bandwidthMeasureStarted)
1739
0
  {
1740
0
    rdp->autodetect->bandwidthMeasureByteCount += length;
1741
0
  }
1742
1743
0
  if (!fastpath_decrypt(fastpath, s, &length))
1744
0
    return STATE_RUN_FAILED;
1745
1746
0
  return fastpath_recv_updates(rdp->fastpath, s);
1747
0
}
1748
1749
static state_run_t rdp_recv_pdu(rdpRdp* rdp, wStream* s)
1750
0
{
1751
0
  const int rc = tpkt_verify_header(s);
1752
0
  if (rc > 0)
1753
0
    return rdp_recv_tpkt_pdu(rdp, s);
1754
0
  else if (rc == 0)
1755
0
    return rdp_recv_fastpath_pdu(rdp, s);
1756
0
  else
1757
0
    return STATE_RUN_FAILED;
1758
0
}
1759
1760
static state_run_t rdp_handle_sc_flags(rdpRdp* rdp, wStream* s, UINT32 flag,
1761
                                       CONNECTION_STATE nextState)
1762
0
{
1763
0
  const UINT32 mask = FINALIZE_SC_SYNCHRONIZE_PDU | FINALIZE_SC_CONTROL_COOPERATE_PDU |
1764
0
                      FINALIZE_SC_CONTROL_GRANTED_PDU | FINALIZE_SC_FONT_MAP_PDU;
1765
0
  WINPR_ASSERT(rdp);
1766
0
  state_run_t status = rdp_recv_pdu(rdp, s);
1767
0
  if (state_run_success(status))
1768
0
  {
1769
0
    const UINT32 flags = rdp->finalize_sc_pdus & mask;
1770
0
    if ((flags & flag) == flag)
1771
0
    {
1772
0
      if (!rdp_client_transition_to_state(rdp, nextState))
1773
0
        status = STATE_RUN_FAILED;
1774
0
      else
1775
0
        status = STATE_RUN_SUCCESS;
1776
0
    }
1777
0
    else
1778
0
    {
1779
0
      char flag_buffer[256] = { 0 };
1780
0
      char mask_buffer[256] = { 0 };
1781
0
      WLog_Print(rdp->log, WLOG_WARN,
1782
0
                 "[%s] unexpected server message, expected flag %s [have %s]",
1783
0
                 rdp_get_state_string(rdp),
1784
0
                 rdp_finalize_flags_to_str(flag, flag_buffer, sizeof(flag_buffer)),
1785
0
                 rdp_finalize_flags_to_str(flags, mask_buffer, sizeof(mask_buffer)));
1786
0
    }
1787
0
  }
1788
0
  return status;
1789
0
}
1790
1791
static state_run_t rdp_client_exchange_monitor_layout(rdpRdp* rdp, wStream* s)
1792
0
{
1793
0
  WINPR_ASSERT(rdp);
1794
1795
0
  if (!rdp_check_monitor_layout_pdu_state(rdp, FALSE))
1796
0
    return FALSE;
1797
1798
  /* We might receive unrelated messages from the server (channel traffic),
1799
   * so only proceed if some flag changed
1800
   */
1801
0
  const UINT32 old = rdp->finalize_sc_pdus;
1802
0
  state_run_t status = rdp_recv_pdu(rdp, s);
1803
0
  const UINT32 now = rdp->finalize_sc_pdus;
1804
0
  const BOOL changed = (old != now) || rdp->monitor_layout_pdu;
1805
1806
  /* This PDU is optional, so if we received a finalize PDU continue there */
1807
0
  if (state_run_success(status) && changed)
1808
0
  {
1809
0
    if (!rdp->monitor_layout_pdu)
1810
0
    {
1811
0
      if (!rdp_finalize_is_flag_set(rdp, FINALIZE_SC_SYNCHRONIZE_PDU))
1812
0
        return STATE_RUN_FAILED;
1813
0
    }
1814
1815
0
    status = rdp_client_connect_finalize(rdp);
1816
0
    if (state_run_success(status) && !rdp->monitor_layout_pdu)
1817
0
      status = STATE_RUN_TRY_AGAIN;
1818
0
  }
1819
0
  return status;
1820
0
}
1821
1822
static state_run_t rdp_recv_callback_int(rdpTransport* transport, wStream* s, void* extra)
1823
7.99k
{
1824
7.99k
  state_run_t status = STATE_RUN_SUCCESS;
1825
7.99k
  rdpRdp* rdp = (rdpRdp*)extra;
1826
1827
7.99k
  WINPR_ASSERT(transport);
1828
7.99k
  WINPR_ASSERT(rdp);
1829
7.99k
  WINPR_ASSERT(s);
1830
1831
7.99k
  switch (rdp_get_state(rdp))
1832
7.99k
  {
1833
0
    case CONNECTION_STATE_NEGO:
1834
0
      if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
1835
0
        status = STATE_RUN_FAILED;
1836
0
      else
1837
0
        status = STATE_RUN_CONTINUE;
1838
0
      break;
1839
0
    case CONNECTION_STATE_NLA:
1840
0
      if (nla_get_state(rdp->nla) < NLA_STATE_AUTH_INFO)
1841
0
      {
1842
0
        if (nla_recv_pdu(rdp->nla, s) < 1)
1843
0
        {
1844
0
          WLog_Print(rdp->log, WLOG_ERROR, "%s - nla_recv_pdu() fail",
1845
0
                     rdp_get_state_string(rdp));
1846
0
          status = STATE_RUN_FAILED;
1847
0
        }
1848
0
      }
1849
0
      else if (nla_get_state(rdp->nla) == NLA_STATE_POST_NEGO)
1850
0
      {
1851
0
        nego_recv(rdp->transport, s, (void*)rdp->nego);
1852
1853
0
        if (!nego_update_settings_from_state(rdp->nego, rdp->settings))
1854
0
          return FALSE;
1855
1856
0
        if (nego_get_state(rdp->nego) != NEGO_STATE_FINAL)
1857
0
        {
1858
0
          WLog_Print(rdp->log, WLOG_ERROR, "%s - nego_recv() fail",
1859
0
                     rdp_get_state_string(rdp));
1860
0
          status = STATE_RUN_FAILED;
1861
0
        }
1862
0
        else if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
1863
0
          status = STATE_RUN_FAILED;
1864
0
      }
1865
1866
0
      if (state_run_success(status))
1867
0
      {
1868
0
        if (nla_get_state(rdp->nla) == NLA_STATE_AUTH_INFO)
1869
0
        {
1870
0
          transport_set_nla_mode(rdp->transport, FALSE);
1871
1872
0
          if (rdp->settings->VmConnectMode)
1873
0
          {
1874
0
            if (!nego_set_state(rdp->nego, NEGO_STATE_NLA))
1875
0
              status = STATE_RUN_FAILED;
1876
0
            else if (!nego_set_requested_protocols(rdp->nego,
1877
0
                                                   PROTOCOL_HYBRID | PROTOCOL_SSL))
1878
0
              status = STATE_RUN_FAILED;
1879
0
            else if (!nego_send_negotiation_request(rdp->nego))
1880
0
              status = STATE_RUN_FAILED;
1881
0
            else if (!nla_set_state(rdp->nla, NLA_STATE_POST_NEGO))
1882
0
              status = STATE_RUN_FAILED;
1883
0
          }
1884
0
          else
1885
0
          {
1886
0
            if (!nla_set_state(rdp->nla, NLA_STATE_FINAL))
1887
0
              status = STATE_RUN_FAILED;
1888
0
          }
1889
0
        }
1890
0
      }
1891
0
      if (state_run_success(status))
1892
0
      {
1893
1894
0
        if (nla_get_state(rdp->nla) == NLA_STATE_FINAL)
1895
0
        {
1896
0
          if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
1897
0
            status = STATE_RUN_FAILED;
1898
0
          else
1899
0
            status = STATE_RUN_CONTINUE;
1900
0
        }
1901
0
      }
1902
0
      break;
1903
1904
0
    case CONNECTION_STATE_AAD:
1905
0
      if (aad_recv(rdp->aad, s) < 1)
1906
0
      {
1907
0
        WLog_Print(rdp->log, WLOG_ERROR, "%s - aad_recv() fail", rdp_get_state_string(rdp));
1908
0
        status = STATE_RUN_FAILED;
1909
0
      }
1910
0
      if (state_run_success(status))
1911
0
      {
1912
0
        if (aad_get_state(rdp->aad) == AAD_STATE_FINAL)
1913
0
        {
1914
0
          transport_set_aad_mode(rdp->transport, FALSE);
1915
0
          if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_REQUEST))
1916
0
            status = STATE_RUN_FAILED;
1917
0
          else
1918
0
            status = STATE_RUN_CONTINUE;
1919
0
        }
1920
0
      }
1921
0
      break;
1922
1923
0
    case CONNECTION_STATE_MCS_CREATE_REQUEST:
1924
0
      if (!mcs_client_begin(rdp->mcs))
1925
0
      {
1926
0
        WLog_Print(rdp->log, WLOG_ERROR, "%s - mcs_client_begin() fail",
1927
0
                   rdp_get_state_string(rdp));
1928
0
        status = STATE_RUN_FAILED;
1929
0
      }
1930
0
      else if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CREATE_RESPONSE))
1931
0
        status = STATE_RUN_FAILED;
1932
0
      else if (Stream_GetRemainingLength(s) > 0)
1933
0
        status = STATE_RUN_CONTINUE;
1934
0
      break;
1935
1936
0
    case CONNECTION_STATE_MCS_CREATE_RESPONSE:
1937
0
      if (!mcs_recv_connect_response(rdp->mcs, s))
1938
0
      {
1939
0
        WLog_Print(rdp->log, WLOG_ERROR, "mcs_recv_connect_response failure");
1940
0
        status = STATE_RUN_FAILED;
1941
0
      }
1942
0
      else
1943
0
      {
1944
0
        if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ERECT_DOMAIN))
1945
0
          status = STATE_RUN_FAILED;
1946
0
        else if (!mcs_send_erect_domain_request(rdp->mcs))
1947
0
        {
1948
0
          WLog_Print(rdp->log, WLOG_ERROR, "mcs_send_erect_domain_request failure");
1949
0
          status = STATE_RUN_FAILED;
1950
0
        }
1951
0
        else if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER))
1952
0
          status = STATE_RUN_FAILED;
1953
0
        else if (!mcs_send_attach_user_request(rdp->mcs))
1954
0
        {
1955
0
          WLog_Print(rdp->log, WLOG_ERROR, "mcs_send_attach_user_request failure");
1956
0
          status = STATE_RUN_FAILED;
1957
0
        }
1958
0
        else if (!rdp_client_transition_to_state(rdp,
1959
0
                                                 CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM))
1960
0
          status = STATE_RUN_FAILED;
1961
0
      }
1962
0
      break;
1963
1964
0
    case CONNECTION_STATE_MCS_ATTACH_USER_CONFIRM:
1965
0
      if (!mcs_recv_attach_user_confirm(rdp->mcs, s))
1966
0
      {
1967
0
        WLog_Print(rdp->log, WLOG_ERROR, "mcs_recv_attach_user_confirm failure");
1968
0
        status = STATE_RUN_FAILED;
1969
0
      }
1970
0
      else if (!freerdp_settings_get_bool(rdp->settings, FreeRDP_SupportSkipChannelJoin))
1971
0
      {
1972
0
        if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST))
1973
0
          status = STATE_RUN_FAILED;
1974
0
        else if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId))
1975
0
        {
1976
0
          WLog_Print(rdp->log, WLOG_ERROR, "mcs_send_channel_join_request failure");
1977
0
          status = STATE_RUN_FAILED;
1978
0
        }
1979
0
        else if (!rdp_client_transition_to_state(
1980
0
                     rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE))
1981
0
          status = STATE_RUN_FAILED;
1982
0
      }
1983
0
      else
1984
0
      {
1985
        /* SKIP_CHANNELJOIN is active, consider channels to be joined */
1986
0
        if (!rdp_client_skip_mcs_channel_join(rdp))
1987
0
          status = STATE_RUN_FAILED;
1988
0
      }
1989
0
      break;
1990
1991
0
    case CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE:
1992
0
      if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s))
1993
0
      {
1994
0
        WLog_Print(rdp->log, WLOG_ERROR,
1995
0
                   "%s - "
1996
0
                   "rdp_client_connect_mcs_channel_join_confirm() fail",
1997
0
                   rdp_get_state_string(rdp));
1998
0
        status = STATE_RUN_FAILED;
1999
0
      }
2000
2001
0
      break;
2002
2003
0
    case CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST:
2004
0
      if (!rdp_client_connect_auto_detect(rdp, s))
2005
0
      {
2006
0
        if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_LICENSING))
2007
0
          status = STATE_RUN_FAILED;
2008
0
        else
2009
0
          status = STATE_RUN_TRY_AGAIN;
2010
0
      }
2011
0
      break;
2012
2013
0
    case CONNECTION_STATE_LICENSING:
2014
0
      status = rdp_client_connect_license(rdp, s);
2015
2016
0
      if (state_run_failed(status))
2017
0
      {
2018
0
        char buffer[64] = { 0 };
2019
0
        WLog_Print(rdp->log, WLOG_DEBUG, "%s - rdp_client_connect_license() - %s",
2020
0
                   rdp_get_state_string(rdp),
2021
0
                   state_run_result_string(status, buffer, ARRAYSIZE(buffer)));
2022
0
      }
2023
2024
0
      break;
2025
2026
0
    case CONNECTION_STATE_MULTITRANSPORT_BOOTSTRAPPING_REQUEST:
2027
0
      if (!rdp_client_connect_auto_detect(rdp, s))
2028
0
      {
2029
0
        rdp_client_transition_to_state(
2030
0
            rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
2031
0
        status = STATE_RUN_TRY_AGAIN;
2032
0
      }
2033
0
      break;
2034
2035
0
    case CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE:
2036
0
      status = rdp_client_connect_demand_active(rdp, s);
2037
2038
0
      if (state_run_failed(status))
2039
0
      {
2040
0
        char buffer[64] = { 0 };
2041
0
        WLog_Print(rdp->log, WLOG_DEBUG,
2042
0
                   "%s - "
2043
0
                   "rdp_client_connect_demand_active() - %s",
2044
0
                   rdp_get_state_string(rdp),
2045
0
                   state_run_result_string(status, buffer, ARRAYSIZE(buffer)));
2046
0
      }
2047
0
      else if (status == STATE_RUN_ACTIVE)
2048
0
      {
2049
0
        if (!rdp_client_transition_to_state(
2050
0
                rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE))
2051
0
          status = STATE_RUN_FAILED;
2052
0
        else
2053
0
          status = STATE_RUN_CONTINUE;
2054
0
      }
2055
0
      break;
2056
2057
0
    case CONNECTION_STATE_CAPABILITIES_EXCHANGE_MONITOR_LAYOUT:
2058
0
      status = rdp_client_exchange_monitor_layout(rdp, s);
2059
0
      break;
2060
2061
0
    case CONNECTION_STATE_CAPABILITIES_EXCHANGE_CONFIRM_ACTIVE:
2062
0
      status = rdp_client_connect_confirm_active(rdp, s);
2063
0
      break;
2064
2065
0
    case CONNECTION_STATE_FINALIZATION_CLIENT_SYNC:
2066
0
      status = rdp_handle_sc_flags(rdp, s, FINALIZE_SC_SYNCHRONIZE_PDU,
2067
0
                                   CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE);
2068
0
      break;
2069
0
    case CONNECTION_STATE_FINALIZATION_CLIENT_COOPERATE:
2070
0
      status = rdp_handle_sc_flags(rdp, s, FINALIZE_SC_CONTROL_COOPERATE_PDU,
2071
0
                                   CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL);
2072
0
      break;
2073
0
    case CONNECTION_STATE_FINALIZATION_CLIENT_GRANTED_CONTROL:
2074
0
      status = rdp_handle_sc_flags(rdp, s, FINALIZE_SC_CONTROL_GRANTED_PDU,
2075
0
                                   CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP);
2076
0
      break;
2077
0
    case CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP:
2078
0
      status = rdp_handle_sc_flags(rdp, s, FINALIZE_SC_FONT_MAP_PDU, CONNECTION_STATE_ACTIVE);
2079
0
      break;
2080
2081
0
    case CONNECTION_STATE_ACTIVE:
2082
0
      status = rdp_recv_pdu(rdp, s);
2083
2084
0
      if (state_run_failed(status))
2085
0
      {
2086
0
        char buffer[64] = { 0 };
2087
0
        WLog_Print(rdp->log, WLOG_DEBUG, "%s - rdp_recv_pdu() - %s",
2088
0
                   rdp_get_state_string(rdp),
2089
0
                   state_run_result_string(status, buffer, ARRAYSIZE(buffer)));
2090
0
      }
2091
0
      break;
2092
2093
7.99k
    default:
2094
7.99k
      WLog_Print(rdp->log, WLOG_ERROR, "%s state %d", rdp_get_state_string(rdp),
2095
7.99k
                 rdp_get_state(rdp));
2096
7.99k
      status = STATE_RUN_FAILED;
2097
7.99k
      break;
2098
7.99k
  }
2099
2100
7.99k
  if (state_run_failed(status))
2101
7.99k
  {
2102
7.99k
    char buffer[64] = { 0 };
2103
7.99k
    WLog_Print(rdp->log, WLOG_ERROR, "%s status %s", rdp_get_state_string(rdp),
2104
7.99k
               state_run_result_string(status, buffer, ARRAYSIZE(buffer)));
2105
7.99k
  }
2106
7.99k
  return status;
2107
7.99k
}
2108
2109
state_run_t rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra)
2110
7.99k
{
2111
7.99k
  char buffer[64] = { 0 };
2112
7.99k
  state_run_t rc = STATE_RUN_FAILED;
2113
7.99k
  const size_t start = Stream_GetPosition(s);
2114
7.99k
  const rdpContext* context = transport_get_context(transport);
2115
2116
7.99k
  WINPR_ASSERT(context);
2117
7.99k
  do
2118
7.99k
  {
2119
7.99k
    const rdpRdp* rdp = context->rdp;
2120
7.99k
    WINPR_ASSERT(rdp);
2121
2122
7.99k
    if (rc == STATE_RUN_TRY_AGAIN)
2123
0
      Stream_SetPosition(s, start);
2124
2125
7.99k
    const char* old = rdp_get_state_string(rdp);
2126
7.99k
    const size_t orem = Stream_GetRemainingLength(s);
2127
7.99k
    rc = rdp_recv_callback_int(transport, s, extra);
2128
2129
7.99k
    const char* now = rdp_get_state_string(rdp);
2130
7.99k
    const size_t rem = Stream_GetRemainingLength(s);
2131
2132
7.99k
    WLog_Print(rdp->log, WLOG_TRACE,
2133
7.99k
               "(client)[%s -> %s] current return %s [feeding %" PRIuz " bytes, %" PRIuz
2134
7.99k
               " bytes not processed]",
2135
7.99k
               old, now, state_run_result_string(rc, buffer, sizeof(buffer)), orem, rem);
2136
7.99k
  } while ((rc == STATE_RUN_TRY_AGAIN) || (rc == STATE_RUN_CONTINUE));
2137
7.99k
  return rc;
2138
7.99k
}
2139
2140
BOOL rdp_send_channel_data(rdpRdp* rdp, UINT16 channelId, const BYTE* data, size_t size)
2141
0
{
2142
0
  return freerdp_channel_send(rdp, channelId, data, size);
2143
0
}
2144
2145
BOOL rdp_channel_send_packet(rdpRdp* rdp, UINT16 channelId, size_t totalSize, UINT32 flags,
2146
                             const BYTE* data, size_t chunkSize)
2147
0
{
2148
0
  return freerdp_channel_send_packet(rdp, channelId, totalSize, flags, data, chunkSize);
2149
0
}
2150
2151
BOOL rdp_send_error_info(rdpRdp* rdp)
2152
0
{
2153
0
  wStream* s = NULL;
2154
0
  BOOL status = 0;
2155
2156
0
  if (rdp->errorInfo == ERRINFO_SUCCESS)
2157
0
    return TRUE;
2158
2159
0
  s = rdp_data_pdu_init(rdp);
2160
2161
0
  if (!s)
2162
0
    return FALSE;
2163
2164
0
  Stream_Write_UINT32(s, rdp->errorInfo); /* error id (4 bytes) */
2165
0
  status = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_ERROR_INFO, 0);
2166
0
  return status;
2167
0
}
2168
2169
int rdp_check_fds(rdpRdp* rdp)
2170
0
{
2171
0
  int status = 0;
2172
0
  rdpTsg* tsg = NULL;
2173
0
  rdpTransport* transport = NULL;
2174
2175
0
  WINPR_ASSERT(rdp);
2176
0
  transport = rdp->transport;
2177
2178
0
  tsg = transport_get_tsg(transport);
2179
0
  if (tsg)
2180
0
  {
2181
0
    if (!tsg_check_event_handles(tsg))
2182
0
    {
2183
0
      WLog_Print(rdp->log, WLOG_ERROR, "rdp_check_fds: tsg_check_event_handles()");
2184
0
      return -1;
2185
0
    }
2186
2187
0
    if (tsg_get_state(tsg) != TSG_STATE_PIPE_CREATED)
2188
0
      return 1;
2189
0
  }
2190
2191
0
  status = transport_check_fds(transport);
2192
2193
0
  if (status == 1)
2194
0
  {
2195
0
    if (!rdp_client_redirect(rdp)) /* session redirection */
2196
0
      return -1;
2197
0
  }
2198
2199
0
  if (status < 0)
2200
0
    WLog_Print(rdp->log, WLOG_DEBUG, "transport_check_fds() - %i", status);
2201
2202
0
  return status;
2203
0
}
2204
2205
BOOL freerdp_get_stats(rdpRdp* rdp, UINT64* inBytes, UINT64* outBytes, UINT64* inPackets,
2206
                       UINT64* outPackets)
2207
0
{
2208
0
  if (!rdp)
2209
0
    return FALSE;
2210
2211
0
  if (inBytes)
2212
0
    *inBytes = rdp->inBytes;
2213
0
  if (outBytes)
2214
0
    *outBytes = rdp->outBytes;
2215
0
  if (inPackets)
2216
0
    *inPackets = rdp->inPackets;
2217
0
  if (outPackets)
2218
0
    *outPackets = rdp->outPackets;
2219
2220
0
  return TRUE;
2221
0
}
2222
2223
/**
2224
 * Instantiate new RDP module.
2225
 * @return new RDP module
2226
 */
2227
2228
rdpRdp* rdp_new(rdpContext* context)
2229
14.9k
{
2230
14.9k
  rdpRdp* rdp = NULL;
2231
14.9k
  DWORD flags = 0;
2232
14.9k
  rdp = (rdpRdp*)calloc(1, sizeof(rdpRdp));
2233
2234
14.9k
  if (!rdp)
2235
0
    return NULL;
2236
2237
14.9k
  rdp->log = WLog_Get(RDP_TAG);
2238
14.9k
  WINPR_ASSERT(rdp->log);
2239
2240
14.9k
  _snprintf(rdp->log_context, sizeof(rdp->log_context), "%p", (void*)context);
2241
14.9k
  WLog_SetContext(rdp->log, NULL, rdp->log_context);
2242
2243
14.9k
  InitializeCriticalSection(&rdp->critical);
2244
14.9k
  rdp->context = context;
2245
14.9k
  WINPR_ASSERT(rdp->context);
2246
2247
14.9k
  if (context->ServerMode)
2248
6.97k
    flags |= FREERDP_SETTINGS_SERVER_MODE;
2249
2250
14.9k
  if (!context->settings)
2251
14.9k
  {
2252
14.9k
    context->settings = rdp->settings = freerdp_settings_new(flags);
2253
2254
14.9k
    if (!rdp->settings)
2255
0
      goto fail;
2256
14.9k
  }
2257
0
  else
2258
0
    rdp->settings = context->settings;
2259
2260
  /* Keep a backup copy of settings for later comparisons */
2261
14.9k
  if (!rdp_set_backup_settings(rdp))
2262
0
    goto fail;
2263
2264
14.9k
  rdp->settings->instance = context->instance;
2265
2266
14.9k
  context->settings = rdp->settings;
2267
14.9k
  if (context->instance)
2268
7.99k
    context->settings->instance = context->instance;
2269
6.97k
  else if (context->peer)
2270
6.97k
  {
2271
6.97k
    rdp->settings->instance = context->peer;
2272
2273
#if defined(WITH_FREERDP_DEPRECATED)
2274
    context->peer->settings = rdp->settings;
2275
#endif
2276
6.97k
  }
2277
2278
14.9k
  rdp->transport = transport_new(context);
2279
2280
14.9k
  if (!rdp->transport)
2281
0
    goto fail;
2282
2283
14.9k
  {
2284
14.9k
    const rdpTransportIo* io = transport_get_io_callbacks(rdp->transport);
2285
14.9k
    if (!io)
2286
0
      goto fail;
2287
14.9k
    rdp->io = calloc(1, sizeof(rdpTransportIo));
2288
14.9k
    if (!rdp->io)
2289
0
      goto fail;
2290
14.9k
    *rdp->io = *io;
2291
14.9k
  }
2292
2293
0
  rdp->aad = aad_new(context, rdp->transport);
2294
14.9k
  if (!rdp->aad)
2295
0
    goto fail;
2296
2297
14.9k
  rdp->license = license_new(rdp);
2298
2299
14.9k
  if (!rdp->license)
2300
0
    goto fail;
2301
2302
14.9k
  rdp->input = input_new(rdp);
2303
2304
14.9k
  if (!rdp->input)
2305
0
    goto fail;
2306
2307
14.9k
  rdp->update = update_new(rdp);
2308
2309
14.9k
  if (!rdp->update)
2310
0
    goto fail;
2311
2312
14.9k
  rdp->fastpath = fastpath_new(rdp);
2313
2314
14.9k
  if (!rdp->fastpath)
2315
0
    goto fail;
2316
2317
14.9k
  rdp->nego = nego_new(rdp->transport);
2318
2319
14.9k
  if (!rdp->nego)
2320
0
    goto fail;
2321
2322
14.9k
  rdp->mcs = mcs_new(rdp->transport);
2323
2324
14.9k
  if (!rdp->mcs)
2325
0
    goto fail;
2326
2327
14.9k
  rdp->redirection = redirection_new();
2328
2329
14.9k
  if (!rdp->redirection)
2330
0
    goto fail;
2331
2332
14.9k
  rdp->autodetect = autodetect_new(rdp->context);
2333
2334
14.9k
  if (!rdp->autodetect)
2335
0
    goto fail;
2336
2337
14.9k
  rdp->heartbeat = heartbeat_new();
2338
2339
14.9k
  if (!rdp->heartbeat)
2340
0
    goto fail;
2341
2342
14.9k
  rdp->multitransport = multitransport_new(rdp, INITIATE_REQUEST_PROTOCOL_UDPFECL |
2343
14.9k
                                                    INITIATE_REQUEST_PROTOCOL_UDPFECR);
2344
2345
14.9k
  if (!rdp->multitransport)
2346
0
    goto fail;
2347
2348
14.9k
  rdp->bulk = bulk_new(context);
2349
2350
14.9k
  if (!rdp->bulk)
2351
0
    goto fail;
2352
2353
14.9k
  rdp->pubSub = PubSub_New(TRUE);
2354
14.9k
  if (!rdp->pubSub)
2355
0
    goto fail;
2356
2357
14.9k
  rdp->abortEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
2358
14.9k
  if (!rdp->abortEvent)
2359
0
    goto fail;
2360
14.9k
  return rdp;
2361
2362
0
fail:
2363
0
  WINPR_PRAGMA_DIAG_PUSH
2364
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2365
0
  rdp_free(rdp);
2366
0
  WINPR_PRAGMA_DIAG_POP
2367
0
  return NULL;
2368
14.9k
}
2369
2370
static void rdp_reset_free(rdpRdp* rdp)
2371
14.9k
{
2372
14.9k
  WINPR_ASSERT(rdp);
2373
2374
14.9k
  rdp_free_rc4_decrypt_keys(rdp);
2375
14.9k
  rdp_free_rc4_encrypt_keys(rdp);
2376
2377
14.9k
  winpr_Cipher_Free(rdp->fips_encrypt);
2378
14.9k
  winpr_Cipher_Free(rdp->fips_decrypt);
2379
14.9k
  rdp->fips_encrypt = NULL;
2380
14.9k
  rdp->fips_decrypt = NULL;
2381
2382
14.9k
  mcs_free(rdp->mcs);
2383
14.9k
  nego_free(rdp->nego);
2384
14.9k
  license_free(rdp->license);
2385
14.9k
  transport_free(rdp->transport);
2386
14.9k
  fastpath_free(rdp->fastpath);
2387
2388
14.9k
  rdp->mcs = NULL;
2389
14.9k
  rdp->nego = NULL;
2390
14.9k
  rdp->license = NULL;
2391
14.9k
  rdp->transport = NULL;
2392
14.9k
  rdp->fastpath = NULL;
2393
14.9k
}
2394
2395
BOOL rdp_reset(rdpRdp* rdp)
2396
0
{
2397
0
  BOOL rc = TRUE;
2398
0
  rdpContext* context = NULL;
2399
0
  rdpSettings* settings = NULL;
2400
2401
0
  WINPR_ASSERT(rdp);
2402
2403
0
  context = rdp->context;
2404
0
  WINPR_ASSERT(context);
2405
2406
0
  settings = rdp->settings;
2407
0
  WINPR_ASSERT(settings);
2408
2409
0
  bulk_reset(rdp->bulk);
2410
2411
0
  rdp_reset_free(rdp);
2412
2413
0
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerRandom, NULL, 0))
2414
0
    rc = FALSE;
2415
2416
0
  if (!freerdp_settings_set_pointer_len(settings, FreeRDP_ServerCertificate, NULL, 0))
2417
0
    rc = FALSE;
2418
2419
0
  if (!freerdp_settings_set_string(settings, FreeRDP_ClientAddress, NULL))
2420
0
    rc = FALSE;
2421
2422
0
  if (!rc)
2423
0
    goto fail;
2424
2425
0
  rc = FALSE;
2426
0
  rdp->transport = transport_new(context);
2427
0
  if (!rdp->transport)
2428
0
    goto fail;
2429
2430
0
  if (rdp->io)
2431
0
  {
2432
0
    if (!transport_set_io_callbacks(rdp->transport, rdp->io))
2433
0
      goto fail;
2434
0
  }
2435
2436
0
  aad_free(rdp->aad);
2437
0
  rdp->aad = aad_new(context, rdp->transport);
2438
0
  if (!rdp->aad)
2439
0
    goto fail;
2440
2441
0
  rdp->nego = nego_new(rdp->transport);
2442
0
  if (!rdp->nego)
2443
0
    goto fail;
2444
2445
0
  rdp->mcs = mcs_new(rdp->transport);
2446
0
  if (!rdp->mcs)
2447
0
    goto fail;
2448
2449
0
  if (!transport_set_layer(rdp->transport, TRANSPORT_LAYER_TCP))
2450
0
    goto fail;
2451
2452
0
  rdp->license = license_new(rdp);
2453
0
  if (!rdp->license)
2454
0
    goto fail;
2455
2456
0
  rdp->fastpath = fastpath_new(rdp);
2457
0
  if (!rdp->fastpath)
2458
0
    goto fail;
2459
2460
0
  rdp->errorInfo = 0;
2461
0
  rc = rdp_finalize_reset_flags(rdp, TRUE);
2462
2463
0
fail:
2464
0
  return rc;
2465
0
}
2466
2467
/**
2468
 * Free RDP module.
2469
 * @param rdp RDP module to be freed
2470
 */
2471
2472
void rdp_free(rdpRdp* rdp)
2473
14.9k
{
2474
14.9k
  if (rdp)
2475
14.9k
  {
2476
14.9k
    DeleteCriticalSection(&rdp->critical);
2477
14.9k
    rdp_reset_free(rdp);
2478
2479
14.9k
    freerdp_settings_free(rdp->settings);
2480
14.9k
    freerdp_settings_free(rdp->originalSettings);
2481
14.9k
    freerdp_settings_free(rdp->remoteSettings);
2482
2483
14.9k
    input_free(rdp->input);
2484
14.9k
    update_free(rdp->update);
2485
14.9k
    nla_free(rdp->nla);
2486
14.9k
    redirection_free(rdp->redirection);
2487
14.9k
    autodetect_free(rdp->autodetect);
2488
14.9k
    heartbeat_free(rdp->heartbeat);
2489
14.9k
    multitransport_free(rdp->multitransport);
2490
14.9k
    bulk_free(rdp->bulk);
2491
14.9k
    free(rdp->io);
2492
14.9k
    PubSub_Free(rdp->pubSub);
2493
14.9k
    if (rdp->abortEvent)
2494
14.9k
      CloseHandle(rdp->abortEvent);
2495
14.9k
    aad_free(rdp->aad);
2496
14.9k
    free(rdp);
2497
14.9k
  }
2498
14.9k
}
2499
2500
BOOL rdp_io_callback_set_event(rdpRdp* rdp, BOOL set)
2501
0
{
2502
0
  if (!rdp)
2503
0
    return FALSE;
2504
0
  return transport_io_callback_set_event(rdp->transport, set);
2505
0
}
2506
2507
const rdpTransportIo* rdp_get_io_callbacks(rdpRdp* rdp)
2508
0
{
2509
0
  if (!rdp)
2510
0
    return NULL;
2511
0
  return rdp->io;
2512
0
}
2513
2514
BOOL rdp_set_io_callbacks(rdpRdp* rdp, const rdpTransportIo* io_callbacks)
2515
0
{
2516
0
  if (!rdp)
2517
0
    return FALSE;
2518
0
  free(rdp->io);
2519
0
  rdp->io = NULL;
2520
0
  if (io_callbacks)
2521
0
  {
2522
0
    rdp->io = malloc(sizeof(rdpTransportIo));
2523
0
    if (!rdp->io)
2524
0
      return FALSE;
2525
0
    *rdp->io = *io_callbacks;
2526
0
    return transport_set_io_callbacks(rdp->transport, rdp->io);
2527
0
  }
2528
0
  return TRUE;
2529
0
}
2530
2531
BOOL rdp_set_io_callback_context(rdpRdp* rdp, void* usercontext)
2532
0
{
2533
0
  WINPR_ASSERT(rdp);
2534
0
  rdp->ioContext = usercontext;
2535
0
  return TRUE;
2536
0
}
2537
2538
void* rdp_get_io_callback_context(rdpRdp* rdp)
2539
0
{
2540
0
  WINPR_ASSERT(rdp);
2541
0
  return rdp->ioContext;
2542
0
}
2543
2544
const char* rdp_finalize_flags_to_str(UINT32 flags, char* buffer, size_t size)
2545
0
{
2546
0
  char number[32] = { 0 };
2547
0
  const UINT32 mask = ~(FINALIZE_SC_SYNCHRONIZE_PDU | FINALIZE_SC_CONTROL_COOPERATE_PDU |
2548
0
                        FINALIZE_SC_CONTROL_GRANTED_PDU | FINALIZE_SC_FONT_MAP_PDU |
2549
0
                        FINALIZE_CS_SYNCHRONIZE_PDU | FINALIZE_CS_CONTROL_COOPERATE_PDU |
2550
0
                        FINALIZE_CS_CONTROL_REQUEST_PDU | FINALIZE_CS_PERSISTENT_KEY_LIST_PDU |
2551
0
                        FINALIZE_CS_FONT_LIST_PDU | FINALIZE_DEACTIVATE_REACTIVATE);
2552
2553
0
  if (flags & FINALIZE_SC_SYNCHRONIZE_PDU)
2554
0
    winpr_str_append("FINALIZE_SC_SYNCHRONIZE_PDU", buffer, size, "|");
2555
0
  if (flags & FINALIZE_SC_CONTROL_COOPERATE_PDU)
2556
0
    winpr_str_append("FINALIZE_SC_CONTROL_COOPERATE_PDU", buffer, size, "|");
2557
0
  if (flags & FINALIZE_SC_CONTROL_GRANTED_PDU)
2558
0
    winpr_str_append("FINALIZE_SC_CONTROL_GRANTED_PDU", buffer, size, "|");
2559
0
  if (flags & FINALIZE_SC_FONT_MAP_PDU)
2560
0
    winpr_str_append("FINALIZE_SC_FONT_MAP_PDU", buffer, size, "|");
2561
0
  if (flags & FINALIZE_CS_SYNCHRONIZE_PDU)
2562
0
    winpr_str_append("FINALIZE_CS_SYNCHRONIZE_PDU", buffer, size, "|");
2563
0
  if (flags & FINALIZE_CS_CONTROL_COOPERATE_PDU)
2564
0
    winpr_str_append("FINALIZE_CS_CONTROL_COOPERATE_PDU", buffer, size, "|");
2565
0
  if (flags & FINALIZE_CS_CONTROL_REQUEST_PDU)
2566
0
    winpr_str_append("FINALIZE_CS_CONTROL_REQUEST_PDU", buffer, size, "|");
2567
0
  if (flags & FINALIZE_CS_PERSISTENT_KEY_LIST_PDU)
2568
0
    winpr_str_append("FINALIZE_CS_PERSISTENT_KEY_LIST_PDU", buffer, size, "|");
2569
0
  if (flags & FINALIZE_CS_FONT_LIST_PDU)
2570
0
    winpr_str_append("FINALIZE_CS_FONT_LIST_PDU", buffer, size, "|");
2571
0
  if (flags & FINALIZE_DEACTIVATE_REACTIVATE)
2572
0
    winpr_str_append("FINALIZE_DEACTIVATE_REACTIVATE", buffer, size, "|");
2573
0
  if (flags & mask)
2574
0
    winpr_str_append("UNKNOWN_FLAG", buffer, size, "|");
2575
0
  if (flags == 0)
2576
0
    winpr_str_append("NO_FLAG_SET", buffer, size, "|");
2577
0
  _snprintf(number, sizeof(number), " [0x%08" PRIx32 "]", flags);
2578
0
  winpr_str_append(number, buffer, size, "");
2579
0
  return buffer;
2580
0
}
2581
2582
BOOL rdp_finalize_reset_flags(rdpRdp* rdp, BOOL clearAll)
2583
0
{
2584
0
  WINPR_ASSERT(rdp);
2585
0
  WLog_Print(rdp->log, WLOG_DEBUG, "[%s] reset finalize_sc_pdus", rdp_get_state_string(rdp));
2586
0
  if (clearAll)
2587
0
    rdp->finalize_sc_pdus = 0;
2588
0
  else
2589
0
    rdp->finalize_sc_pdus &= FINALIZE_DEACTIVATE_REACTIVATE;
2590
2591
0
  return rdp_set_monitor_layout_pdu_state(rdp, FALSE);
2592
0
}
2593
2594
BOOL rdp_finalize_set_flag(rdpRdp* rdp, UINT32 flag)
2595
8.30k
{
2596
8.30k
  char buffer[1024] = { 0 };
2597
2598
8.30k
  WINPR_ASSERT(rdp);
2599
2600
8.30k
  WLog_Print(rdp->log, WLOG_DEBUG, "[%s] received flag %s", rdp_get_state_string(rdp),
2601
8.30k
             rdp_finalize_flags_to_str(flag, buffer, sizeof(buffer)));
2602
8.30k
  rdp->finalize_sc_pdus |= flag;
2603
8.30k
  return TRUE;
2604
8.30k
}
2605
2606
BOOL rdp_finalize_is_flag_set(rdpRdp* rdp, UINT32 flag)
2607
0
{
2608
0
  WINPR_ASSERT(rdp);
2609
0
  return (rdp->finalize_sc_pdus & flag) == flag;
2610
0
}
2611
2612
BOOL rdp_reset_rc4_encrypt_keys(rdpRdp* rdp)
2613
0
{
2614
0
  WINPR_ASSERT(rdp);
2615
0
  rdp_free_rc4_encrypt_keys(rdp);
2616
0
  rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len);
2617
2618
0
  rdp->encrypt_use_count = 0;
2619
0
  return rdp->rc4_encrypt_key != NULL;
2620
0
}
2621
2622
void rdp_free_rc4_encrypt_keys(rdpRdp* rdp)
2623
14.9k
{
2624
14.9k
  WINPR_ASSERT(rdp);
2625
14.9k
  winpr_RC4_Free(rdp->rc4_encrypt_key);
2626
14.9k
  rdp->rc4_encrypt_key = NULL;
2627
14.9k
}
2628
2629
void rdp_free_rc4_decrypt_keys(rdpRdp* rdp)
2630
14.9k
{
2631
14.9k
  WINPR_ASSERT(rdp);
2632
14.9k
  winpr_RC4_Free(rdp->rc4_decrypt_key);
2633
14.9k
  rdp->rc4_decrypt_key = NULL;
2634
14.9k
}
2635
2636
BOOL rdp_reset_rc4_decrypt_keys(rdpRdp* rdp)
2637
0
{
2638
0
  WINPR_ASSERT(rdp);
2639
0
  rdp_free_rc4_decrypt_keys(rdp);
2640
0
  rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len);
2641
2642
0
  rdp->decrypt_use_count = 0;
2643
0
  return rdp->rc4_decrypt_key != NULL;
2644
0
}
2645
2646
const char* rdp_security_flag_string(UINT32 securityFlags, char* buffer, size_t size)
2647
12.8k
{
2648
12.8k
  if (securityFlags & SEC_EXCHANGE_PKT)
2649
2.09k
    winpr_str_append("SEC_EXCHANGE_PKT", buffer, size, "|");
2650
12.8k
  if (securityFlags & SEC_TRANSPORT_REQ)
2651
2.25k
    winpr_str_append("SEC_TRANSPORT_REQ", buffer, size, "|");
2652
12.8k
  if (securityFlags & SEC_TRANSPORT_RSP)
2653
2.10k
    winpr_str_append("SEC_TRANSPORT_RSP", buffer, size, "|");
2654
12.8k
  if (securityFlags & SEC_ENCRYPT)
2655
1.88k
    winpr_str_append("SEC_ENCRYPT", buffer, size, "|");
2656
12.8k
  if (securityFlags & SEC_RESET_SEQNO)
2657
2.11k
    winpr_str_append("SEC_RESET_SEQNO", buffer, size, "|");
2658
12.8k
  if (securityFlags & SEC_IGNORE_SEQNO)
2659
2.12k
    winpr_str_append("SEC_IGNORE_SEQNO", buffer, size, "|");
2660
12.8k
  if (securityFlags & SEC_INFO_PKT)
2661
1.85k
    winpr_str_append("SEC_INFO_PKT", buffer, size, "|");
2662
12.8k
  if (securityFlags & SEC_LICENSE_PKT)
2663
1.54k
    winpr_str_append("SEC_LICENSE_PKT", buffer, size, "|");
2664
12.8k
  if (securityFlags & SEC_LICENSE_ENCRYPT_CS)
2665
1.87k
    winpr_str_append("SEC_LICENSE_ENCRYPT_CS", buffer, size, "|");
2666
12.8k
  if (securityFlags & SEC_LICENSE_ENCRYPT_SC)
2667
1.87k
    winpr_str_append("SEC_LICENSE_ENCRYPT_SC", buffer, size, "|");
2668
12.8k
  if (securityFlags & SEC_REDIRECTION_PKT)
2669
8.22k
    winpr_str_append("SEC_REDIRECTION_PKT", buffer, size, "|");
2670
12.8k
  if (securityFlags & SEC_SECURE_CHECKSUM)
2671
1.96k
    winpr_str_append("SEC_SECURE_CHECKSUM", buffer, size, "|");
2672
12.8k
  if (securityFlags & SEC_AUTODETECT_REQ)
2673
1.80k
    winpr_str_append("SEC_AUTODETECT_REQ", buffer, size, "|");
2674
12.8k
  if (securityFlags & SEC_AUTODETECT_RSP)
2675
1.96k
    winpr_str_append("SEC_AUTODETECT_RSP", buffer, size, "|");
2676
12.8k
  if (securityFlags & SEC_HEARTBEAT)
2677
1.67k
    winpr_str_append("SEC_HEARTBEAT", buffer, size, "|");
2678
12.8k
  if (securityFlags & SEC_FLAGSHI_VALID)
2679
1.36k
    winpr_str_append("SEC_FLAGSHI_VALID", buffer, size, "|");
2680
12.8k
  {
2681
12.8k
    char msg[32] = { 0 };
2682
2683
12.8k
    _snprintf(msg, sizeof(msg), "[0x%08" PRIx32 "]", securityFlags);
2684
12.8k
    winpr_str_append(msg, buffer, size, "");
2685
12.8k
  }
2686
12.8k
  return buffer;
2687
12.8k
}
2688
2689
static BOOL rdp_reset_remote_settings(rdpRdp* rdp)
2690
14.9k
{
2691
14.9k
  UINT32 flags = FREERDP_SETTINGS_REMOTE_MODE;
2692
14.9k
  WINPR_ASSERT(rdp);
2693
14.9k
  freerdp_settings_free(rdp->remoteSettings);
2694
2695
14.9k
  if (!freerdp_settings_get_bool(rdp->settings, FreeRDP_ServerMode))
2696
7.99k
    flags |= FREERDP_SETTINGS_SERVER_MODE;
2697
14.9k
  rdp->remoteSettings = freerdp_settings_new(flags);
2698
14.9k
  return rdp->remoteSettings != NULL;
2699
14.9k
}
2700
2701
BOOL rdp_set_backup_settings(rdpRdp* rdp)
2702
14.9k
{
2703
14.9k
  WINPR_ASSERT(rdp);
2704
14.9k
  freerdp_settings_free(rdp->originalSettings);
2705
14.9k
  rdp->originalSettings = freerdp_settings_clone(rdp->settings);
2706
14.9k
  if (!rdp->originalSettings)
2707
0
    return FALSE;
2708
14.9k
  return rdp_reset_remote_settings(rdp);
2709
14.9k
}
2710
2711
BOOL rdp_reset_runtime_settings(rdpRdp* rdp)
2712
0
{
2713
0
  WINPR_ASSERT(rdp);
2714
0
  WINPR_ASSERT(rdp->context);
2715
2716
0
  freerdp_settings_free(rdp->settings);
2717
0
  rdp->context->settings = rdp->settings = freerdp_settings_clone(rdp->originalSettings);
2718
2719
0
  if (!rdp->settings)
2720
0
    return FALSE;
2721
0
  return rdp_reset_remote_settings(rdp);
2722
0
}
2723
2724
static BOOL starts_with(const char* tok, const char* val)
2725
12.0k
{
2726
12.0k
  const size_t len = strlen(val);
2727
12.0k
  if (strncmp(tok, val, len) != 0)
2728
12.0k
    return FALSE;
2729
86
  if (tok[len] != '=')
2730
12
    return FALSE;
2731
74
  return TRUE;
2732
86
}
2733
2734
static BOOL option_equals(const char* what, const char* val)
2735
222
{
2736
222
  return _stricmp(what, val) == 0;
2737
222
}
2738
2739
static BOOL parse_on_off_option(const char* value)
2740
74
{
2741
74
  WINPR_ASSERT(value);
2742
74
  const char* sep = strchr(value, '=');
2743
74
  if (!sep)
2744
0
    return TRUE;
2745
74
  if (option_equals("on", &sep[1]))
2746
0
    return TRUE;
2747
74
  if (option_equals("true", &sep[1]))
2748
0
    return TRUE;
2749
74
  if (option_equals("off", &sep[1]))
2750
74
    return FALSE;
2751
0
  if (option_equals("false", &sep[1]))
2752
0
    return FALSE;
2753
2754
0
  errno = 0;
2755
0
  long val = strtol(value, NULL, 0);
2756
0
  if (errno == 0)
2757
0
    return val == 0 ? FALSE : TRUE;
2758
2759
0
  return FALSE;
2760
0
}
2761
2762
13.2k
#define STR(x) #x
2763
2764
static BOOL option_is_experimental(wLog* log, const char* tok)
2765
324
{
2766
324
  const char* experimental[] = { STR(WITH_DSP_EXPERIMENTAL), STR(WITH_VAAPI) };
2767
966
  for (size_t x = 0; x < ARRAYSIZE(experimental); x++)
2768
646
  {
2769
646
    const char* opt = experimental[x];
2770
646
    if (starts_with(tok, opt))
2771
4
    {
2772
4
      return parse_on_off_option(tok);
2773
4
    }
2774
646
  }
2775
320
  return FALSE;
2776
324
}
2777
2778
static BOOL option_is_debug(wLog* log, const char* tok)
2779
324
{
2780
324
  WINPR_ASSERT(log);
2781
324
  const char* debug[] = { STR(WITH_DEBUG_ALL),
2782
324
                        STR(WITH_DEBUG_CERTIFICATE),
2783
324
                        STR(WITH_DEBUG_CAPABILITIES),
2784
324
                        STR(WITH_DEBUG_CHANNELS),
2785
324
                        STR(WITH_DEBUG_CLIPRDR),
2786
324
                        STR(WITH_DEBUG_CODECS),
2787
324
                        STR(WITH_DEBUG_RDPGFX),
2788
324
                        STR(WITH_DEBUG_DVC),
2789
324
                        STR(WITH_DEBUG_TSMF),
2790
324
                        STR(WITH_DEBUG_KBD),
2791
324
                        STR(WITH_DEBUG_LICENSE),
2792
324
                        STR(WITH_DEBUG_NEGO),
2793
324
                        STR(WITH_DEBUG_NLA),
2794
324
                        STR(WITH_DEBUG_TSG),
2795
324
                        STR(WITH_DEBUG_RAIL),
2796
324
                        STR(WITH_DEBUG_RDP),
2797
324
                        STR(WITH_DEBUG_RDPEI),
2798
324
                        STR(WITH_DEBUG_REDIR),
2799
324
                        STR(WITH_DEBUG_RDPDR),
2800
324
                        STR(WITH_DEBUG_RFX),
2801
324
                        STR(WITH_DEBUG_SCARD),
2802
324
                        STR(WITH_DEBUG_SND),
2803
324
                        STR(WITH_DEBUG_SVC),
2804
324
                        STR(WITH_DEBUG_TRANSPORT),
2805
324
                        STR(WITH_DEBUG_TIMEZONE),
2806
324
                        STR(WITH_DEBUG_WND),
2807
324
                        STR(WITH_DEBUG_X11_CLIPRDR),
2808
324
                        STR(WITH_DEBUG_X11_LOCAL_MOVESIZE),
2809
324
                        STR(WITH_DEBUG_X11),
2810
324
                        STR(WITH_DEBUG_XV),
2811
324
                        STR(WITH_DEBUG_RINGBUFFER),
2812
324
                        STR(WITH_DEBUG_SYMBOLS),
2813
324
                        STR(WITH_DEBUG_EVENTS),
2814
324
                        STR(WITH_DEBUG_MUTEX),
2815
324
                        STR(WITH_DEBUG_NTLM),
2816
324
                        STR(WITH_DEBUG_SDL_EVENTS),
2817
324
                        STR(WITH_DEBUG_SDL_KBD_EVENTS),
2818
324
                        STR(WITH_DEBUG_THREADS),
2819
324
                        STR(WITH_DEBUG_URBDRC) };
2820
2821
11.4k
  for (size_t x = 0; x < ARRAYSIZE(debug); x++)
2822
11.1k
  {
2823
11.1k
    const char* opt = debug[x];
2824
11.1k
    if (starts_with(tok, opt))
2825
70
      return parse_on_off_option(tok);
2826
11.1k
  }
2827
2828
254
  if (starts_with(tok, "WITH_DEBUG"))
2829
0
  {
2830
0
    WLog_Print(log, WLOG_WARN, "[BUG] Unmapped Debug-Build option '%s'.", tok);
2831
0
    return parse_on_off_option(tok);
2832
0
  }
2833
2834
254
  return FALSE;
2835
254
}
2836
2837
static void log_build_warn(rdpRdp* rdp, const char* what, const char* msg,
2838
                           BOOL (*cmp)(wLog* log, const char* tok))
2839
4
{
2840
4
  WINPR_ASSERT(rdp);
2841
4
  size_t len = sizeof(FREERDP_BUILD_CONFIG);
2842
4
  char* list = calloc(len, sizeof(char));
2843
4
  char* config = _strdup(FREERDP_BUILD_CONFIG);
2844
4
  if (config && list)
2845
4
  {
2846
4
    char* tok = strtok(config, " ");
2847
652
    while (tok)
2848
648
    {
2849
648
      if (cmp(rdp->log, tok))
2850
0
        winpr_str_append(tok, list, len, " ");
2851
2852
648
      tok = strtok(NULL, " ");
2853
648
    }
2854
4
  }
2855
4
  free(config);
2856
2857
4
  if (list)
2858
4
  {
2859
4
    if (strlen(list) > 0)
2860
0
    {
2861
0
      WLog_Print(rdp->log, WLOG_WARN, "*************************************************");
2862
0
      WLog_Print(rdp->log, WLOG_WARN, "This build is using [%s] build options:", what);
2863
0
      char* tok = strtok(list, " ");
2864
0
      while (tok)
2865
0
      {
2866
0
        WLog_Print(rdp->log, WLOG_WARN, "* '%s'", tok);
2867
0
        tok = strtok(NULL, " ");
2868
0
      }
2869
0
      WLog_Print(rdp->log, WLOG_WARN, "");
2870
0
      WLog_Print(rdp->log, WLOG_WARN, "[%s] build options %s", what, msg);
2871
0
      WLog_Print(rdp->log, WLOG_WARN, "*************************************************");
2872
0
    }
2873
4
  }
2874
4
  free(list);
2875
4
}
2876
2877
void rdp_log_build_warnings(rdpRdp* rdp)
2878
14.9k
{
2879
14.9k
  static unsigned count = 0;
2880
2881
14.9k
  WINPR_ASSERT(rdp);
2882
  /* Since this function is called in context creation routines stop logging
2883
   * this issue repetedly. This is required for proxy, which would otherwise
2884
   * spam the log with these. */
2885
14.9k
  if (count > 0)
2886
14.9k
    return;
2887
2
  count++;
2888
2
  log_build_warn(rdp, "experimental", "might crash the application", option_is_experimental);
2889
2
  log_build_warn(rdp, "debug", "might leak sensitive information (credentials, ...)",
2890
2
                 option_is_debug);
2891
2
}