Coverage Report

Created: 2026-03-04 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/libfreerdp/core/nego.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * RDP Protocol Security Negotiation
4
 *
5
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
7
 * Copyright 2015 Thincast Technologies GmbH
8
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9
 *
10
 * Licensed under the Apache License, Version 2.0 (the "License");
11
 * you may not use this file except in compliance with the License.
12
 * You may obtain a copy of the License at
13
 *
14
 *     http://www.apache.org/licenses/LICENSE-2.0
15
 *
16
 * Unless required by applicable law or agreed to in writing, software
17
 * distributed under the License is distributed on an "AS IS" BASIS,
18
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
 * See the License for the specific language governing permissions and
20
 * limitations under the License.
21
 */
22
23
#include <freerdp/config.h>
24
25
#include <winpr/crt.h>
26
#include <winpr/assert.h>
27
#include <winpr/stream.h>
28
29
#include <freerdp/log.h>
30
31
#include "tpkt.h"
32
33
#include "nego.h"
34
#include "aad.h"
35
36
#include "transport.h"
37
38
15.4k
#define NEGO_TAG FREERDP_TAG("core.nego")
39
40
struct rdp_nego
41
{
42
  UINT16 port;
43
  UINT32 flags;
44
  const char* hostname;
45
  char* cookie;
46
  BYTE* RoutingToken;
47
  DWORD RoutingTokenLength;
48
  BOOL SendPreconnectionPdu;
49
  UINT32 PreconnectionId;
50
  const char* PreconnectionBlob;
51
52
  NEGO_STATE state;
53
  BOOL TcpConnected;
54
  BOOL SecurityConnected;
55
  UINT32 CookieMaxLength;
56
57
  BOOL sendNegoData;
58
  UINT32 SelectedProtocol;
59
  UINT32 RequestedProtocols;
60
  BOOL NegotiateSecurityLayer;
61
  BOOL EnabledProtocols[32];
62
  BOOL RestrictedAdminModeRequired;  /* Client-side */
63
  BOOL RestrictedAdminModeSupported; /* Server-side */
64
  BOOL RemoteCredsGuardRequired;
65
  BOOL RemoteCredsGuardActive;
66
  BOOL RemoteCredsGuardSupported;
67
  BOOL GatewayEnabled;
68
  BOOL GatewayBypassLocal;
69
  BOOL ConnectChildSession;
70
71
  rdpTransport* transport;
72
  wLog* log;
73
};
74
75
static const char* nego_state_string(NEGO_STATE state)
76
0
{
77
0
  static const char* const NEGO_STATE_STRINGS[] = { "NEGO_STATE_INITIAL", "NEGO_STATE_RDSTLS",
78
0
                                                  "NEGO_STATE_AAD",     "NEGO_STATE_EXT",
79
0
                                                  "NEGO_STATE_NLA",     "NEGO_STATE_TLS",
80
0
                                                  "NEGO_STATE_RDP",     "NEGO_STATE_FAIL",
81
0
                                                  "NEGO_STATE_FINAL",   "NEGO_STATE_INVALID" };
82
0
  if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
83
0
    return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
84
0
  return NEGO_STATE_STRINGS[state];
85
0
}
86
87
static BOOL nego_tcp_connect(rdpNego* nego);
88
static BOOL nego_transport_connect(rdpNego* nego);
89
static BOOL nego_transport_disconnect(rdpNego* nego);
90
static BOOL nego_security_connect(rdpNego* nego);
91
static BOOL nego_send_preconnection_pdu(rdpNego* nego);
92
static BOOL nego_recv_response(rdpNego* nego);
93
static void nego_send(rdpNego* nego);
94
static BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s);
95
static BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s);
96
static BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s);
97
98
BOOL nego_update_settings_from_state(rdpNego* nego, rdpSettings* settings)
99
0
{
100
0
  WINPR_ASSERT(nego);
101
102
  /* update settings with negotiated protocol security */
103
0
  return freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
104
0
                                     nego->RequestedProtocols) &&
105
0
         freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
106
0
                                     nego->SelectedProtocol) &&
107
0
         freerdp_settings_set_uint32(settings, FreeRDP_NegotiationFlags, nego->flags);
108
0
}
109
110
/**
111
 * Negotiate protocol security and connect.
112
 *
113
 * @param nego A pointer to the NEGO struct
114
 *
115
 * @return \b TRUE for success, \b FALSE otherwise
116
 */
117
118
BOOL nego_connect(rdpNego* nego)
119
0
{
120
0
  rdpContext* context = nullptr;
121
0
  rdpSettings* settings = nullptr;
122
0
  WINPR_ASSERT(nego);
123
0
  context = transport_get_context(nego->transport);
124
0
  WINPR_ASSERT(context);
125
0
  settings = context->settings;
126
0
  WINPR_ASSERT(settings);
127
128
0
  if (nego_get_state(nego) == NEGO_STATE_INITIAL)
129
0
  {
130
0
    if (nego->EnabledProtocols[PROTOCOL_RDSAAD])
131
0
    {
132
0
      nego_set_state(nego, NEGO_STATE_AAD);
133
0
    }
134
0
    else if (nego->EnabledProtocols[PROTOCOL_RDSTLS])
135
0
    {
136
0
      nego_set_state(nego, NEGO_STATE_RDSTLS);
137
0
    }
138
0
    else if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
139
0
    {
140
0
      nego_set_state(nego, NEGO_STATE_EXT);
141
0
    }
142
0
    else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
143
0
    {
144
0
      nego_set_state(nego, NEGO_STATE_NLA);
145
0
    }
146
0
    else if (nego->EnabledProtocols[PROTOCOL_SSL])
147
0
    {
148
0
      nego_set_state(nego, NEGO_STATE_TLS);
149
0
    }
150
0
    else if (nego->EnabledProtocols[PROTOCOL_RDP])
151
0
    {
152
0
      nego_set_state(nego, NEGO_STATE_RDP);
153
0
    }
154
0
    else
155
0
    {
156
0
      WLog_Print(nego->log, WLOG_ERROR, "No security protocol is enabled");
157
0
      nego_set_state(nego, NEGO_STATE_FAIL);
158
0
      return FALSE;
159
0
    }
160
161
0
    if (!nego->NegotiateSecurityLayer)
162
0
    {
163
0
      WLog_Print(nego->log, WLOG_DEBUG, "Security Layer Negotiation is disabled");
164
      /* attempt only the highest enabled protocol (see nego_attempt_*) */
165
0
      nego->EnabledProtocols[PROTOCOL_RDSAAD] = FALSE;
166
0
      nego->EnabledProtocols[PROTOCOL_HYBRID] = FALSE;
167
0
      nego->EnabledProtocols[PROTOCOL_SSL] = FALSE;
168
0
      nego->EnabledProtocols[PROTOCOL_RDP] = FALSE;
169
0
      nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = FALSE;
170
0
      nego->EnabledProtocols[PROTOCOL_RDSTLS] = FALSE;
171
172
0
      UINT32 SelectedProtocol = 0;
173
0
      switch (nego_get_state(nego))
174
0
      {
175
0
        case NEGO_STATE_AAD:
176
0
          nego->EnabledProtocols[PROTOCOL_RDSAAD] = TRUE;
177
0
          SelectedProtocol = PROTOCOL_RDSAAD;
178
0
          break;
179
0
        case NEGO_STATE_RDSTLS:
180
0
          nego->EnabledProtocols[PROTOCOL_RDSTLS] = TRUE;
181
0
          SelectedProtocol = PROTOCOL_RDSTLS;
182
0
          break;
183
0
        case NEGO_STATE_EXT:
184
0
          nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = TRUE;
185
0
          nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
186
0
          SelectedProtocol = PROTOCOL_HYBRID_EX;
187
0
          break;
188
0
        case NEGO_STATE_NLA:
189
0
          nego->EnabledProtocols[PROTOCOL_HYBRID] = TRUE;
190
0
          SelectedProtocol = PROTOCOL_HYBRID;
191
0
          break;
192
0
        case NEGO_STATE_TLS:
193
0
          nego->EnabledProtocols[PROTOCOL_SSL] = TRUE;
194
0
          SelectedProtocol = PROTOCOL_SSL;
195
0
          break;
196
0
        case NEGO_STATE_RDP:
197
0
          nego->EnabledProtocols[PROTOCOL_RDP] = TRUE;
198
0
          SelectedProtocol = PROTOCOL_RDP;
199
0
          break;
200
0
        default:
201
0
          WLog_Print(nego->log, WLOG_ERROR, "Invalid NEGO state 0x%08" PRIx32,
202
0
                     nego_get_state(nego));
203
0
          return FALSE;
204
0
      }
205
0
      if (!nego_set_selected_protocol(nego, SelectedProtocol))
206
0
        return FALSE;
207
0
    }
208
209
0
    if (!nego_tcp_connect(nego))
210
0
    {
211
0
      WLog_Print(nego->log, WLOG_ERROR, "Failed to connect");
212
0
      return FALSE;
213
0
    }
214
215
0
    if (nego->SendPreconnectionPdu)
216
0
    {
217
0
      if (!nego_send_preconnection_pdu(nego))
218
0
      {
219
0
        WLog_Print(nego->log, WLOG_ERROR, "Failed to send preconnection pdu");
220
0
        nego_set_state(nego, NEGO_STATE_FINAL);
221
0
        return FALSE;
222
0
      }
223
0
    }
224
0
  }
225
226
0
  if (!nego->NegotiateSecurityLayer)
227
0
  {
228
0
    nego_set_state(nego, NEGO_STATE_FINAL);
229
0
  }
230
0
  else
231
0
  {
232
0
    do
233
0
    {
234
0
      WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
235
0
      nego_send(nego);
236
237
0
      if (nego_get_state(nego) == NEGO_STATE_FAIL)
238
0
      {
239
0
        if (freerdp_get_last_error(transport_get_context(nego->transport)) ==
240
0
            FREERDP_ERROR_SUCCESS)
241
0
          WLog_Print(nego->log, WLOG_ERROR, "Protocol Security Negotiation Failure");
242
243
0
        nego_set_state(nego, NEGO_STATE_FINAL);
244
0
        return FALSE;
245
0
      }
246
0
    } while (nego_get_state(nego) != NEGO_STATE_FINAL);
247
0
  }
248
249
0
  {
250
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
251
0
    WLog_Print(nego->log, WLOG_DEBUG, "Negotiated %s security",
252
0
               nego_protocol_to_str(nego->SelectedProtocol, buffer, sizeof(buffer)));
253
0
  }
254
255
  /* update settings with negotiated protocol security */
256
0
  if (!nego_update_settings_from_state(nego, settings))
257
0
    return FALSE;
258
259
0
  if (nego->SelectedProtocol == PROTOCOL_RDP)
260
0
  {
261
0
    if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
262
0
      return FALSE;
263
264
0
    if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionMethods) == 0)
