Coverage Report

Created: 2023-11-19 06:16

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