Coverage Report

Created: 2026-08-31 06:29

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