265
0
    {
266
      /**
267
       * Advertise all supported encryption methods if the client
268
       * implementation did not set any security methods
269
       */
270
0
      if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionMethods,
271
0
                                       ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT |
272
0
                                           ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS))
273
0
        return FALSE;
274
0
    }
275
0
  }
276
277
  /* finally connect security layer (if not already done) */
278
0
  if (!nego_security_connect(nego))
279
0
  {
280
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
281
0
    WLog_Print(nego->log, WLOG_DEBUG, "Failed to connect with %s security",
282
0
               nego_protocol_to_str(nego->SelectedProtocol, buffer, sizeof(buffer)));
283
0
    return FALSE;
284
0
  }
285
286
0
  return TRUE;
287
0
}
288
289
BOOL nego_disconnect(rdpNego* nego)
290
0
{
291
0
  WINPR_ASSERT(nego);
292
0
  nego_set_state(nego, NEGO_STATE_INITIAL);
293
0
  return nego_transport_disconnect(nego);
294
0
}
295
296
static BOOL nego_try_connect(rdpNego* nego)
297
0
{
298
0
  WINPR_ASSERT(nego);
299
300
0
  switch (nego->SelectedProtocol)
301
0
  {
302
0
    case PROTOCOL_RDSAAD:
303
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_RDSAAD");
304
0
      nego->SecurityConnected = transport_connect_aad(nego->transport);
305
0
      break;
306
0
    case PROTOCOL_RDSTLS:
307
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_RDSTLS");
308
0
      nego->SecurityConnected = transport_connect_rdstls(nego->transport);
309
0
      break;
310
0
    case PROTOCOL_HYBRID:
311
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_HYBRID");
312
0
      nego->SecurityConnected = transport_connect_nla(nego->transport, FALSE);
313
0
      break;
314
0
    case PROTOCOL_HYBRID_EX:
315
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_HYBRID_EX");
316
0
      nego->SecurityConnected = transport_connect_nla(nego->transport, TRUE);
317
0
      break;
318
0
    case PROTOCOL_SSL:
319
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_SSL");
320
0
      nego->SecurityConnected = transport_connect_tls(nego->transport);
321
0
      break;
322
0
    case PROTOCOL_RDP:
323
0
      WLog_Print(nego->log, WLOG_DEBUG, "nego_security_connect with PROTOCOL_RDP");
324
0
      nego->SecurityConnected = transport_connect_rdp(nego->transport);
325
0
      break;
326
0
    default:
327
0
      WLog_Print(nego->log, WLOG_ERROR,
328
0
                 "cannot connect security layer because no protocol has been selected yet.");
329
0
      return FALSE;
330
0
  }
331
0
  return nego->SecurityConnected;
332
0
}
333
334
/* connect to selected security layer */
335
BOOL nego_security_connect(rdpNego* nego)
336
0
{
337
0
  WINPR_ASSERT(nego);
338
0
  if (!nego->TcpConnected)
339
0
  {
340
0
    nego->SecurityConnected = FALSE;
341
0
  }
342
0
  else if (!nego->SecurityConnected)
343
0
  {
344
0
    if (!nego_try_connect(nego))
345
0
      return FALSE;
346
0
  }
347
348
0
  return nego->SecurityConnected;
349
0
}
350
351
static BOOL nego_tcp_connect(rdpNego* nego)
352
0
{
353
0
  rdpContext* context = nullptr;
354
0
  WINPR_ASSERT(nego);
355
0
  if (!nego->TcpConnected)
356
0
  {
357
0
    UINT32 TcpConnectTimeout = 0;
358
359
0
    context = transport_get_context(nego->transport);
360
0
    WINPR_ASSERT(context);
361
362
0
    TcpConnectTimeout =
363
0
        freerdp_settings_get_uint32(context->settings, FreeRDP_TcpConnectTimeout);
364
365
0
    if (nego->GatewayEnabled)
366
0
    {
367
0
      if (nego->GatewayBypassLocal)
368
0
      {
369
        /* Attempt a direct connection first, and then fallback to using the gateway */
370
0
        WLog_Print(
371
0
            nego->log, WLOG_INFO,
372
0
            "Detecting if host can be reached locally. - This might take some time.");
373
0
        WLog_Print(nego->log, WLOG_INFO,
374
0
                   "To disable auto detection use /gateway-usage-method:direct");
375
0
        transport_set_gateway_enabled(nego->transport, FALSE);
376
0
        nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
377
0
                                               TcpConnectTimeout);
378
0
      }
379
380
0
      if (!nego->TcpConnected)
381
0
      {
382
0
        transport_set_gateway_enabled(nego->transport, TRUE);
383
0
        nego->TcpConnected = transport_connect(nego->transport, nego->hostname, nego->port,
384
0
                                               TcpConnectTimeout);
385
0
      }
386
0
    }
387
0
    else if (nego->ConnectChildSession)
388
0
    {
389
0
      nego->TcpConnected = transport_connect_childsession(nego->transport);
390
0
    }
391
0
    else
392
0
    {
393
0
      nego->TcpConnected =
394
0
          transport_connect(nego->transport, nego->hostname, nego->port, TcpConnectTimeout);
395
0
    }
396
0
  }
397
398
0
  return nego->TcpConnected;
399
0
}
400
401
/**
402
 * Connect TCP layer. For direct approach, connect security layer as well.
403
 *
404
 * @param nego A pointer to the NEGO struct
405
 *
406
 * @return \b TRUE for success, \b FALSE otherwise
407
 */
408
409
BOOL nego_transport_connect(rdpNego* nego)
410
0
{
411
0
  WINPR_ASSERT(nego);
412
0
  if (!nego_tcp_connect(nego))
413
0
    return FALSE;
414
415
0
  if (nego->TcpConnected && !nego->NegotiateSecurityLayer)
416
0
    return nego_security_connect(nego);
417
418
0
  return nego->TcpConnected;
419
0
}
420
421
/**
422
 * Disconnect TCP layer.
423
 *
424
 * @param nego A pointer to the NEGO struct
425
 *
426
 * @return \b TRUE for success, \b FALSE otherwise
427
 */
428
429
BOOL nego_transport_disconnect(rdpNego* nego)
430
0
{
431
0
  WINPR_ASSERT(nego);
432
0
  if (nego->TcpConnected)
433
0
    transport_disconnect(nego->transport);
434
435
0
  nego->TcpConnected = FALSE;
436
0
  nego->SecurityConnected = FALSE;
437
0
  return TRUE;
438
0
}
439
440
/**
441
 * Send preconnection information if enabled.
442
 *
443
 * @param nego A pointer to the NEGO struct
444
 *
445
 * @return \b TRUE for success, \b FALSE otherwise
446
 */
