Coverage Report

Created: 2024-05-20 06:11

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