447
448
BOOL nego_send_preconnection_pdu(rdpNego* nego)
449
0
{
450
0
  wStream* s = nullptr;
451
0
  UINT32 cbSize = 0;
452
0
  UINT16 cchPCB = 0;
453
0
  WCHAR* wszPCB = nullptr;
454
455
0
  WINPR_ASSERT(nego);
456
457
0
  WLog_Print(nego->log, WLOG_DEBUG, "Sending preconnection PDU");
458
459
0
  if (!nego_tcp_connect(nego))
460
0
    return FALSE;
461
462
  /* it's easier to always send the version 2 PDU, and it's just 2 bytes overhead */
463
0
  cbSize = PRECONNECTION_PDU_V2_MIN_SIZE;
464
465
0
  if (nego->PreconnectionBlob)
466
0
  {
467
0
    size_t len = 0;
468
0
    wszPCB = ConvertUtf8ToWCharAlloc(nego->PreconnectionBlob, &len);
469
0
    if (len > UINT16_MAX - 1)
470
0
    {
471
0
      free(wszPCB);
472
0
      return FALSE;
473
0
    }
474
0
    cchPCB = (UINT16)len;
475
0
    cchPCB += 1; /* zero-termination */
476
0
    cbSize += cchPCB * sizeof(WCHAR);
477
0
  }
478
479
0
  s = Stream_New(nullptr, cbSize);
480
481
0
  if (!s)
482
0
  {
483
0
    free(wszPCB);
484
0
    WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
485
0
    return FALSE;
486
0
  }
487
488
0
  Stream_Write_UINT32(s, cbSize);                /* cbSize */
489
0
  Stream_Write_UINT32(s, 0);                     /* Flags */
490
0
  Stream_Write_UINT32(s, PRECONNECTION_PDU_V2);  /* Version */
491
0
  Stream_Write_UINT32(s, nego->PreconnectionId); /* Id */
492
0
  Stream_Write_UINT16(s, cchPCB);                /* cchPCB */
493
494
0
  if (wszPCB)
495
0
  {
496
0
    Stream_Write(s, wszPCB, cchPCB * sizeof(WCHAR)); /* wszPCB */
497
0
    free(wszPCB);
498
0
  }
499
500
0
  Stream_SealLength(s);
501
502
0
  if (transport_write(nego->transport, s) < 0)
503
0
  {
504
0
    Stream_Free(s, TRUE);
505
0
    return FALSE;
506
0
  }
507
508
0
  Stream_Free(s, TRUE);
509
0
  return TRUE;
510
0
}
511
512
static void nego_attempt_rdstls(rdpNego* nego)
513
0
{
514
0
  WINPR_ASSERT(nego);
515
0
  nego->RequestedProtocols = PROTOCOL_RDSTLS | PROTOCOL_SSL;
516
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDSTLS security");
517
518
0
  if (!nego_transport_connect(nego))
519
0
  {
520
0
    nego_set_state(nego, NEGO_STATE_FAIL);
521
0
    return;
522
0
  }
523
524
0
  if (!nego_send_negotiation_request(nego))
525
0
  {
526
0
    nego_set_state(nego, NEGO_STATE_FAIL);
527
0
    return;
528
0
  }
529
530
0
  if (!nego_recv_response(nego))
531
0
  {
532
0
    nego_set_state(nego, NEGO_STATE_FAIL);
533
0
    return;
534
0
  }
535
536
0
  WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
537
538
0
  if (nego_get_state(nego) != NEGO_STATE_FINAL)
539
0
  {
540
0
    nego_transport_disconnect(nego);
541
542
0
    if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
543
0
      nego_set_state(nego, NEGO_STATE_EXT);
544
0
    else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
545
0
      nego_set_state(nego, NEGO_STATE_NLA);
546
0
    else if (nego->EnabledProtocols[PROTOCOL_SSL])
547
0
      nego_set_state(nego, NEGO_STATE_TLS);
548
0
    else if (nego->EnabledProtocols[PROTOCOL_RDP])
549
0
      nego_set_state(nego, NEGO_STATE_RDP);
550
0
    else
551
0
      nego_set_state(nego, NEGO_STATE_FAIL);
552
0
  }
553
0
}
554
555
static void nego_attempt_rdsaad(rdpNego* nego)
556
0
{
557
0
  WINPR_ASSERT(nego);
558
0
  nego->RequestedProtocols = PROTOCOL_RDSAAD;
559
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDS AAD Auth security");
560
561
0
  if (!nego_transport_connect(nego))
562
0
  {
563
0
    nego_set_state(nego, NEGO_STATE_FAIL);
564
0
    return;
565
0
  }
566
567
0
  if (!nego_send_negotiation_request(nego))
568
0
  {
569
0
    nego_set_state(nego, NEGO_STATE_FAIL);
570
0
    return;
571
0
  }
572
573
0
  if (!nego_recv_response(nego))
574
0
  {
575
0
    nego_set_state(nego, NEGO_STATE_FAIL);
576
0
    return;
577
0
  }
578
579
0
  WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
580
581
0
  if (nego_get_state(nego) != NEGO_STATE_FINAL)
582
0
  {
583
0
    nego_transport_disconnect(nego);
584
585
0
    if (nego->EnabledProtocols[PROTOCOL_HYBRID_EX])
586
0
      nego_set_state(nego, NEGO_STATE_EXT);
587
0
    else if (nego->EnabledProtocols[PROTOCOL_HYBRID])
588
0
      nego_set_state(nego, NEGO_STATE_NLA);
589
0
    else if (nego->EnabledProtocols[PROTOCOL_SSL])
590
0
      nego_set_state(nego, NEGO_STATE_TLS);
591
0
    else if (nego->EnabledProtocols[PROTOCOL_RDP])
592
0
      nego_set_state(nego, NEGO_STATE_RDP);
593
0
    else
594
0
      nego_set_state(nego, NEGO_STATE_FAIL);
595
0
  }
596
0
}
597
598
static void nego_attempt_ext(rdpNego* nego)
599
0
{
600
0
  WINPR_ASSERT(nego);
601
0
  nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL | PROTOCOL_HYBRID_EX;
602
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA extended security");
603
604
0
  if (!nego_transport_connect(nego))
605
0
  {
606
0
    nego_set_state(nego, NEGO_STATE_FAIL);
607
0
    return;
608
0
  }
609
610
0
  if (!nego_send_negotiation_request(nego))
611
0
  {
612
0
    nego_set_state(nego, NEGO_STATE_FAIL);
613
0
    return;
614
0
  }
615
616
0
  if (!nego_recv_response(nego))
617
0
  {
618
0
    nego_set_state(nego, NEGO_STATE_FAIL);
619
0
    return;
620
0
  }
621
622
0
  WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
623
624
0
  if (nego_get_state(nego) != NEGO_STATE_FINAL)
625
0
  {
626
0
    nego_transport_disconnect(nego);
627
628
0
    if (nego->EnabledProtocols[PROTOCOL_HYBRID])
629
0
      nego_set_state(nego, NEGO_STATE_NLA);
630
0
    else if (nego->EnabledProtocols[PROTOCOL_SSL])
631
0
      nego_set_state(nego, NEGO_STATE_TLS);
632
0
    else if (nego->EnabledProtocols[PROTOCOL_RDP])
633
0
      nego_set_state(nego, NEGO_STATE_RDP);
634
0
    else
635
0
      nego_set_state(nego, NEGO_STATE_FAIL);
636
0
  }
637
0
}
638
639
static void nego_attempt_nla(rdpNego* nego)
640
0
{
641
0
  WINPR_ASSERT(nego);
642
0
  nego->RequestedProtocols = PROTOCOL_HYBRID | PROTOCOL_SSL;
643
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting NLA security");
644
645
0
  if (!nego_transport_connect(nego))
646
0
  {
647
0
    nego_set_state(nego, NEGO_STATE_FAIL);
648
0
    return;
649
0
  }
650
651
0
  if (!nego_send_negotiation_request(nego))
652
0
  {
653
0
    nego_set_state(nego, NEGO_STATE_FAIL);
654
0
    return;
655
0
  }
656
657
0
  if (!nego_recv_response(nego))
658
0
  {
659
0
    nego_set_state(nego, NEGO_STATE_FAIL);
660
0
    return;
661
0
  }
662
663
0
  WLog_Print(nego->log, WLOG_DEBUG, "state: %s", nego_state_string(nego_get_state(nego)));
664
665
0
  if (nego_get_state(nego) != NEGO_STATE_FINAL)
666
0
  {
667
0
    nego_transport_disconnect(nego);
668
669
0
    if (nego->EnabledProtocols[PROTOCOL_SSL])
670
0
      nego_set_state(nego, NEGO_STATE_TLS);
671
0
    else if (nego->EnabledProtocols[PROTOCOL_RDP])
672
0
      nego_set_state(nego, NEGO_STATE_RDP);
673
0
    else
674
0
      nego_set_state(nego, NEGO_STATE_FAIL);
675
0
  }
676
0
}
677
678
static void nego_attempt_tls(rdpNego* nego)
679
0
{
680
0
  WINPR_ASSERT(nego);
681
0
  nego->RequestedProtocols = PROTOCOL_SSL;
682
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting TLS security");
683
684
0
  if (!nego_transport_connect(nego))
685
0
  {
686
0
    nego_set_state(nego, NEGO_STATE_FAIL);
687
0
    return;
688
0
  }
689
690
0
  if (!nego_send_negotiation_request(nego))
691
0
  {
692
0
    nego_set_state(nego, NEGO_STATE_FAIL);
693
0
    return;
694
0
  }
695
696
0
  if (!nego_recv_response(nego))
697
0
  {
698
0
    nego_set_state(nego, NEGO_STATE_FAIL);
699
0
    return;
700
0
  }
701
702
0
  if (nego_get_state(nego) != NEGO_STATE_FINAL)
703
0
  {
704
0
    nego_transport_disconnect(nego);
705
706
0
    if (nego->EnabledProtocols[PROTOCOL_RDP])
707
0
      nego_set_state(nego, NEGO_STATE_RDP);
708
0
    else
709
0
      nego_set_state(nego, NEGO_STATE_FAIL);
710
0
  }
711
0
}
712
713
static void nego_attempt_rdp(rdpNego* nego)
714
0
{
715
0
  WINPR_ASSERT(nego);
716
0
  nego->RequestedProtocols = PROTOCOL_RDP;
717
0
  WLog_Print(nego->log, WLOG_DEBUG, "Attempting RDP security");
718
719
0
  if (!nego_transport_connect(nego))
720
0
  {
721
0
    nego_set_state(nego, NEGO_STATE_FAIL);
722
0
    return;
723
0
  }
724
725
0
  if (!nego_send_negotiation_request(nego))
726
0
  {
727
0
    nego_set_state(nego, NEGO_STATE_FAIL);
728
0
    return;
729
0
  }
730
731
0
  if (!nego_recv_response(nego))
732
0
  {
733
0
    nego_set_state(nego, NEGO_STATE_FAIL);
734
0
    return;
735
0
  }
736
0
}
737
738
/**
739
 * Wait to receive a negotiation response
740
 *
741
 * @param nego A pointer to the NEGO struct
742
 *
743
 * @return \b TRUE for success, \b FALSE for failure
744
 */
745
746
BOOL nego_recv_response(rdpNego* nego)
747
0
{
748
0
  int status = 0;
749
0
  wStream* s = nullptr;
750
751
0
  WINPR_ASSERT(nego);
752
0
  s = Stream_New(nullptr, 1024);
753
754
0
  if (!s)
755
0
  {
756
0
    WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
757
0
    return FALSE;
758
0
  }
759
760
0
  status = transport_read_pdu(nego->transport, s);
761
762
0
  if (status < 0)
763
0
  {
764
0
    Stream_Free(s, TRUE);
765
0
    return FALSE;
766
0
  }
767
768
0
  status = nego_recv(nego->transport, s, nego);
769
0
  Stream_Free(s, TRUE);
770
771
0
  return (status >= 0);
772
0
}
773
774
/**
775
 * Receive protocol security negotiation message.
776
 * msdn{cc240501}
777
 *
778
 * @param transport The transport to read from
779
 * @param s A stream to read the received data from
780
 * @param extra nego pointer
781
 *
782
 * @return \b 0 for success, \b -1 for failure
783
 */
784
785
int nego_recv(WINPR_ATTR_UNUSED rdpTransport* transport, wStream* s, void* extra)
786
0
{
787
0
  BYTE li = 0;
788
0
  BYTE type = 0;
789
0
  UINT16 length = 0;
790
0
  rdpNego* nego = (rdpNego*)extra;
791
792
0
  WINPR_ASSERT(nego);
793
0
  if (!tpkt_read_header(s, &length))
794
0
    return -1;
795
796
0
  if (!tpdu_read_connection_confirm(s, &li, length))
797
0
    return -1;
798
799
0
  if (li > 6)
800
0
  {
801
    /* rdpNegData (optional) */
802
0
    Stream_Read_UINT8(s, type); /* Type */
803
804
0
    switch (type)
805
0
    {
806
0
      case TYPE_RDP_NEG_RSP:
807
0
        if (!nego_process_negotiation_response(nego, s))
808
0
          return -1;
809
0
        {
810
0
          char buffer[64] = WINPR_C_ARRAY_INIT;
811
0
          WLog_Print(
812
0
              nego->log, WLOG_DEBUG, "selected_protocol: %s",
813
0
              nego_protocol_to_str(nego->SelectedProtocol, buffer, sizeof(buffer)));
814
0
        }
815
816
        /* enhanced security selected ? */
817
818
0
        if (nego->SelectedProtocol)
819
0
        {
820
0
          if ((nego->SelectedProtocol == PROTOCOL_RDSAAD) &&
821
0
              (!nego->EnabledProtocols[PROTOCOL_RDSAAD]))
822
0
          {
823
0
            nego_set_state(nego, NEGO_STATE_FAIL);
824
0
          }
825
0
          if ((nego->SelectedProtocol == PROTOCOL_HYBRID) &&
826
0
              (!nego->EnabledProtocols[PROTOCOL_HYBRID]))
827
0
          {
828
0
            nego_set_state(nego, NEGO_STATE_FAIL);
829
0
          }
830
831
0
          if ((nego->SelectedProtocol == PROTOCOL_SSL) &&
832
0
              (!nego->EnabledProtocols[PROTOCOL_SSL]))
833
0
          {
834
0
            nego_set_state(nego, NEGO_STATE_FAIL);
835
0
          }
836
0
        }
837
0
        else if (!nego->EnabledProtocols[PROTOCOL_RDP])
838
0
        {
839
0
          nego_set_state(nego, NEGO_STATE_FAIL);
840
0
        }
841
842
0
        break;
843
844
0
      case TYPE_RDP_NEG_FAILURE:
845
0
        if (!nego_process_negotiation_failure(nego, s))
846
0
          return -1;
847
0
        break;
848
0
      default:
849
0
        return -1;
850
0
    }
851
0
  }
852
0
  else if (li == 6)
853
0
  {
854
0
    WLog_Print(nego->log, WLOG_DEBUG, "no rdpNegData");
855
856
0
    if (!nego->EnabledProtocols[PROTOCOL_RDP])
857
0
      nego_set_state(nego, NEGO_STATE_FAIL);
858
0
    else
859
0
      nego_set_state(nego, NEGO_STATE_FINAL);
860
0
  }
861
0
  else
862
0
  {
863
0
    WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation response");
864
0
    nego_set_state(nego, NEGO_STATE_FAIL);
865
0
  }
866
867
0
  if (!tpkt_ensure_stream_consumed(nego->log, s, length))
868
0
    return -1;
869
0
  return 0;
870
0
}
871
872
/**
873
 * Read optional routing token or cookie of X.224 Connection Request PDU.
874
 * msdn{cc240470}
875
 */
876
877
static BOOL nego_read_request_token_or_cookie(rdpNego* nego, wStream* s)
878
0
{
879
  /* routingToken and cookie are optional and mutually exclusive!
880
   *
881
   * routingToken (variable): An optional and variable-length routing
882
   * token (used for load balancing) terminated by a 0x0D0A two-byte
883
   * sequence: (check [MSFT-SDLBTS] for details!)
884
   * Cookie:[space]msts=[ip address].[port].[reserved][\x0D\x0A]
885
   * tsv://MS Terminal Services Plugin.1.[\x0D\x0A]
886
   *
887
   * cookie (variable): An optional and variable-length ANSI character
888
   * string terminated by a 0x0D0A two-byte sequence:
889
   * Cookie:[space]mstshash=[ANSISTRING][\x0D\x0A]
890
   */
891
0
  UINT16 crlf = 0;
892
0
  BOOL result = FALSE;
893
0
  BOOL isToken = FALSE;
894
0
  size_t remain = Stream_GetRemainingLength(s);
895
896
0
  WINPR_ASSERT(nego);
897
898
0
  const char* str = Stream_ConstPointer(s);
899
0
  const size_t pos = Stream_GetPosition(s);
900
901
  /* minimum length for token is 15 */
902
0
  if (remain < 15)
903
0
    return TRUE;
904
905
0
  if (memcmp(Stream_ConstPointer(s), "Cookie: mstshash=", 17) != 0)
906
0
  {
907
0
    if (memcmp(Stream_ConstPointer(s), "Cookie: msts=", 13) != 0)
908
0
    {
909
0
      if (memcmp(Stream_ConstPointer(s), "tsv:", 4) != 0)
910
0
      {
911
0
        if (memcmp(Stream_ConstPointer(s), "mth://", 6) != 0)
912
0
        {
913
          /* remaining bytes are neither a token nor a cookie */
914
0
          return TRUE;
915
0
        }
916
0
      }
917
0
    }
918
0
    isToken = TRUE;
919
0
  }
920
0
  else
921
0
  {
922
    /* not a token, minimum length for cookie is 19 */
923
0
    if (remain < 19)
924
0
      return TRUE;
925
926
0
    Stream_Seek(s, 17);
927
0
  }
928
929
0
  while (Stream_GetRemainingLength(s) >= 2)
930
0
  {
931
0
    Stream_Read_UINT16(s, crlf);
932
933
0
    if (crlf == 0x0A0D)
934
0
      break;
935
936
0
    Stream_Rewind(s, 1);
937
0
  }
938
939
0
  if (crlf == 0x0A0D)
940
0
  {
941
0
    Stream_Rewind(s, 2);
942
0
    const size_t len = Stream_GetPosition(s) - pos;
943
0
    Stream_Write_UINT16(s, 0);
944
945
0
    if (len > UINT32_MAX)
946
0
      return FALSE;
947
948
0
    if (strnlen(str, len) == len)
949
0
    {
950
0
      if (isToken)
951
0
        result = nego_set_routing_token(nego, str, (UINT32)len);
952
0
      else
953
0
        result = nego_set_cookie(nego, str);
954
0
    }
955
0
  }
956
957
0
  if (!result)
958
0
  {
959
0
    if (!Stream_SetPosition(s, pos))
960
0
      return FALSE;
961
0
    WLog_Print(nego->log, WLOG_ERROR, "invalid %s received",
962
0
               isToken ? "routing token" : "cookie");
963
0
  }
964
0
  else
965
0
  {
966
0
    WLog_Print(nego->log, WLOG_DEBUG, "received %s [%s]", isToken ? "routing token" : "cookie",
967
0
               str);
968
0
  }
969
970
0
  return result;
971
0
}
972
973
/**
974
 * Read protocol security negotiation request message.
975
 *
976
 * @param nego A pointer to the NEGO struct
977
 * @param s A stream to read from
978
 *
979
 * @return \b TRUE for success, \b FALSE for failure
980
 */
981
982
BOOL nego_read_request(rdpNego* nego, wStream* s)
983
0
{
984
0
  BYTE li = 0;
985
0
  BYTE type = 0;
986
0
  UINT16 length = 0;
987
988
0
  WINPR_ASSERT(nego);
989
0
  WINPR_ASSERT(s);
990
991
0
  if (!tpkt_read_header(s, &length))
992
0
    return FALSE;
993
994
0
  if (!tpdu_read_connection_request(s, &li, length))
995
0
    return FALSE;
996
997
0
  if (li != Stream_GetRemainingLength(s) + 6)
998
0
  {
999
0
    WLog_Print(nego->log, WLOG_ERROR, "Incorrect TPDU length indicator.");
1000
0
    return FALSE;
1001
0
  }
1002
1003
0
  if (!nego_read_request_token_or_cookie(nego, s))
1004
0
  {
1005
0
    WLog_Print(nego->log, WLOG_ERROR, "Failed to parse routing token or cookie.");
1006
0
    return FALSE;
1007
0
  }
1008
1009
0
  if (Stream_GetRemainingLength(s) >= 8)
1010
0
  {
1011
    /* rdpNegData (optional) */
1012
0
    Stream_Read_UINT8(s, type); /* Type */
1013
1014
0
    if (type != TYPE_RDP_NEG_REQ)
1015
0
    {
1016
0
      WLog_Print(nego->log, WLOG_ERROR, "Incorrect negotiation request type %" PRIu8 "",
1017
0
                 type);
1018
0
      return FALSE;
1019
0
    }
1020
1021
0
    if (!nego_process_negotiation_request(nego, s))
1022
0
      return FALSE;
1023
0
  }
1024
1025
0
  return tpkt_ensure_stream_consumed(nego->log, s, length);
1026
0
}
1027
1028
/**
1029
 * Send protocol security negotiation message.
1030
 *
1031
 * @param nego A pointer to the NEGO struct
1032
 */
1033
1034
void nego_send(rdpNego* nego)
1035
0
{
1036
0
  WINPR_ASSERT(nego);
1037
1038
0
  switch (nego_get_state(nego))
1039
0
  {
1040
0
    case NEGO_STATE_AAD:
1041
0
      nego_attempt_rdsaad(nego);
1042
0
      break;
1043
0
    case NEGO_STATE_RDSTLS:
1044
0
      nego_attempt_rdstls(nego);
1045
0
      break;
1046
0
    case NEGO_STATE_EXT:
1047
0
      nego_attempt_ext(nego);
1048
0
      break;
1049
0
    case NEGO_STATE_NLA:
1050
0
      nego_attempt_nla(nego);
1051
0
      break;
1052
0
    case NEGO_STATE_TLS:
1053
0
      nego_attempt_tls(nego);
1054
0
      break;
1055
0
    case NEGO_STATE_RDP:
1056
0
      nego_attempt_rdp(nego);
1057
0
      break;
1058
0
    default:
1059
0
      WLog_Print(nego->log, WLOG_ERROR, "invalid negotiation state for sending");
1060
0
      break;
1061
0
  }
1062
0
}
1063
1064
/**
1065
 * Send RDP Negotiation Request (RDP_NEG_REQ).
1066
 * msdn{cc240500}
1067
 * msdn{cc240470}
1068
 *
1069
 * @param nego A pointer to the NEGO struct
1070
 *
1071
 * @return \b TRUE for success, \b FALSE otherwise
1072
 */
1073
1074
BOOL nego_send_negotiation_request(rdpNego* nego)
1075
0
{
1076
0
  BOOL rc = FALSE;
1077
0
  wStream* s = nullptr;
1078
0
  size_t length = 0;
1079
0
  size_t bm = 0;
1080
0
  size_t em = 0;
1081
0
  BYTE flags = 0;
1082
0
  size_t cookie_length = 0;
1083
0
  s = Stream_New(nullptr, 512);
1084
1085
0
  WINPR_ASSERT(nego);
1086
0
  if (!s)
1087
0
  {
1088
0
    WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1089
0
    return FALSE;
1090
0
  }
1091
1092
0
  length = TPDU_CONNECTION_REQUEST_LENGTH;
1093
0
  bm = Stream_GetPosition(s);
1094
0
  Stream_Seek(s, length);
1095
1096
0
  if (nego->RoutingToken)
1097
0
  {
1098
0
    Stream_Write(s, nego->RoutingToken, nego->RoutingTokenLength);
1099
1100
    /* Ensure Routing Token is correctly terminated - may already be present in string */
1101
1102
0
    if ((nego->RoutingTokenLength > 2) &&
1103
0
        (nego->RoutingToken[nego->RoutingTokenLength - 2] == 0x0D) &&
1104
0
        (nego->RoutingToken[nego->RoutingTokenLength - 1] == 0x0A))
1105
0
    {
1106
0
      WLog_Print(nego->log, WLOG_DEBUG,
1107
0
                 "Routing token looks correctly terminated - use verbatim");
1108
0
      length += nego->RoutingTokenLength;
1109
0
    }
1110
0
    else
1111
0
    {
1112
0
      WLog_Print(nego->log, WLOG_DEBUG, "Adding terminating CRLF to routing token");
1113
0
      Stream_Write_UINT8(s, 0x0D); /* CR */
1114
0
      Stream_Write_UINT8(s, 0x0A); /* LF */
1115
0
      length += nego->RoutingTokenLength + 2;
1116
0
    }
1117
0
  }
1118
0
  else if (nego->cookie)
1119
0
  {
1120
0
    cookie_length = strlen(nego->cookie);
1121
1122
0
    if (cookie_length > nego->CookieMaxLength)
1123
0
      cookie_length = nego->CookieMaxLength;
1124
1125
0
    Stream_Write(s, "Cookie: mstshash=", 17);
1126
0
    Stream_Write(s, (BYTE*)nego->cookie, cookie_length);
1127
0
    Stream_Write_UINT8(s, 0x0D); /* CR */
1128
0
    Stream_Write_UINT8(s, 0x0A); /* LF */
1129
0
    length += cookie_length + 19;
1130
0
  }
1131
1132
0
  {
1133
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
1134
0
    WLog_Print(nego->log, WLOG_DEBUG, "RequestedProtocols: %s",
1135
0
               nego_protocol_to_str(nego->RequestedProtocols, buffer, sizeof(buffer)));
1136
0
  }
1137
1138
0
  if ((nego->RequestedProtocols > PROTOCOL_RDP) || (nego->sendNegoData))
1139
0
  {
1140
    /* RDP_NEG_DATA must be present for TLS and NLA */
1141
0
    if (nego->RestrictedAdminModeRequired)
1142
0
      flags |= RESTRICTED_ADMIN_MODE_REQUIRED;
1143
1144
0
    if (nego->RemoteCredsGuardRequired)
1145
0
      flags |= REDIRECTED_AUTHENTICATION_MODE_REQUIRED;
1146
1147
0
    Stream_Write_UINT8(s, TYPE_RDP_NEG_REQ);
1148
0
    Stream_Write_UINT8(s, flags);
1149
0
    Stream_Write_UINT16(s, 8);                        /* RDP_NEG_DATA length (8) */
1150
0
    Stream_Write_UINT32(s, nego->RequestedProtocols); /* requestedProtocols */
1151
0
    length += 8;
1152
0
  }
1153
1154
0
  if (length > UINT16_MAX)
1155
0
    goto fail;
1156
1157
0
  em = Stream_GetPosition(s);
1158
0
  if (!Stream_SetPosition(s, bm))
1159
0
    goto fail;
1160
0
  if (!tpkt_write_header(s, (UINT16)length))
1161
0
    goto fail;
1162
0
  if (!tpdu_write_connection_request(s, (UINT16)length - 5))
1163
0
    goto fail;
1164
0
  if (!Stream_SetPosition(s, em))
1165
0
    goto fail;
1166
0
  Stream_SealLength(s);
1167
0
  rc = (transport_write(nego->transport, s) >= 0);
1168
0
fail:
1169
0
  Stream_Free(s, TRUE);
1170
0
  return rc;
1171
0
}
1172
1173
static BOOL nego_process_correlation_info(WINPR_ATTR_UNUSED rdpNego* nego, wStream* s)
1174
0
{
1175
0
  UINT8 type = 0;
1176
0
  UINT8 flags = 0;
1177
0
  UINT16 length = 0;
1178
0
  BYTE correlationId[16] = WINPR_C_ARRAY_INIT;
1179
1180
0
  if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 36))
1181
0
  {
1182
0
    WLog_Print(nego->log, WLOG_ERROR,
1183
0
               "RDP_NEG_REQ::flags CORRELATION_INFO_PRESENT but data is missing");
1184
0
    return FALSE;
1185
0
  }
1186
1187
0
  Stream_Read_UINT8(s, type);
1188
0
  if (type != TYPE_RDP_CORRELATION_INFO)
1189
0
  {
1190
0
    WLog_Print(nego->log, WLOG_ERROR,
1191
0
               "(RDP_NEG_CORRELATION_INFO::type != TYPE_RDP_CORRELATION_INFO");
1192
0
    return FALSE;
1193
0
  }
1194
0
  Stream_Read_UINT8(s, flags);
1195
0
  if (flags != 0)
1196
0
  {
1197
0
    WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::flags != 0");
1198
0
    return FALSE;
1199
0
  }
1200
0
  Stream_Read_UINT16(s, length);
1201
0
  if (length != 36)
1202
0
  {
1203
0
    WLog_Print(nego->log, WLOG_ERROR, "(RDP_NEG_CORRELATION_INFO::length != 36");
1204
0
    return FALSE;
1205
0
  }
1206
1207
0
  Stream_Read(s, correlationId, sizeof(correlationId));
1208
0
  if ((correlationId[0] == 0x00) || (correlationId[0] == 0xF4))
1209
0
  {
1210
0
    WLog_Print(nego->log, WLOG_ERROR,
1211
0
               "(RDP_NEG_CORRELATION_INFO::correlationId[0] has invalid value 0x%02" PRIx8,
1212
0
               correlationId[0]);
1213
0
    return FALSE;
1214
0
  }
1215
0
  for (size_t x = 0; x < ARRAYSIZE(correlationId); x++)
1216
0
  {
1217
0
    if (correlationId[x] == 0x0D)
1218
0
    {
1219
0
      WLog_Print(nego->log, WLOG_ERROR,
1220
0
                 "(RDP_NEG_CORRELATION_INFO::correlationId[%" PRIuz
1221
0
                 "] has invalid value 0x%02" PRIx8,
1222
0
                 x, correlationId[x]);
1223
0
      return FALSE;
1224
0
    }
1225
0
  }
1226
0
  Stream_Seek(s, 16); /* skip reserved bytes */
1227
1228
0
  WLog_Print(nego->log, WLOG_INFO,
1229
0
             "RDP_NEG_CORRELATION_INFO::correlationId = { %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8
1230
0
             ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8
1231
0
             ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8 ", %02" PRIx8
1232
0
             ", %02" PRIx8 " }",
1233
0
             correlationId[0], correlationId[1], correlationId[2], correlationId[3],
1234
0
             correlationId[4], correlationId[5], correlationId[6], correlationId[7],
1235
0
             correlationId[8], correlationId[9], correlationId[10], correlationId[11],
1236
0
             correlationId[12], correlationId[13], correlationId[14], correlationId[15]);
1237
0
  return TRUE;
1238
0
}
1239
1240
BOOL nego_process_negotiation_request(rdpNego* nego, wStream* s)
1241
0
{
1242
0
  BYTE flags = 0;
1243
0
  UINT16 length = 0;
1244
1245
0
  WINPR_ASSERT(nego);
1246
0
  WINPR_ASSERT(s);
1247
1248
0
  if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1249
0
    return FALSE;
1250
0
  Stream_Read_UINT8(s, flags);
1251
0
  if ((flags & ~(RESTRICTED_ADMIN_MODE_REQUIRED | REDIRECTED_AUTHENTICATION_MODE_REQUIRED |
1252
0
                 CORRELATION_INFO_PRESENT)) != 0)
1253
0
  {
1254
0
    WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::flags invalid value 0x%02" PRIx8, flags);
1255
0
    return FALSE;
1256
0
  }
1257
0
  if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1258
0
  {
1259
0
    if (nego->RestrictedAdminModeSupported)
1260
0
    {
1261
0
      WLog_Print(nego->log, WLOG_INFO, "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED");
1262
0
    }
1263
0
    else
1264
0
    {
1265
0
      WLog_Print(nego->log, WLOG_ERROR,
1266
0
                 "RDP_NEG_REQ::flags RESTRICTED_ADMIN_MODE_REQUIRED but disabled");
1267
0
      return FALSE;
1268
0
    }
1269
0
  }
1270
1271
0
  if (flags & REDIRECTED_AUTHENTICATION_MODE_REQUIRED)
1272
0
  {
1273
0
    if (nego->RemoteCredsGuardSupported)
1274
0
    {
1275
0
      WLog_Print(nego->log, WLOG_INFO,
1276
0
                 "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED");
1277
0
      nego->RemoteCredsGuardActive = TRUE;
1278
0
    }
1279
0
    else
1280
0
    {
1281
      /* If both RESTRICTED_ADMIN_MODE_REQUIRED and REDIRECTED_AUTHENTICATION_MODE_REQUIRED
1282
       * are set, it means one or the other. In this case, don't fail if Remote Guard isn't
1283
       * available. */
1284
0
      if (flags & RESTRICTED_ADMIN_MODE_REQUIRED)
1285
0
      {
1286
0
        WLog_Print(nego->log, WLOG_INFO,
1287
0
                   "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED ignored.");
1288
0
      }
1289
0
      else
1290
0
      {
1291
0
        WLog_Print(
1292
0
            nego->log, WLOG_ERROR,
1293
0
            "RDP_NEG_REQ::flags REDIRECTED_AUTHENTICATION_MODE_REQUIRED but disabled");
1294
0
        return FALSE;
1295
0
      }
1296
0
    }
1297
0
  }
1298
1299
0
  Stream_Read_UINT16(s, length);
1300
0
  if (length != 8)
1301
0
  {
1302
0
    WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_REQ::length != 8");
1303
0
    return FALSE;
1304
0
  }
1305
0
  Stream_Read_UINT32(s, nego->RequestedProtocols);
1306
1307
0
  if (flags & CORRELATION_INFO_PRESENT)
1308
0
  {
1309
0
    if (!nego_process_correlation_info(nego, s))
1310
0
      return FALSE;
1311
0
  }
1312
1313
0
  {
1314
0
    char buffer[64] = WINPR_C_ARRAY_INIT;
1315
0
    WLog_Print(nego->log, WLOG_DEBUG, "RDP_NEG_REQ: RequestedProtocol: %s",
1316
0
               nego_protocol_to_str(nego->RequestedProtocols, buffer, sizeof(buffer)));
1317
0
  }
1318
0
  nego_set_state(nego, NEGO_STATE_FINAL);
1319
0
  return TRUE;
1320
0
}
1321
1322
static const char* nego_rdp_neg_rsp_flags_str(UINT32 flags)
1323
0
{
1324
0
  const uint32_t mask =
1325
0
      (EXTENDED_CLIENT_DATA_SUPPORTED | DYNVC_GFX_PROTOCOL_SUPPORTED | RDP_NEGRSP_RESERVED |
1326
0
       RESTRICTED_ADMIN_MODE_SUPPORTED | REDIRECTED_AUTHENTICATION_MODE_SUPPORTED);
1327
0
  static char buffer[1024] = WINPR_C_ARRAY_INIT;
1328
1329
0
  (void)_snprintf(buffer, ARRAYSIZE(buffer), "[0x%02" PRIx32 "] ", flags);
1330
0
  if (flags & EXTENDED_CLIENT_DATA_SUPPORTED)
1331
0
    winpr_str_append("EXTENDED_CLIENT_DATA_SUPPORTED", buffer, sizeof(buffer), "|");
1332
0
  if (flags & DYNVC_GFX_PROTOCOL_SUPPORTED)
1333
0
    winpr_str_append("DYNVC_GFX_PROTOCOL_SUPPORTED", buffer, sizeof(buffer), "|");
1334
0
  if (flags & RDP_NEGRSP_RESERVED)
1335
0
    winpr_str_append("RDP_NEGRSP_RESERVED", buffer, sizeof(buffer), "|");
1336
0
  if (flags & RESTRICTED_ADMIN_MODE_SUPPORTED)
1337
0
    winpr_str_append("RESTRICTED_ADMIN_MODE_SUPPORTED", buffer, sizeof(buffer), "|");
1338
0
  if (flags & REDIRECTED_AUTHENTICATION_MODE_SUPPORTED)
1339
0
    winpr_str_append("REDIRECTED_AUTHENTICATION_MODE_SUPPORTED", buffer, sizeof(buffer), "|");
1340
0
  if (flags & ~mask)
1341
0
  {
1342
0
    char buffer2[32] = WINPR_C_ARRAY_INIT;
1343
0
    (void)_snprintf(buffer2, sizeof(buffer2), "UNKNOWN[0x%04" PRIx32 "]", flags & ~mask);
1344
0
    winpr_str_append(buffer2, buffer, sizeof(buffer), "|");
1345
0
  }
1346
1347
0
  return buffer;
1348
0
}
1349
1350
BOOL nego_process_negotiation_response(rdpNego* nego, wStream* s)
1351
0
{
1352
0
  UINT16 length = 0;
1353
1354
0
  WINPR_ASSERT(nego);
1355
0
  WINPR_ASSERT(s);
1356
1357
0
  if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1358
0
  {
1359
0
    nego_set_state(nego, NEGO_STATE_FAIL);
1360
0
    return FALSE;
1361
0
  }
1362
1363
0
  Stream_Read_UINT8(s, nego->flags);
1364
0
  WLog_Print(nego->log, WLOG_DEBUG, "RDP_NEG_RSP::flags = { %s }",
1365
0
             nego_rdp_neg_rsp_flags_str(nego->flags));
1366
1367
0
  Stream_Read_UINT16(s, length);
1368
0
  if (length != 8)
1369
0
  {
1370
0
    WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_RSP::length != 8");
1371
0
    nego_set_state(nego, NEGO_STATE_FAIL);
1372
0
    return FALSE;
1373
0
  }
1374
0
  UINT32 SelectedProtocol = 0;
1375
0
  Stream_Read_UINT32(s, SelectedProtocol);
1376
1377
0
  if (!nego_set_selected_protocol(nego, SelectedProtocol))
1378
0
    return FALSE;
1379
0
  return nego_set_state(nego, NEGO_STATE_FINAL);
1380
0
}
1381
1382
static const char* nego_rdp_neg_fail_str(uint32_t what)
1383
0
{
1384
0
  switch (what)
1385
0
  {
1386
0
    case SSL_REQUIRED_BY_SERVER:
1387
0
      return "SSL_REQUIRED_BY_SERVER";
1388
0
    case SSL_NOT_ALLOWED_BY_SERVER:
1389
0
      return "SSL_NOT_ALLOWED_BY_SERVER";
1390
0
    case SSL_CERT_NOT_ON_SERVER:
1391
0
      return "SSL_CERT_NOT_ON_SERVER";
1392
0
    case INCONSISTENT_FLAGS:
1393
0
      return "INCONSISTENT_FLAGS";
1394
0
    case HYBRID_REQUIRED_BY_SERVER:
1395
0
      return "HYBRID_REQUIRED_BY_SERVER";
1396
0
    case SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER:
1397
0
      return "SSL_WITH_USER_AUTH_REQUIRED_BY_SERVER";
1398
0
    default:
1399
0
      return "UNKNOWN";
1400
0
  }
1401
0
}
1402
1403
static void nego_disable_all_except(rdpNego* nego, uint32_t what)
1404
0
{
1405
0
  WINPR_ASSERT(nego);
1406
1407
0
  char buffer[32] = WINPR_C_ARRAY_INIT;
1408
0
  WLog_Print(nego->log, WLOG_DEBUG, "Disabling all modes except %s",
1409
0
             nego_protocol_to_str(what, buffer, sizeof(buffer)));
1410
1411
0
  for (size_t x = 0; x < ARRAYSIZE(nego->EnabledProtocols); x++)
1412
0
  {
1413
0
    if (x == what)
1414
0
      continue;
1415
0
    nego->EnabledProtocols[x] = FALSE;
1416
0
  }
1417
0
}
1418
1419
/**
1420
 * Process Negotiation Failure from Connection Confirm message.
1421
 * @param nego A pointer to the NEGO struct
1422
 * @param s The stream to read from
1423
 *
1424
 * @return \b TRUE for success, \b FALSE otherwise
1425
 */
1426
1427
BOOL nego_process_negotiation_failure(rdpNego* nego, wStream* s)
1428
0
{
1429
0
  BYTE flags = 0;
1430
0
  UINT16 length = 0;
1431
1432
0
  WINPR_ASSERT(nego);
1433
0
  WINPR_ASSERT(s);
1434
1435
0
  WLog_Print(nego->log, WLOG_DEBUG, "RDP_NEG_FAILURE");
1436
0
  if (!Stream_CheckAndLogRequiredLengthWLog(nego->log, s, 7))
1437
0
    return FALSE;
1438
1439
0
  Stream_Read_UINT8(s, flags);
1440
0
  if (flags != 0)
1441
0
  {
1442
0
    WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::flags = 0x%02" PRIx8, flags);
1443
0
    return FALSE;
1444
0
  }
1445
0
  Stream_Read_UINT16(s, length);
1446
0
  if (length != 8)
1447
0
  {
1448
0
    WLog_Print(nego->log, WLOG_ERROR, "RDP_NEG_FAILURE::length != 8");
1449
0
    return FALSE;
1450
0
  }
1451
0
  const uint32_t failureCode = Stream_Get_UINT32(s);
1452
0
  const char* failureStr = nego_rdp_neg_fail_str(failureCode);
1453
0
  DWORD level = WLOG_WARN;
1454
0
  switch (failureCode)
1455
0
  {
1456
0
    case SSL_REQUIRED_BY_SERVER:
1457
0
      nego_disable_all_except(nego, PROTOCOL_SSL);
1458
0
      break;
1459
1460
0
    case SSL_NOT_ALLOWED_BY_SERVER:
1461
0
      nego_disable_all_except(nego, PROTOCOL_RDP);
1462
0
      nego->sendNegoData = TRUE;
1463
0
      break;
1464
1465
0
    case SSL_CERT_NOT_ON_SERVER:
1466
0
      level = WLOG_ERROR;
1467
0
      nego->sendNegoData = TRUE;
1468
0
      break;
1469
1470
0
    case INCONSISTENT_FLAGS:
1471
0
      level = WLOG_ERROR;
1472
0
      break;
1473
1474
0
    case HYBRID_REQUIRED_BY_SERVER:
1475
0
      nego_disable_all_except(nego, PROTOCOL_HYBRID);
1476
0
      break;
1477
1478
0
    default:
1479
0
      level = WLOG_ERROR;
1480
0
      break;
1481
0
  }
1482
1483
0
  WLog_Print(nego->log, level, "Error: %s [0x%08" PRIx32 "]", failureStr, failureCode);
1484
0
  nego_set_state(nego, NEGO_STATE_FAIL);
1485
0
  return TRUE;
1486
0
}
1487
1488
/**
1489
 * Send RDP Negotiation Response (RDP_NEG_RSP).
1490
 * @param nego A pointer to the NEGO struct
1491
 */
1492
1493
BOOL nego_send_negotiation_response(rdpNego* nego)
1494
0
{
1495
0
  BOOL status = FALSE;
1496
0
  BYTE flags = 0;
1497
0
  rdpContext* context = nullptr;
1498
0
  rdpSettings* settings = nullptr;
1499
1500
0
  WINPR_ASSERT(nego);
1501
0
  context = transport_get_context(nego->transport);
1502
0
  WINPR_ASSERT(context);
1503
1504
0
  settings = context->settings;
1505
0
  WINPR_ASSERT(settings);
1506
1507
0
  wStream* s = Stream_New(nullptr, 512);
1508
1509
0
  if (!s)
1510
0
  {
1511
0
    WLog_Print(nego->log, WLOG_ERROR, "Stream_New failed!");
1512
0
    return FALSE;
1513
0
  }
1514
1515
0
  UINT16 length = TPDU_CONNECTION_CONFIRM_LENGTH;
1516
0
  const size_t bm = Stream_GetPosition(s);
1517
0
  if (!Stream_SafeSeek(s, length))
1518
0
    goto fail;
1519
1520
0
  if (nego->SelectedProtocol & PROTOCOL_FAILED_NEGO)
1521
0
  {
1522
0
    UINT32 errorCode = (nego->SelectedProtocol & ~PROTOCOL_FAILED_NEGO);
1523
0
    flags = 0;
1524
0
    Stream_Write_UINT8(s, TYPE_RDP_NEG_FAILURE);
1525
0
    Stream_Write_UINT8(s, flags); /* flags */
1526
0
    Stream_Write_UINT16(s, 8);    /* RDP_NEG_DATA length (8) */
1527
0
    Stream_Write_UINT32(s, errorCode);
1528
0
    length += 8;
1529
0
  }
1530
0
  else
1531
0
  {
1532
0
    flags = EXTENDED_CLIENT_DATA_SUPPORTED;
1533
1534
0
    if (freerdp_settings_get_bool(settings, FreeRDP_SupportGraphicsPipeline))
1535
0
      flags |= DYNVC_GFX_PROTOCOL_SUPPORTED;
1536
1537
0
    if (nego->RestrictedAdminModeSupported)
1538
0
      flags |= RESTRICTED_ADMIN_MODE_SUPPORTED;
1539
1540
0
    if (nego->RemoteCredsGuardSupported)
1541
0
      flags |= REDIRECTED_AUTHENTICATION_MODE_SUPPORTED;
1542
1543
    /* RDP_NEG_DATA must be present for TLS, NLA, RDP and RDSTLS */
1544
0
    Stream_Write_UINT8(s, TYPE_RDP_NEG_RSP);
1545
0
    Stream_Write_UINT8(s, flags);                   /* flags */
1546
0
    Stream_Write_UINT16(s, 8);                      /* RDP_NEG_DATA length (8) */
1547
0
    Stream_Write_UINT32(s, nego->SelectedProtocol); /* selectedProtocol */
1548
0
    length += 8;
1549
0
  }
1550
1551
0
  const size_t em = Stream_GetPosition(s);
1552
0
  if (!Stream_SetPosition(s, bm))
1553
0
    goto fail;
1554
0
  if (!tpkt_write_header(s, length))
1555
0
    goto fail;
1556
1557
0
  if (!tpdu_write_connection_confirm(s, length - 5))
1558
0
    goto fail;
1559
1560
0
  if (!Stream_SetPosition(s, em))
1561
0
    goto fail;
1562
0
  Stream_SealLength(s);
1563
1564
0
  status = (transport_write(nego->transport, s) >= 0);
1565
1566
0
fail:
1567
0
  Stream_Free(s, TRUE);
1568
1569
0
  if (status)
1570
0
  {
1571
    /* update settings with negotiated protocol security */
1572
0
    if (!freerdp_settings_set_uint32(settings, FreeRDP_RequestedProtocols,
1573
0
                                     nego->RequestedProtocols))
1574
0
      return FALSE;
1575
0
    if (!freerdp_settings_set_uint32(settings, FreeRDP_SelectedProtocol,
1576
0
                                     nego->SelectedProtocol))
1577
0
      return FALSE;
1578
1579
0
    switch (nego->SelectedProtocol)
1580
0
    {
1581
0
      case PROTOCOL_RDP:
1582
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, FALSE))
1583
0
          return FALSE;
1584
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1585
0
          return FALSE;
1586
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, TRUE))
1587
0
          return FALSE;
1588
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, TRUE))
1589
0
          return FALSE;
1590
1591
0
        if (freerdp_settings_get_uint32(settings, FreeRDP_EncryptionLevel) ==
1592
0
            ENCRYPTION_LEVEL_NONE)
1593
0
        {
1594
          /**
1595
           * If the server implementation did not explicitly set a
1596
           * encryption level we default to client compatible
1597
           */
1598
0
          if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1599
0
                                           ENCRYPTION_LEVEL_CLIENT_COMPATIBLE))
1600
0
            return FALSE;
1601
0
        }
1602
1603
0
        if (freerdp_settings_get_bool(settings, FreeRDP_LocalConnection))
1604
0
        {
1605
          /**
1606
           * Note: This hack was firstly introduced in commit 95f5e115 to
1607
           * disable the unnecessary encryption with peers connecting to
1608
           * 127.0.0.1 or local unix sockets.
1609
           * This also affects connections via port tunnels! (e.g. ssh -L)
1610
           */
1611
0
          WLog_Print(nego->log, WLOG_INFO,
1612
0
                     "Turning off encryption for local peer with standard rdp security");
1613
0
          if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1614
0
            return FALSE;
1615
0
          if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1616
0
                                           ENCRYPTION_LEVEL_NONE))
1617
0
            return FALSE;
1618
0
        }
1619
0
        else if (!freerdp_settings_get_pointer(settings, FreeRDP_RdpServerRsaKey))
1620
0
        {
1621
0
          WLog_Print(nego->log, WLOG_ERROR, "Missing server certificate");
1622
0
          return FALSE;
1623
0
        }
1624
0
        break;
1625
0
      case PROTOCOL_SSL:
1626
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1627
0
          return FALSE;
1628
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1629
0
          return FALSE;
1630
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1631
0
          return FALSE;
1632
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1633
0
          return FALSE;
1634
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1635
0
          return FALSE;
1636
1637
0
        if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1638
0
                                         ENCRYPTION_LEVEL_NONE))
1639
0
          return FALSE;
1640
0
        break;
1641
0
      case PROTOCOL_HYBRID:
1642
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1643
0
          return FALSE;
1644
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE))
1645
0
          return FALSE;
1646
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, FALSE))
1647
0
          return FALSE;
1648
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1649
0
          return FALSE;
1650
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1651
0
          return FALSE;
1652
1653
0
        if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1654
0
                                         ENCRYPTION_LEVEL_NONE))
1655
0
          return FALSE;
1656
0
        break;
1657
0
      case PROTOCOL_RDSTLS:
1658
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_TlsSecurity, TRUE))
1659
0
          return FALSE;
1660
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, FALSE))
1661
0
          return FALSE;
1662
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdstlsSecurity, TRUE))
1663
0
          return FALSE;
1664
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_RdpSecurity, FALSE))
1665
0
          return FALSE;
1666
0
        if (!freerdp_settings_set_bool(settings, FreeRDP_UseRdpSecurityLayer, FALSE))
1667
0
          return FALSE;
1668
1669
0
        if (!freerdp_settings_set_uint32(settings, FreeRDP_EncryptionLevel,
1670
0
                                         ENCRYPTION_LEVEL_NONE))
1671
0
          return FALSE;
1672
0
        break;
1673
0
      default:
1674
0
        break;
1675
0
    }
1676
0
  }
1677
1678
0
  return status;
1679
0
}
1680
1681
/**
1682
 * Initialize NEGO state machine.
1683
 * @param nego A pointer to the NEGO struct
1684
 */
1685
1686
void nego_init(rdpNego* nego)
1687
15.4k
{
1688
15.4k
  WINPR_ASSERT(nego);
1689
15.4k
  nego_set_state(nego, NEGO_STATE_INITIAL);
1690
15.4k
  nego->RequestedProtocols = PROTOCOL_RDP;
1691
15.4k
  nego->CookieMaxLength = DEFAULT_COOKIE_MAX_LENGTH;
1692
15.4k
  nego->sendNegoData = FALSE;
1693
15.4k
  nego->flags = 0;
1694
15.4k
}
1695
1696
/**
1697
 * Create a new NEGO state machine instance.
1698
 *
1699
 * @param transport The transport to use
1700
 *
1701
 * @return A pointer to the allocated NEGO instance or nullptr
1702
 */
1703
1704
rdpNego* nego_new(rdpTransport* transport)
1705
15.4k
{
1706
15.4k
  rdpNego* nego = (rdpNego*)calloc(1, sizeof(rdpNego));
1707
1708
15.4k
  if (!nego)
1709
0
    return nullptr;
1710
1711
15.4k
  nego->log = WLog_Get(NEGO_TAG);
1712
15.4k
  WINPR_ASSERT(nego->log);
1713
15.4k
  nego->transport = transport;
1714
15.4k
  nego_init(nego);
1715
15.4k
  return nego;
1716
15.4k
}
1717
1718
/**
1719
 * Free NEGO state machine.
1720
 * @param nego A pointer to the NEGO struct
1721
 */
1722
1723
void nego_free(rdpNego* nego)
1724
15.4k
{
1725
15.4k
  if (nego)
1726
15.4k
  {
1727
15.4k
    free(nego->RoutingToken);
1728
15.4k
    free(nego->cookie);
1729
15.4k
    free(nego);
1730
15.4k
  }
1731
15.4k
}
1732
1733
/**
1734
 * Set target hostname and port.
1735
 * @param nego A pointer to the NEGO struct
1736
 * @param hostname The hostname to set
1737
 * @param port The port to set
1738
 *
1739
 * @return \b TRUE for success, \b FALSE otherwise
1740
 */
1741
1742
BOOL nego_set_target(rdpNego* nego, const char* hostname, UINT16 port)
1743
0
{
1744
0
  WINPR_ASSERT(nego);
1745
0
  WINPR_ASSERT(hostname);
1746
1747
0
  nego->hostname = hostname;
1748
0
  nego->port = port;
1749
0
  return TRUE;
1750
0
}
1751
1752
/**
1753
 * Enable security layer negotiation.
1754
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1755
 * @param NegotiateSecurityLayer whether to enable security layer negotiation (TRUE for enabled,
1756
 * FALSE for disabled)
1757
 */
1758
1759
void nego_set_negotiation_enabled(rdpNego* nego, BOOL NegotiateSecurityLayer)
1760
0
{
1761
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling security layer negotiation: %s",
1762
0
             NegotiateSecurityLayer ? "TRUE" : "FALSE");
1763
0
  nego->NegotiateSecurityLayer = NegotiateSecurityLayer;
1764
0
}
1765
1766
/**
1767
 * Enable restricted admin mode.
1768
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1769
 * @param RestrictedAdminModeRequired whether to enable security layer negotiation (TRUE for
1770
 * enabled, FALSE for disabled)
1771
 */
1772
1773
void nego_set_restricted_admin_mode_required(rdpNego* nego, BOOL RestrictedAdminModeRequired)
1774
0
{
1775
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling restricted admin mode: %s",
1776
0
             RestrictedAdminModeRequired ? "TRUE" : "FALSE");
1777
0
  nego->RestrictedAdminModeRequired = RestrictedAdminModeRequired;
1778
0
}
1779
1780
void nego_set_restricted_admin_mode_supported(rdpNego* nego, BOOL enabled)
1781
0
{
1782
0
  WINPR_ASSERT(nego);
1783
1784
0
  nego->RestrictedAdminModeSupported = enabled;
1785
0
}
1786
1787
void nego_set_RCG_required(rdpNego* nego, BOOL enabled)
1788
0
{
1789
0
  WINPR_ASSERT(nego);
1790
1791
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling remoteCredentialGuards: %s",
1792
0
             enabled ? "TRUE" : "FALSE");
1793
0
  nego->RemoteCredsGuardRequired = enabled;
1794
0
}
1795
1796
void nego_set_RCG_supported(rdpNego* nego, BOOL enabled)
1797
0
{
1798
0
  WINPR_ASSERT(nego);
1799
1800
0
  nego->RemoteCredsGuardSupported = enabled;
1801
0
}
1802
1803
BOOL nego_get_remoteCredentialGuard(const rdpNego* nego)
1804
0
{
1805
0
  WINPR_ASSERT(nego);
1806
1807
0
  return nego->RemoteCredsGuardActive;
1808
0
}
1809
1810
void nego_set_childsession_enabled(rdpNego* nego, BOOL ChildSessionEnabled)
1811
0
{
1812
0
  WINPR_ASSERT(nego);
1813
0
  nego->ConnectChildSession = ChildSessionEnabled;
1814
0
}
1815
1816
void nego_set_gateway_enabled(rdpNego* nego, BOOL GatewayEnabled)
1817
0
{
1818
0
  nego->GatewayEnabled = GatewayEnabled;
1819
0
}
1820
1821
void nego_set_gateway_bypass_local(rdpNego* nego, BOOL GatewayBypassLocal)
1822
0
{
1823
0
  nego->GatewayBypassLocal = GatewayBypassLocal;
1824
0
}
1825
1826
/**
1827
 * Enable RDP security protocol.
1828
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1829
 * @param enable_rdp whether to enable normal RDP protocol (TRUE for enabled, FALSE for disabled)
1830
 */
1831
1832
void nego_enable_rdp(rdpNego* nego, BOOL enable_rdp)
1833
0
{
1834
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDP security: %s", enable_rdp ? "TRUE" : "FALSE");
1835
0
  nego->EnabledProtocols[PROTOCOL_RDP] = enable_rdp;
1836
0
}
1837
1838
/**
1839
 * Enable TLS security protocol.
1840
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1841
 * @param enable_tls whether to enable TLS + RDP protocol (TRUE for enabled, FALSE for disabled)
1842
 */
1843
1844
void nego_enable_tls(rdpNego* nego, BOOL enable_tls)
1845
0
{
1846
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling TLS security: %s", enable_tls ? "TRUE" : "FALSE");
1847
0
  nego->EnabledProtocols[PROTOCOL_SSL] = enable_tls;
1848
0
}
1849
1850
/**
1851
 * Enable NLA security protocol.
1852
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1853
 * @param enable_nla whether to enable network level authentication protocol (TRUE for enabled,
1854
 * FALSE for disabled)
1855
 */
1856
1857
void nego_enable_nla(rdpNego* nego, BOOL enable_nla)
1858
0
{
1859
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling NLA security: %s", enable_nla ? "TRUE" : "FALSE");
1860
0
  nego->EnabledProtocols[PROTOCOL_HYBRID] = enable_nla;
1861
0
}
1862
1863
/**
1864
 * Enable RDSTLS security protocol.
1865
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1866
 * @param enable_rdstls whether to enable RDSTLS protocol (TRUE for enabled,
1867
 * FALSE for disabled)
1868
 */
1869
1870
void nego_enable_rdstls(rdpNego* nego, BOOL enable_rdstls)
1871
0
{
1872
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDSTLS security: %s",
1873
0
             enable_rdstls ? "TRUE" : "FALSE");
1874
0
  nego->EnabledProtocols[PROTOCOL_RDSTLS] = enable_rdstls;
1875
0
}
1876
1877
/**
1878
 * Enable NLA extended security protocol.
1879
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1880
 * @param enable_ext whether to enable network level authentication extended protocol (TRUE for
1881
 * enabled, FALSE for disabled)
1882
 */
1883
1884
void nego_enable_ext(rdpNego* nego, BOOL enable_ext)
1885
0
{
1886
0
  WLog_Print(nego->log, WLOG_DEBUG, "Enabling NLA extended security: %s",
1887
0
             enable_ext ? "TRUE" : "FALSE");
1888
0
  nego->EnabledProtocols[PROTOCOL_HYBRID_EX] = enable_ext;
1889
0
}
1890
1891
/**
1892
 * Enable RDS AAD security protocol.
1893
 * @param nego A pointer to the NEGO struct pointer to the negotiation structure
1894
 * @param enable_aad whether to enable RDS AAD Auth protocol (TRUE for
1895
 * enabled, FALSE for disabled)
1896
 */
1897
1898
void nego_enable_aad(rdpNego* nego, BOOL enable_aad)
1899
0
{
1900
0
  WINPR_ASSERT(nego);
1901
0
  if (aad_is_supported())
1902
0
  {
1903
0
    WLog_Print(nego->log, WLOG_DEBUG, "Enabling RDS AAD security: %s",
1904
0
               enable_aad ? "TRUE" : "FALSE");
1905
0
    nego->EnabledProtocols[PROTOCOL_RDSAAD] = enable_aad;
1906
0
  }
1907
0
  else
1908
0
  {
1909
0
    WLog_Print(nego->log, WLOG_WARN, "This build does not support AAD security, disabling.");
1910
0
  }
1911
0
}
1912
1913
/**
1914
 * Set routing token.
1915
 * @param nego A pointer to the NEGO struct
1916
 * @param RoutingToken A pointer to the routing token
1917
 * @param RoutingTokenLength The length of the routing token
1918
 *
1919
 * @return \b TRUE for success, \b FALSE otherwise
1920
 */
1921
1922
BOOL nego_set_routing_token(rdpNego* nego, const void* RoutingToken, DWORD RoutingTokenLength)
1923
0
{
1924
0
  if (RoutingTokenLength == 0)
1925
0
    return FALSE;
1926
1927
0
  free(nego->RoutingToken);
1928
0
  nego->RoutingTokenLength = RoutingTokenLength;
1929
0
  nego->RoutingToken = (BYTE*)malloc(nego->RoutingTokenLength);
1930
1931
0
  if (!nego->RoutingToken)
1932
0
    return FALSE;
1933
1934
0
  CopyMemory(nego->RoutingToken, RoutingToken, nego->RoutingTokenLength);
1935
0
  return TRUE;
1936
0
}
1937
1938
/**
1939
 * Set cookie.
1940
 * @param nego A pointer to the NEGO struct
1941
 * @param cookie A pointer to the cookie string
1942
 *
1943
 * @return \b TRUE for success, \b FALSE otherwise
1944
 */
1945
1946
BOOL nego_set_cookie(rdpNego* nego, const char* cookie)
1947
0
{
1948
0
  if (nego->cookie)
1949
0
  {
1950
0
    free(nego->cookie);
1951
0
    nego->cookie = nullptr;
1952
0
  }
1953
1954
0
  if (!cookie)
1955
0
    return TRUE;
1956
1957
0
  nego->cookie = _strdup(cookie);
1958
1959
0
  return (nego->cookie != nullptr);
1960
0
}
1961
1962
/**
1963
 * Set cookie maximum length
1964
 * @param nego A pointer to the NEGO struct
1965
 * @param CookieMaxLength the length to set
1966
 */
1967
1968
void nego_set_cookie_max_length(rdpNego* nego, UINT32 CookieMaxLength)
1969
0
{
1970
0
  nego->CookieMaxLength = CookieMaxLength;
1971
0
}
1972
1973
/**
1974
 * Enable / disable preconnection PDU.
1975
 * @param nego A pointer to the NEGO struct
1976
 * @param SendPreconnectionPdu The value to set
1977
 */
1978
1979
void nego_set_send_preconnection_pdu(rdpNego* nego, BOOL SendPreconnectionPdu)
1980
0
{
1981
0
  nego->SendPreconnectionPdu = SendPreconnectionPdu;
1982
0
}
1983
1984
/**
1985
 * Set preconnection id.
1986
 * @param nego A pointer to the NEGO struct
1987
 * @param PreconnectionId the ID to set
1988
 */
1989
1990
void nego_set_preconnection_id(rdpNego* nego, UINT32 PreconnectionId)
1991
0
{
1992
0
  nego->PreconnectionId = PreconnectionId;
1993
0
}
1994
1995
/**
1996
 * Set preconnection blob.
1997
 * @param nego A pointer to the NEGO struct
1998
 * @param PreconnectionBlob A pointer to the blob to use
1999
 */
2000
2001
void nego_set_preconnection_blob(rdpNego* nego, const char* PreconnectionBlob)
2002
0
{
2003
0
  nego->PreconnectionBlob = PreconnectionBlob;
2004
0
}
2005
2006
UINT32 nego_get_selected_protocol(const rdpNego* nego)
2007
0
{
2008
0
  if (!nego)
2009
0
    return 0;
2010
2011
0
  return nego->SelectedProtocol;
2012
0
}
2013
2014
BOOL nego_set_selected_protocol(rdpNego* nego, UINT32 SelectedProtocol)
2015
0
{
2016
0
  WINPR_ASSERT(nego);
2017
0
  nego->SelectedProtocol = SelectedProtocol;
2018
0
  return TRUE;
2019
0
}
2020
2021
UINT32 nego_get_requested_protocols(const rdpNego* nego)
2022
0
{
2023
0
  if (!nego)
2024
0
    return 0;
2025
2026
0
  return nego->RequestedProtocols;
2027
0
}
2028
2029
BOOL nego_set_requested_protocols(rdpNego* nego, UINT32 RequestedProtocols)
2030
0
{
2031
0
  if (!nego)
2032
0
    return FALSE;
2033
2034
0
  nego->RequestedProtocols = RequestedProtocols;
2035
0
  return TRUE;
2036
0
}
2037
2038
NEGO_STATE nego_get_state(const rdpNego* nego)
2039
0
{
2040
0
  if (!nego)
2041
0
    return NEGO_STATE_FAIL;
2042
2043
0
  return nego->state;
2044
0
}
2045
2046
BOOL nego_set_state(rdpNego* nego, NEGO_STATE state)
2047
15.4k
{
2048
15.4k
  WINPR_ASSERT(nego);
2049
15.4k
  nego->state = state;
2050
15.4k
  return TRUE;
2051
15.4k
}
2052
2053
SEC_WINNT_AUTH_IDENTITY* nego_get_identity(rdpNego* nego)
2054
0
{
2055
0
  rdpNla* nla = nullptr;
2056
0
  if (!nego)
2057
0
    return nullptr;
2058
2059
0
  nla = transport_get_nla(nego->transport);
2060
0
  return nla_get_identity(nla);
2061
0
}
2062
2063
void nego_free_nla(rdpNego* nego)
2064
0
{
2065
0
  if (!nego || !nego->transport)
2066
0
    return;
2067
2068
0
  transport_set_nla(nego->transport, nullptr);
2069
0
}
2070
2071
const BYTE* nego_get_routing_token(const rdpNego* nego, DWORD* RoutingTokenLength)
2072
0
{
2073
0
  if (!nego)
2074
0
    return nullptr;
2075
0
  if (RoutingTokenLength)
2076
0
    *RoutingTokenLength = nego->RoutingTokenLength;
2077
0
  return nego->RoutingToken;
2078
0
}
2079
2080
const char* nego_protocol_to_str(UINT32 protocol, char* buffer, size_t size)
2081
0
{
2082
0
  const UINT32 mask = ~(PROTOCOL_SSL | PROTOCOL_HYBRID | PROTOCOL_RDSTLS | PROTOCOL_HYBRID_EX |
2083
0
                        PROTOCOL_RDSAAD | PROTOCOL_FAILED_NEGO);
2084
0
  char str[48] = WINPR_C_ARRAY_INIT;
2085
2086
0
  if (protocol & PROTOCOL_SSL)
2087
0
    (void)winpr_str_append("SSL", str, sizeof(str), "|");
2088
0
  if (protocol & PROTOCOL_HYBRID)
2089
0
    (void)winpr_str_append("HYBRID", str, sizeof(str), "|");
2090
0
  if (protocol & PROTOCOL_RDSTLS)
2091
0
    (void)winpr_str_append("RDSTLS", str, sizeof(str), "|");
2092
0
  if (protocol & PROTOCOL_HYBRID_EX)
2093
0
    (void)winpr_str_append("HYBRID_EX", str, sizeof(str), "|");
2094
0
  if (protocol & PROTOCOL_RDSAAD)
2095
0
    (void)winpr_str_append("RDSAAD", str, sizeof(str), "|");
2096
0
  if (protocol & PROTOCOL_FAILED_NEGO)
2097
0
    (void)winpr_str_append("NEGO FAILED", str, sizeof(str), "|");
2098
2099
0
  if (protocol == PROTOCOL_RDP)
2100
0
    (void)winpr_str_append("RDP", str, sizeof(str), "");
2101
0
  else if ((protocol & mask) != 0)
2102
0
    (void)winpr_str_append("UNKNOWN", str, sizeof(str), "|");
2103
2104
0
  (void)_snprintf(buffer, size, "[%s][0x%08" PRIx32 "]", str, protocol);
2105
0
  return buffer;
2106
0
}