Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/libfreerdp/core/nla.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Network Level Authentication (NLA)
4
 *
5
 * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2015 Thincast Technologies GmbH
7
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8
 * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com>
9
 * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
10
 * Copyright 2022 David Fort <contact@hardening-consulting.com>
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 *     http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24
25
#include <freerdp/config.h>
26
27
#include "settings.h"
28
29
#include <time.h>
30
#include <ctype.h>
31
32
#include <freerdp/log.h>
33
#include <freerdp/build-config.h>
34
35
#include <winpr/crt.h>
36
#include <winpr/assert.h>
37
#include <winpr/sam.h>
38
#include <winpr/sspi.h>
39
#include <winpr/print.h>
40
#include <winpr/tchar.h>
41
#include <winpr/ncrypt.h>
42
#include <winpr/cred.h>
43
#include <winpr/debug.h>
44
#include <winpr/asn1.h>
45
#include <winpr/secapi.h>
46
47
#include "../crypto/tls.h"
48
#include "nego.h"
49
#include "rdp.h"
50
#include "nla.h"
51
#include "utils.h"
52
#include "credssp_auth.h"
53
#include <freerdp/utils/smartcardlogon.h>
54
55
#define TAG FREERDP_TAG("core.nla")
56
57
#define SERVER_KEY "Software\\" FREERDP_VENDOR_STRING "\\" FREERDP_PRODUCT_STRING "\\Server"
58
59
0
#define NLA_AUTH_PKG NEGO_SSP_NAME
60
61
typedef enum
62
{
63
  AUTHZ_SUCCESS = 0x00000000,
64
  AUTHZ_ACCESS_DENIED = 0x00000005,
65
} AUTHZ_RESULT;
66
67
/**
68
 * TSRequest ::= SEQUENCE {
69
 *  version    [0] INTEGER,
70
 *  negoTokens [1] NegoData OPTIONAL,
71
 *  authInfo   [2] OCTET STRING OPTIONAL,
72
 *  pubKeyAuth [3] OCTET STRING OPTIONAL,
73
 *  errorCode  [4] INTEGER OPTIONAL
74
 * }
75
 *
76
 * NegoData ::= SEQUENCE OF NegoDataItem
77
 *
78
 * NegoDataItem ::= SEQUENCE {
79
 *  negoToken [0] OCTET STRING
80
 * }
81
 *
82
 * TSCredentials ::= SEQUENCE {
83
 *  credType    [0] INTEGER,
84
 *  credentials [1] OCTET STRING
85
 * }
86
 *
87
 * TSPasswordCreds ::= SEQUENCE {
88
 *  domainName  [0] OCTET STRING,
89
 *  userName    [1] OCTET STRING,
90
 *  password    [2] OCTET STRING
91
 * }
92
 *
93
 * TSSmartCardCreds ::= SEQUENCE {
94
 *  pin        [0] OCTET STRING,
95
 *  cspData    [1] TSCspDataDetail,
96
 *  userHint   [2] OCTET STRING OPTIONAL,
97
 *  domainHint [3] OCTET STRING OPTIONAL
98
 * }
99
 *
100
 * TSCspDataDetail ::= SEQUENCE {
101
 *  keySpec       [0] INTEGER,
102
 *  cardName      [1] OCTET STRING OPTIONAL,
103
 *  readerName    [2] OCTET STRING OPTIONAL,
104
 *  containerName [3] OCTET STRING OPTIONAL,
105
 *  cspName       [4] OCTET STRING OPTIONAL
106
 * }
107
 *
108
 */
109
110
#define NLA_PKG_NAME CREDSSP_AUTH_PKG_SPNEGO
111
112
struct rdp_nla
113
{
114
  BOOL server;
115
  NLA_STATE state;
116
  ULONG sendSeqNum;
117
  ULONG recvSeqNum;
118
  rdpContext* rdpcontext;
119
  rdpTransport* transport;
120
  UINT32 version;
121
  UINT32 peerVersion;
122
  UINT32 errorCode;
123
124
  /* Lifetime of buffer nla_new -> nla_free */
125
  SecBuffer ClientNonce; /* Depending on protocol version a random nonce or a value read from the
126
                            server. */
127
128
  SecBuffer negoToken;
129
  SecBuffer pubKeyAuth;
130
  SecBuffer authInfo;
131
  SecBuffer PublicKey;
132
  SecBuffer tsCredentials;
133
134
  SEC_WINNT_AUTH_IDENTITY* identity;
135
136
  rdpCredsspAuth* auth;
137
  char* pkinitArgs;
138
  SmartcardCertInfo* smartcardCert;
139
  BYTE certSha1[20];
140
  BOOL earlyUserAuth;
141
};
142
143
static BOOL nla_send(rdpNla* nla);
144
static int nla_server_recv(rdpNla* nla);
145
static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
146
static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
147
static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
148
static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
149
static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
150
static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
151
152
void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
153
0
{
154
0
  WINPR_ASSERT(nla);
155
0
  WLog_DBG(TAG, "Early User Auth active: %s", earlyUserAuth ? "true" : "false");
156
0
  nla->earlyUserAuth = earlyUserAuth;
157
0
}
158
159
static void nla_buffer_free(rdpNla* nla)
160
13.2k
{
161
13.2k
  WINPR_ASSERT(nla);
162
13.2k
  sspi_SecBufferFree(&nla->pubKeyAuth);
163
13.2k
  sspi_SecBufferFree(&nla->authInfo);
164
13.2k
  sspi_SecBufferFree(&nla->negoToken);
165
13.2k
  sspi_SecBufferFree(&nla->ClientNonce);
166
13.2k
  sspi_SecBufferFree(&nla->PublicKey);
167
13.2k
}
168
169
static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx, const SecBuffer* buffer)
170
0
{
171
0
  if (!buffer)
172
0
    return FALSE;
173
0
  return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
174
0
}
175
176
static BOOL nla_sec_buffer_alloc(SecBuffer* buffer, size_t size)
177
13.2k
{
178
13.2k
  WINPR_ASSERT(buffer);
179
13.2k
  sspi_SecBufferFree(buffer);
180
13.2k
  if (size > ULONG_MAX)
181
0
    return FALSE;
182
13.2k
  if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
183
0
    return FALSE;
184
185
13.2k
  WINPR_ASSERT(buffer);
186
13.2k
  buffer->BufferType = SECBUFFER_TOKEN;
187
13.2k
  return TRUE;
188
13.2k
}
189
190
static BOOL nla_sec_buffer_alloc_from_data(SecBuffer* buffer, const BYTE* data, size_t offset,
191
                                           size_t size)
192
12
{
193
12
  if (!nla_sec_buffer_alloc(buffer, offset + size))
194
0
    return FALSE;
195
196
12
  WINPR_ASSERT(buffer);
197
12
  BYTE* pb = buffer->pvBuffer;
198
12
  memcpy(&pb[offset], data, size);
199
12
  return TRUE;
200
12
}
201
202
/* CredSSP Client-To-Server Binding Hash\0 */
203
static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
204
                                            0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
205
                                            0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
206
                                            0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
207
                                            0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
208
209
/* CredSSP Server-To-Client Binding Hash\0 */
210
static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
211
                                            0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
212
                                            0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
213
                                            0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
214
                                            0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
215
216
static const UINT32 NonceLength = 32;
217
218
static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
219
0
{
220
0
  BOOL ret = FALSE;
221
222
0
  WINPR_ASSERT(nla);
223
0
  WINPR_ASSERT(nla->rdpcontext);
224
225
0
  rdpSettings* settings = nla->rdpcontext->settings;
226
0
  WINPR_ASSERT(settings);
227
228
0
  if (!settings->SmartcardLogon)
229
0
    return TRUE;
230
231
0
  smartcardCertInfo_Free(nla->smartcardCert);
232
233
0
  if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
234
0
  {
235
0
    WLog_ERR(TAG, "unable to get smartcard certificate for logon");
236
0
    return FALSE;
237
0
  }
238
239
0
  if (!settings->CspName)
240
0
  {
241
0
    if (nla->smartcardCert->csp && !freerdp_settings_set_string_from_utf16(
242
0
                                       settings, FreeRDP_CspName, nla->smartcardCert->csp))
243
0
    {
244
0
      WLog_ERR(TAG, "unable to set CSP name");
245
0
      goto out;
246
0
    }
247
0
    if (!settings->CspName &&
248
0
        !freerdp_settings_set_string(settings, FreeRDP_CspName, MS_SCARD_PROV_A))
249
0
    {
250
0
      WLog_ERR(TAG, "unable to set CSP name");
251
0
      goto out;
252
0
    }
253
0
  }
254
255
0
  if (!settings->ReaderName && nla->smartcardCert->reader)
256
0
  {
257
0
    if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ReaderName,
258
0
                                                nla->smartcardCert->reader))
259
0
    {
260
0
      WLog_ERR(TAG, "unable to copy reader name");
261
0
      goto out;
262
0
    }
263
0
  }
264
265
0
  if (!settings->ContainerName && nla->smartcardCert->containerName)
266
0
  {
267
0
    if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ContainerName,
268
0
                                                nla->smartcardCert->containerName))
269
0
    {
270
0
      WLog_ERR(TAG, "unable to copy container name");
271
0
      goto out;
272
0
    }
273
0
  }
274
275
0
  memcpy(nla->certSha1, nla->smartcardCert->sha1Hash, sizeof(nla->certSha1));
276
277
0
  if (nla->smartcardCert->pkinitArgs)
278
0
  {
279
0
    nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
280
0
    if (!nla->pkinitArgs)
281
0
    {
282
0
      WLog_ERR(TAG, "unable to copy pkinitArgs");
283
0
      goto out;
284
0
    }
285
0
  }
286
287
0
  ret = TRUE;
288
0
out:
289
0
  return ret;
290
0
}
291
292
static BOOL nla_client_setup_identity(rdpNla* nla)
293
0
{
294
0
  BOOL PromptPassword = FALSE;
295
296
0
  WINPR_ASSERT(nla);
297
0
  WINPR_ASSERT(nla->rdpcontext);
298
299
0
  rdpSettings* settings = nla->rdpcontext->settings;
300
0
  WINPR_ASSERT(settings);
301
302
0
  freerdp* instance = nla->rdpcontext->instance;
303
0
  WINPR_ASSERT(instance);
304
305
  /* */
306
0
  if ((utils_str_is_empty(settings->Username) ||
307
0
       (utils_str_is_empty(settings->Password) &&
308
0
        utils_str_is_empty((const char*)settings->RedirectionPassword))))
309
0
  {
310
0
    PromptPassword = TRUE;
311
0
  }
312
313
0
  if (PromptPassword && !utils_str_is_empty(settings->Username))
314
0
  {
315
0
    WINPR_SAM* sam = SamOpen(NULL, TRUE);
316
0
    if (sam)
317
0
    {
318
0
      const size_t userLength = strlen(settings->Username);
319
0
      WINPR_SAM_ENTRY* entry = SamLookupUserA(
320
0
          sam, settings->Username, userLength + 1 /* ensure '\0' is checked too */, NULL, 0);
321
0
      if (entry)
322
0
      {
323
        /**
324
         * The user could be found in SAM database.
325
         * Use entry in SAM database later instead of prompt
326
         */
327
0
        PromptPassword = FALSE;
328
0
        SamFreeEntry(sam, entry);
329
0
      }
330
331
0
      SamClose(sam);
332
0
    }
333
0
  }
334
335
0
  if (PromptPassword)
336
0
  {
337
0
    if (settings->RestrictedAdminModeRequired)
338
0
    {
339
0
      if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
340
0
        PromptPassword = FALSE;
341
0
    }
342
343
0
    if (settings->RemoteCredentialGuard)
344
0
      PromptPassword = FALSE;
345
0
  }
346
347
0
  BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
348
0
  if (PromptPassword)
349
0
  {
350
0
    switch (utils_authenticate(instance, AUTH_NLA, TRUE))
351
0
    {
352
0
      case AUTH_SKIP:
353
0
      case AUTH_SUCCESS:
354
0
        break;
355
0
      case AUTH_CANCELLED:
356
0
        freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
357
0
        return FALSE;
358
0
      case AUTH_NO_CREDENTIALS:
359
0
        WLog_INFO(TAG, "No credentials provided - using NULL identity");
360
0
        break;
361
0
      default:
362
0
        return FALSE;
363
0
    }
364
0
  }
365
366
0
  if (!settings->Username)
367
0
  {
368
0
    sspi_FreeAuthIdentity(nla->identity);
369
0
    nla->identity = NULL;
370
0
  }
371
0
  else if (settings->SmartcardLogon)
372
0
  {
373
0
    if (smartCardLogonWasDisabled)
374
0
    {
375
0
      if (!nla_adjust_settings_from_smartcard(nla))
376
0
        return FALSE;
377
0
    }
378
379
0
    if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
380
0
                                          FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
381
0
                                          sizeof(nla->certSha1)))
382
0
      return FALSE;
383
0
  }
384
0
  else
385
0
  {
386
0
    BOOL usePassword = TRUE;
387
388
0
    if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
389
0
    {
390
0
      if (!identity_set_from_settings_with_pwd(
391
0
              nla->identity, settings, FreeRDP_Username, FreeRDP_Domain,
392
0
              (const WCHAR*)settings->RedirectionPassword,
393
0
              settings->RedirectionPasswordLength / sizeof(WCHAR)))
394
0
        return FALSE;
395
396
0
      usePassword = FALSE;
397
0
    }
398
399
0
    if (settings->RestrictedAdminModeRequired)
400
0
    {
401
0
      if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
402
0
      {
403
0
        if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
404
0
                                        FreeRDP_Domain, FreeRDP_PasswordHash))
405
0
          return FALSE;
406
407
        /**
408
         * Increase password hash length by LB_PASSWORD_MAX_LENGTH to obtain a
409
         * length exceeding the maximum (LB_PASSWORD_MAX_LENGTH) and use it this for
410
         * hash identification in WinPR.
411
         */
412
0
        nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
413
0
        usePassword = FALSE;
414
0
      }
415
0
    }
416
417
0
    if (usePassword)
418
0
    {
419
0
      if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
420
0
                                      FreeRDP_Domain, FreeRDP_Password))
421
0
        return FALSE;
422
0
    }
423
0
  }
424
425
0
  return TRUE;
426
0
}
427
428
static int nla_client_init(rdpNla* nla)
429
0
{
430
0
  WINPR_ASSERT(nla);
431
0
  WINPR_ASSERT(nla->rdpcontext);
432
433
0
  rdpSettings* settings = nla->rdpcontext->settings;
434
0
  WINPR_ASSERT(settings);
435
436
0
  nla_set_state(nla, NLA_STATE_INITIAL);
437
438
0
  if (!nla_adjust_settings_from_smartcard(nla))
439
0
    return -1;
440
441
0
  if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, NULL))
442
0
    return -1;
443
444
0
  if (!nla_client_setup_identity(nla))
445
0
    return -1;
446
447
0
  const char* hostname = freerdp_settings_get_server_name(settings);
448
449
0
  if (!credssp_auth_setup_client(nla->auth, "TERMSRV", hostname, nla->identity, nla->pkinitArgs))
450
0
    return -1;
451
452
0
  const BYTE* data = NULL;
453
0
  DWORD length = 0;
454
0
  if (!transport_get_public_key(nla->transport, &data, &length))
455
0
  {
456
0
    WLog_ERR(TAG, "Failed to get public key");
457
0
    return -1;
458
0
  }
459
460
0
  if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
461
0
  {
462
0
    WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
463
0
    return -1;
464
0
  }
465
466
0
  return 1;
467
0
}
468
469
int nla_client_begin(rdpNla* nla)
470
0
{
471
0
  WINPR_ASSERT(nla);
472
473
0
  if (nla_client_init(nla) < 1)
474
0
    return -1;
475
476
0
  if (nla_get_state(nla) != NLA_STATE_INITIAL)
477
0
    return -1;
478
479
  /*
480
   * from tspkg.dll: 0x00000132
481
   * ISC_REQ_MUTUAL_AUTH
482
   * ISC_REQ_CONFIDENTIALITY
483
   * ISC_REQ_USE_SESSION_KEY
484
   * ISC_REQ_ALLOCATE_MEMORY
485
   */
486
0
  credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
487
488
0
  const int rc = credssp_auth_authenticate(nla->auth);
489
490
0
  switch (rc)
491
0
  {
492
0
    case 0:
493
0
      if (!nla_send(nla))
494
0
        return -1;
495
0
      nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
496
0
      break;
497
0
    case 1:
498
0
      if (credssp_auth_have_output_token(nla->auth))
499
0
      {
500
0
        if (!nla_send(nla))
501
0
          return -1;
502
0
      }
503
0
      nla_set_state(nla, NLA_STATE_FINAL);
504
0
      break;
505
0
    default:
506
0
      switch (credssp_auth_sspi_error(nla->auth))
507
0
      {
508
0
        case SEC_E_LOGON_DENIED:
509
0
        case SEC_E_NO_CREDENTIALS:
510
0
          freerdp_set_last_error_log(nla->rdpcontext,
511
0
                                     FREERDP_ERROR_CONNECT_LOGON_FAILURE);
512
0
          break;
513
0
        default:
514
0
          break;
515
0
      }
516
0
      return -1;
517
0
  }
518
519
0
  return 1;
520
0
}
521
522
static int nla_client_recv_nego_token(rdpNla* nla)
523
0
{
524
0
  credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
525
0
  const int rc = credssp_auth_authenticate(nla->auth);
526
527
0
  switch (rc)
528
0
  {
529
0
    case 0:
530
0
      if (!nla_send(nla))
531
0
        return -1;
532
0
      break;
533
0
    case 1: /* completed */
534
0
    {
535
0
      int res = -1;
536
0
      if (nla->peerVersion < 5)
537
0
        res = nla_encrypt_public_key_echo(nla);
538
0
      else
539
0
        res = nla_encrypt_public_key_hash(nla);
540
541
0
      if (!res)
542
0
        return -1;
543
544
0
      if (!nla_send(nla))
545
0
        return -1;
546
547
0
      nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
548
0
    }
549
0
    break;
550
551
0
    default:
552
0
      return -1;
553
0
  }
554
555
0
  return 1;
556
0
}
557
558
static int nla_client_recv_pub_key_auth(rdpNla* nla)
559
0
{
560
0
  BOOL rc = FALSE;
561
562
0
  WINPR_ASSERT(nla);
563
564
  /* Verify Server Public Key Echo */
565
0
  if (nla->peerVersion < 5)
566
0
    rc = nla_decrypt_public_key_echo(nla);
567
0
  else
568
0
    rc = nla_decrypt_public_key_hash(nla);
569
570
0
  sspi_SecBufferFree(&nla->pubKeyAuth);
571
572
0
  if (!rc)
573
0
    return -1;
574
575
  /* Send encrypted credentials */
576
0
  rc = nla_encrypt_ts_credentials(nla);
577
0
  if (!rc)
578
0
    return -1;
579
580
0
  if (!nla_send(nla))
581
0
    return -1;
582
583
0
  if (nla->earlyUserAuth)
584
0
  {
585
0
    transport_set_early_user_auth_mode(nla->transport, TRUE);
586
0
    nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
587
0
  }
588
0
  else
589
0
    nla_set_state(nla, NLA_STATE_AUTH_INFO);
590
0
  return 1;
591
0
}
592
593
static int nla_client_recv_early_user_auth(rdpNla* nla)
594
0
{
595
0
  WINPR_ASSERT(nla);
596
597
0
  transport_set_early_user_auth_mode(nla->transport, FALSE);
598
0
  nla_set_state(nla, NLA_STATE_AUTH_INFO);
599
0
  return 1;
600
0
}
601
602
static int nla_client_recv(rdpNla* nla)
603
16
{
604
16
  WINPR_ASSERT(nla);
605
606
16
  switch (nla_get_state(nla))
607
16
  {
608
0
    case NLA_STATE_NEGO_TOKEN:
609
0
      return nla_client_recv_nego_token(nla);
610
611
0
    case NLA_STATE_PUB_KEY_AUTH:
612
0
      return nla_client_recv_pub_key_auth(nla);
613
614
0
    case NLA_STATE_EARLY_USER_AUTH:
615
0
      return nla_client_recv_early_user_auth(nla);
616
617
0
    case NLA_STATE_FINAL:
618
16
    default:
619
16
      WLog_ERR(TAG, "NLA in invalid client receive state %s",
620
16
               nla_get_state_str(nla_get_state(nla)));
621
16
      return -1;
622
16
  }
623
16
}
624
625
static int nla_client_authenticate(rdpNla* nla)
626
0
{
627
0
  int rc = -1;
628
629
0
  WINPR_ASSERT(nla);
630
631
0
  wStream* s = Stream_New(NULL, 4096);
632
633
0
  if (!s)
634
0
  {
635
0
    WLog_ERR(TAG, "Stream_New failed!");
636
0
    return -1;
637
0
  }
638
639
0
  if (nla_client_begin(nla) < 1)
640
0
    goto fail;
641
642
0
  while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
643
0
  {
644
0
    Stream_SetPosition(s, 0);
645
0
    const int status = transport_read_pdu(nla->transport, s);
646
647
0
    if (status < 0)
648
0
    {
649
0
      WLog_ERR(TAG, "nla_client_authenticate failure");
650
0
      goto fail;
651
0
    }
652
653
0
    const int status2 = nla_recv_pdu(nla, s);
654
655
0
    if (status2 < 0)
656
0
      goto fail;
657
0
  }
658
659
0
  rc = 1;
660
0
fail:
661
0
  Stream_Free(s, TRUE);
662
0
  return rc;
663
0
}
664
665
/**
666
 * Initialize NTLMSSP authentication module (server).
667
 */
668
669
static int nla_server_init(rdpNla* nla)
670
0
{
671
0
  WINPR_ASSERT(nla);
672
673
0
  const BYTE* data = NULL;
674
0
  DWORD length = 0;
675
0
  if (!transport_get_public_key(nla->transport, &data, &length))
676
0
  {
677
0
    WLog_ERR(TAG, "Failed to get public key");
678
0
    return -1;
679
0
  }
680
681
0
  if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
682
0
  {
683
0
    WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
684
0
    return -1;
685
0
  }
686
687
0
  if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, NULL))
688
0
    return -1;
689
690
0
  if (!credssp_auth_setup_server(nla->auth))
691
0
    return -1;
692
693
0
  nla_set_state(nla, NLA_STATE_INITIAL);
694
0
  return 1;
695
0
}
696
697
static wStream* nla_server_recv_stream(rdpNla* nla)
698
0
{
699
0
  wStream* s = NULL;
700
0
  int status = -1;
701
702
0
  WINPR_ASSERT(nla);
703
704
0
  s = Stream_New(NULL, 4096);
705
706
0
  if (!s)
707
0
    goto fail;
708
709
0
  status = transport_read_pdu(nla->transport, s);
710
711
0
fail:
712
0
  if (status < 0)
713
0
  {
714
0
    WLog_ERR(TAG, "nla_recv() error: %d", status);
715
0
    Stream_Free(s, TRUE);
716
0
    return NULL;
717
0
  }
718
719
0
  return s;
720
0
}
721
722
static BOOL nla_server_recv_credentials(rdpNla* nla)
723
0
{
724
0
  WINPR_ASSERT(nla);
725
726
0
  if (nla_server_recv(nla) < 0)
727
0
    return FALSE;
728
729
0
  if (!nla_decrypt_ts_credentials(nla))
730
0
    return FALSE;
731
732
0
  if (!nla_impersonate(nla))
733
0
    return FALSE;
734
735
0
  if (!nla_revert_to_self(nla))
736
0
    return FALSE;
737
738
0
  return TRUE;
739
0
}
740
741
/**
742
 * Authenticate with client using CredSSP (server).
743
 * @param nla The NLA instance to use
744
 *
745
 * @return 1 if authentication is successful
746
 */
747
748
static int nla_server_authenticate(rdpNla* nla)
749
0
{
750
0
  int ret = -1;
751
752
0
  WINPR_ASSERT(nla);
753
754
0
  if (nla_server_init(nla) < 1)
755
0
    goto fail;
756
757
  /*
758
   * from tspkg.dll: 0x00000112
759
   * ASC_REQ_MUTUAL_AUTH
760
   * ASC_REQ_CONFIDENTIALITY
761
   * ASC_REQ_ALLOCATE_MEMORY
762
   */
763
0
  credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
764
0
                                        ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
765
0
                                        ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
766
767
  /* Client is starting, here es the state machine:
768
   *
769
   *  -- NLA_STATE_INITIAL  --> NLA_STATE_INITIAL
770
   * ----->> sending...
771
   *    ----->> protocol version 6
772
   *    ----->> nego token
773
   *    ----->> client nonce
774
   * <<----- receiving...
775
   *    <<----- protocol version 6
776
   *    <<----- nego token
777
   * ----->> sending...
778
   *    ----->> protocol version 6
779
   *    ----->> nego token
780
   *    ----->> public key auth
781
   *    ----->> client nonce
782
   * -- NLA_STATE_NEGO_TOKEN  --> NLA_STATE_PUB_KEY_AUTH
783
   * <<----- receiving...
784
   *    <<----- protocol version 6
785
   *    <<----- public key info
786
   * ----->> sending...
787
   *    ----->> protocol version 6
788
   *    ----->> auth info
789
   *    ----->> client nonce
790
   * -- NLA_STATE_PUB_KEY_AUTH  --> NLA_STATE
791
   */
792
793
0
  while (TRUE)
794
0
  {
795
0
    int res = -1;
796
797
0
    if (nla_server_recv(nla) < 0)
798
0
      goto fail;
799
800
0
    WLog_DBG(TAG, "Receiving Authentication Token");
801
0
    credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
802
803
0
    res = credssp_auth_authenticate(nla->auth);
804
805
0
    if (res == -1)
806
0
    {
807
      /* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
808
         unfortunately does not map directly to the corresponding NTSTATUS values
809
       */
810
0
      switch (GetLastError())
811
0
      {
812
0
        case ERROR_PASSWORD_MUST_CHANGE:
813
0
          nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
814
0
          break;
815
816
0
        case ERROR_PASSWORD_EXPIRED:
817
0
          nla->errorCode = STATUS_PASSWORD_EXPIRED;
818
0
          break;
819
820
0
        case ERROR_ACCOUNT_DISABLED:
821
0
          nla->errorCode = STATUS_ACCOUNT_DISABLED;
822
0
          break;
823
824
0
        default:
825
0
          nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
826
0
          break;
827
0
      }
828
829
0
      (void)nla_send(nla);
830
      /* Access Denied */
831
0
      goto fail;
832
0
    }
833
834
0
    if (res == 1)
835
0
    {
836
      /* Process final part of the nego token exchange */
837
0
      if (credssp_auth_have_output_token(nla->auth))
838
0
      {
839
0
        if (!nla_send(nla))
840
0
          goto fail;
841
842
0
        if (nla_server_recv(nla) < 0)
843
0
          goto fail;
844
845
0
        WLog_DBG(TAG, "Receiving pubkey Token");
846
0
      }
847
848
0
      if (nla->peerVersion < 5)
849
0
        res = nla_decrypt_public_key_echo(nla);
850
0
      else
851
0
        res = nla_decrypt_public_key_hash(nla);
852
853
0
      if (!res)
854
0
        goto fail;
855
856
      /* Clear nego token buffer or we will send it again to the client */
857
0
      sspi_SecBufferFree(&nla->negoToken);
858
859
0
      if (nla->peerVersion < 5)
860
0
        res = nla_encrypt_public_key_echo(nla);
861
0
      else
862
0
        res = nla_encrypt_public_key_hash(nla);
863
864
0
      if (!res)
865
0
        goto fail;
866
0
    }
867
868
    /* send authentication token */
869
0
    WLog_DBG(TAG, "Sending Authentication Token");
870
871
0
    if (!nla_send(nla))
872
0
      goto fail;
873
874
0
    if (res == 1)
875
0
    {
876
0
      ret = 1;
877
0
      break;
878
0
    }
879
0
  }
880
881
  /* Receive encrypted credentials */
882
0
  if (!nla_server_recv_credentials(nla))
883
0
    ret = -1;
884
885
0
fail:
886
0
  nla_buffer_free(nla);
887
0
  return ret;
888
0
}
889
890
/**
891
 * Authenticate using CredSSP.
892
 * @param nla The NLA instance to use
893
 *
894
 * @return 1 if authentication is successful
895
 */
896
897
int nla_authenticate(rdpNla* nla)
898
0
{
899
0
  WINPR_ASSERT(nla);
900
901
0
  if (nla->server)
902
0
    return nla_server_authenticate(nla);
903
0
  else
904
0
    return nla_client_authenticate(nla);
905
0
}
906
907
static void ap_integer_increment_le(BYTE* number, size_t size)
908
0
{
909
0
  WINPR_ASSERT(number || (size == 0));
910
911
0
  for (size_t index = 0; index < size; index++)
912
0
  {
913
0
    if (number[index] < 0xFF)
914
0
    {
915
0
      number[index]++;
916
0
      break;
917
0
    }
918
0
    else
919
0
    {
920
0
      number[index] = 0;
921
0
      continue;
922
0
    }
923
0
  }
924
0
}
925
926
static void ap_integer_decrement_le(BYTE* number, size_t size)
927
0
{
928
0
  WINPR_ASSERT(number || (size == 0));
929
930
0
  for (size_t index = 0; index < size; index++)
931
0
  {
932
0
    if (number[index] > 0)
933
0
    {
934
0
      number[index]--;
935
0
      break;
936
0
    }
937
0
    else
938
0
    {
939
0
      number[index] = 0xFF;
940
0
      continue;
941
0
    }
942
0
  }
943
0
}
944
945
BOOL nla_encrypt_public_key_echo(rdpNla* nla)
946
0
{
947
0
  BOOL status = FALSE;
948
949
0
  WINPR_ASSERT(nla);
950
951
0
  sspi_SecBufferFree(&nla->pubKeyAuth);
952
0
  if (nla->server)
953
0
  {
954
0
    SecBuffer buf = { 0 };
955
0
    if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
956
0
      return FALSE;
957
0
    ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
958
0
    status = credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, NULL, nla->sendSeqNum++);
959
0
    sspi_SecBufferFree(&buf);
960
0
  }
961
0
  else
962
0
  {
963
0
    status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth, NULL,
964
0
                                  nla->sendSeqNum++);
965
0
  }
966
967
0
  return status;
968
0
}
969
970
BOOL nla_encrypt_public_key_hash(rdpNla* nla)
971
0
{
972
0
  BOOL status = FALSE;
973
0
  WINPR_DIGEST_CTX* sha256 = NULL;
974
0
  SecBuffer buf = { 0 };
975
976
0
  WINPR_ASSERT(nla);
977
978
0
  const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
979
0
  const size_t hashSize =
980
0
      nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
981
982
0
  if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
983
0
    return FALSE;
984
985
  /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
986
0
  if (!(sha256 = winpr_Digest_New()))
987
0
    goto out;
988
989
0
  if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
990
0
    goto out;
991
992
  /* include trailing \0 from hashMagic */
993
0
  if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
994
0
    goto out;
995
996
0
  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
997
0
    goto out;
998
999
  /* SubjectPublicKey */
1000
0
  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1001
0
    goto out;
1002
1003
0
  if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1004
0
    goto out;
1005
1006
0
  sspi_SecBufferFree(&nla->pubKeyAuth);
1007
0
  if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, NULL, nla->sendSeqNum++))
1008
0
    goto out;
1009
1010
0
  status = TRUE;
1011
1012
0
out:
1013
0
  winpr_Digest_Free(sha256);
1014
0
  sspi_SecBufferFree(&buf);
1015
0
  return status;
1016
0
}
1017
1018
BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1019
0
{
1020
0
  BOOL status = FALSE;
1021
0
  SecBuffer public_key = { 0 };
1022
1023
0
  if (!nla)
1024
0
    goto fail;
1025
1026
0
  if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1027
0
    return FALSE;
1028
1029
0
  if (!nla->server)
1030
0
  {
1031
    /* server echos the public key +1 */
1032
0
    ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1033
0
  }
1034
1035
0
  if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1036
0
      memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1037
0
  {
1038
0
    WLog_ERR(TAG, "Could not verify server's public key echo");
1039
#if defined(WITH_DEBUG_NLA)
1040
    WLog_ERR(TAG, "Expected (length = %" PRIu32 "):", nla->PublicKey.cbBuffer);
1041
    winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1042
    WLog_ERR(TAG, "Actual (length = %" PRIu32 "):", public_key.cbBuffer);
1043
    winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1044
#endif
1045
    /* DO NOT SEND CREDENTIALS! */
1046
0
    goto fail;
1047
0
  }
1048
1049
0
  status = TRUE;
1050
0
fail:
1051
0
  sspi_SecBufferFree(&public_key);
1052
0
  return status;
1053
0
}
1054
1055
BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1056
0
{
1057
0
  WINPR_DIGEST_CTX* sha256 = NULL;
1058
0
  BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = { 0 };
1059
0
  BOOL status = FALSE;
1060
1061
0
  WINPR_ASSERT(nla);
1062
1063
0
  const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1064
0
  const size_t hashSize =
1065
0
      nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1066
0
  SecBuffer hash = { 0 };
1067
1068
0
  if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1069
0
    return FALSE;
1070
1071
  /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1072
0
  if (!(sha256 = winpr_Digest_New()))
1073
0
    goto fail;
1074
1075
0
  if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1076
0
    goto fail;
1077
1078
  /* include trailing \0 from hashMagic */
1079
0
  if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1080
0
    goto fail;
1081
1082
0
  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1083
0
    goto fail;
1084
1085
  /* SubjectPublicKey */
1086
0
  if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1087
0
    goto fail;
1088
1089
0
  if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1090
0
    goto fail;
1091
1092
  /* verify hash */
1093
0
  if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1094
0
      memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1095
0
  {
1096
0
    WLog_ERR(TAG, "Could not verify server's hash");
1097
    /* DO NOT SEND CREDENTIALS! */
1098
0
    goto fail;
1099
0
  }
1100
1101
0
  status = TRUE;
1102
0
fail:
1103
0
  winpr_Digest_Free(sha256);
1104
0
  sspi_SecBufferFree(&hash);
1105
0
  return status;
1106
0
}
1107
1108
static BOOL set_creds_octetstring_to_settings(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1109
                                              BOOL optional, FreeRDP_Settings_Keys_String settingId,
1110
                                              rdpSettings* settings)
1111
0
{
1112
0
  if (optional)
1113
0
  {
1114
0
    WinPrAsn1_tagId itemTag = 0;
1115
0
    if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != tagId))
1116
0
      return TRUE;
1117
0
  }
1118
1119
0
  BOOL error = FALSE;
1120
0
  WinPrAsn1_OctetString value;
1121
  /* note: not checking "error" value, as the not present optional item case is handled above
1122
   *       if the function fails it's because of a real error not because the item is not present
1123
   */
1124
0
  if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1125
0
    return FALSE;
1126
1127
0
  return freerdp_settings_set_string_from_utf16N(settings, settingId, (const WCHAR*)value.data,
1128
0
                                                 value.len / sizeof(WCHAR));
1129
0
}
1130
1131
static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* settings)
1132
0
{
1133
0
  BOOL error = FALSE;
1134
1135
  /* keySpec [0] INTEGER */
1136
0
  WinPrAsn1_INTEGER keyspec = 0;
1137
0
  if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1138
0
    return FALSE;
1139
0
  settings->KeySpec = (UINT32)keyspec;
1140
1141
  /* cardName [1] OCTET STRING OPTIONAL */
1142
0
  if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1143
0
    return FALSE;
1144
1145
  /* readerName [2] OCTET STRING OPTIONAL */
1146
0
  if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1147
0
    return FALSE;
1148
1149
  /* containerName [3] OCTET STRING OPTIONAL */
1150
0
  if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1151
0
    return FALSE;
1152
1153
  /* cspName [4] OCTET STRING OPTIONAL */
1154
0
  return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1155
0
}
1156
1157
static BOOL nla_read_KERB_TICKET_LOGON(rdpNla* nla, wStream* s, KERB_TICKET_LOGON* ticket)
1158
0
{
1159
0
  WINPR_ASSERT(nla);
1160
1161
0
  if (!ticket)
1162
0
    return FALSE;
1163
1164
  /* mysterious extra 16 bytes before TGS/TGT content */
1165
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1166
0
    return FALSE;
1167
1168
0
  Stream_Read_UINT32(s, ticket->MessageType);
1169
0
  Stream_Read_UINT32(s, ticket->Flags);
1170
0
  Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1171
0
  Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1172
1173
0
  if (ticket->MessageType != KerbTicketLogon)
1174
0
  {
1175
0
    WLog_ERR(TAG, "Not a KerbTicketLogon");
1176
0
    return FALSE;
1177
0
  }
1178
1179
0
  if (!Stream_CheckAndLogRequiredLength(
1180
0
          TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1181
0
    return FALSE;
1182
1183
  /* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
1184
0
  Stream_Seek(s, 16);
1185
1186
  /*WLog_INFO(TAG, "TGS");
1187
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
1188
0
  ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1189
0
  Stream_Seek(s, ticket->ServiceTicketLength);
1190
1191
  /*WLog_INFO(TAG, "TGT");
1192
  winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
1193
                ticket->TicketGrantingTicketLength);*/
1194
0
  ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1195
0
  return TRUE;
1196
0
}
1197
1198
/** @brief kind of RCG credentials */
1199
typedef enum
1200
{
1201
  RCG_TYPE_KERB,
1202
  RCG_TYPE_NTLM
1203
} RemoteGuardPackageCredType;
1204
1205
static BOOL nla_read_TSRemoteGuardPackageCred(rdpNla* nla, WinPrAsn1Decoder* dec,
1206
                                              RemoteGuardPackageCredType* credsType,
1207
                                              wStream* payload)
1208
0
{
1209
0
  WinPrAsn1_OctetString packageName = { 0 };
1210
0
  WinPrAsn1_OctetString credBuffer = { 0 };
1211
0
  BOOL error = FALSE;
1212
0
  char packageNameStr[100] = { 0 };
1213
1214
  /* packageName [0] OCTET STRING */
1215
0
  if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1216
0
    return TRUE;
1217
1218
0
  ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
1219
0
                         packageNameStr, 100);
1220
0
  WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1221
1222
  /* credBuffer [1] OCTET STRING, */
1223
0
  if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1224
0
    return TRUE;
1225
1226
0
  if (_stricmp(packageNameStr, "Kerberos") == 0)
1227
0
  {
1228
0
    *credsType = RCG_TYPE_KERB;
1229
0
  }
1230
0
  else if (_stricmp(packageNameStr, "NTLM") == 0)
1231
0
  {
1232
0
    *credsType = RCG_TYPE_NTLM;
1233
0
  }
1234
0
  else
1235
0
  {
1236
0
    WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1237
0
    return FALSE;
1238
0
  }
1239
1240
0
  Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1241
0
  return TRUE;
1242
0
}
1243
1244
/** @brief kind of TSCreds */
1245
typedef enum
1246
{
1247
  TSCREDS_INVALID = 0,
1248
  TSCREDS_USER_PASSWD = 1,
1249
  TSCREDS_SMARTCARD = 2,
1250
  TSCREDS_REMOTEGUARD = 6
1251
} TsCredentialsType;
1252
1253
static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1254
0
{
1255
0
  WinPrAsn1Decoder dec = { 0 };
1256
0
  WinPrAsn1Decoder dec2 = { 0 };
1257
0
  WinPrAsn1_OctetString credentials = { 0 };
1258
0
  BOOL error = FALSE;
1259
0
  WinPrAsn1_INTEGER credType = -1;
1260
0
  BOOL ret = TRUE;
1261
1262
0
  WINPR_ASSERT(nla);
1263
0
  WINPR_ASSERT(data);
1264
1265
0
  WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1266
1267
  /* TSCredentials */
1268
0
  if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1269
0
    return FALSE;
1270
0
  dec = dec2;
1271
1272
  /* credType [0] INTEGER */
1273
0
  if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1274
0
    return FALSE;
1275
1276
  /* credentials [1] OCTET STRING */
1277
0
  if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1278
0
    return FALSE;
1279
1280
0
  WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1281
1282
0
  rdpSettings* settings = nla->rdpcontext->settings;
1283
0
  if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1284
0
      credType != TSCREDS_REMOTEGUARD)
1285
0
  {
1286
0
    WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1287
0
    return FALSE;
1288
0
  }
1289
1290
0
  switch (credType)
1291
0
  {
1292
0
    case TSCREDS_USER_PASSWD:
1293
0
    {
1294
      /* TSPasswordCreds */
1295
0
      if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1296
0
        return FALSE;
1297
0
      dec = dec2;
1298
1299
      /* domainName [0] OCTET STRING */
1300
0
      if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1301
0
        return FALSE;
1302
1303
      /* userName [1] OCTET STRING */
1304
0
      if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1305
0
        return FALSE;
1306
1307
      /* password [2] OCTET STRING */
1308
0
      return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1309
0
    }
1310
0
    case TSCREDS_SMARTCARD:
1311
0
    {
1312
      /* TSSmartCardCreds */
1313
0
      if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1314
0
        return FALSE;
1315
0
      dec = dec2;
1316
1317
      /* pin [0] OCTET STRING, */
1318
0
      if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1319
0
        return FALSE;
1320
0
      settings->PasswordIsSmartcardPin = TRUE;
1321
1322
      /* cspData [1] TSCspDataDetail */
1323
0
      WinPrAsn1Decoder cspDetails = { 0 };
1324
0
      if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1325
0
        return FALSE;
1326
0
      if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1327
0
        return FALSE;
1328
1329
      /* userHint [2] OCTET STRING OPTIONAL */
1330
0
      if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1331
0
        return FALSE;
1332
1333
      /* domainHint [3] OCTET STRING OPTIONAL */
1334
0
      return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1335
0
    }
1336
0
    case TSCREDS_REMOTEGUARD:
1337
0
    {
1338
      /* TSRemoteGuardCreds */
1339
0
      if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1340
0
        return FALSE;
1341
1342
      /* logonCred[0] TSRemoteGuardPackageCred */
1343
0
      KERB_TICKET_LOGON kerbLogon = { 0 };
1344
0
      WinPrAsn1Decoder logonCredsSeq = { 0 };
1345
0
      if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1346
0
        return FALSE;
1347
1348
0
      RemoteGuardPackageCredType logonCredsType = { 0 };
1349
0
      wStream logonPayload = { 0 };
1350
0
      if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1351
0
                                             &logonPayload))
1352
0
        return FALSE;
1353
0
      if (logonCredsType != RCG_TYPE_KERB)
1354
0
      {
1355
0
        WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1356
0
        return FALSE;
1357
0
      }
1358
1359
0
      if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1360
0
      {
1361
0
        WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1362
0
        return FALSE;
1363
0
      }
1364
1365
      /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1366
0
      MSV1_0_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
1367
0
      WinPrAsn1Decoder suppCredsSeq = { 0 };
1368
1369
0
      if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq))
1370
0
      {
1371
0
        WinPrAsn1Decoder ntlmCredsSeq = { 0 };
1372
0
        if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1373
0
          return FALSE;
1374
1375
0
        RemoteGuardPackageCredType suppCredsType = { 0 };
1376
0
        wStream ntlmPayload = { 0 };
1377
0
        if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1378
0
                                               &ntlmPayload))
1379
0
          return FALSE;
1380
1381
0
        if (suppCredsType != RCG_TYPE_NTLM)
1382
0
        {
1383
0
          WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1384
0
          return FALSE;
1385
0
        }
1386
1387
        /* TODO: suppCreds = &ntlmCreds; and parse NTLM creds */
1388
0
      }
1389
0
      else if (error)
1390
0
      {
1391
0
        WLog_ERR(TAG, "invalid supplementalCreds");
1392
0
        return FALSE;
1393
0
      }
1394
1395
0
      freerdp_peer* peer = nla->rdpcontext->peer;
1396
0
      ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1397
0
      break;
1398
0
    }
1399
0
    default:
1400
0
      WLog_DBG(TAG, "TSCredentials type " PRIu32 " not supported for now", credType);
1401
0
      ret = FALSE;
1402
0
      break;
1403
0
  }
1404
1405
0
  return ret;
1406
0
}
1407
1408
/**
1409
 * Encode TSCredentials structure.
1410
 * @param nla A pointer to the NLA to use
1411
 *
1412
 * @return \b TRUE for success, \b FALSE otherwise
1413
 */
1414
1415
static BOOL nla_encode_ts_credentials(rdpNla* nla)
1416
0
{
1417
0
  BOOL ret = FALSE;
1418
0
  WinPrAsn1Encoder* enc = NULL;
1419
0
  size_t length = 0;
1420
0
  wStream s = { 0 };
1421
0
  TsCredentialsType credType = TSCREDS_INVALID;
1422
1423
0
  WINPR_ASSERT(nla);
1424
0
  WINPR_ASSERT(nla->rdpcontext);
1425
1426
0
  rdpSettings* settings = nla->rdpcontext->settings;
1427
0
  WINPR_ASSERT(settings);
1428
1429
0
  if (settings->RemoteCredentialGuard)
1430
0
    credType = TSCREDS_REMOTEGUARD;
1431
0
  else if (settings->SmartcardLogon)
1432
0
    credType = TSCREDS_SMARTCARD;
1433
0
  else
1434
0
    credType = TSCREDS_USER_PASSWD;
1435
1436
0
  enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1437
0
  if (!enc)
1438
0
    return FALSE;
1439
1440
  /* TSCredentials */
1441
0
  if (!WinPrAsn1EncSeqContainer(enc))
1442
0
    goto out;
1443
1444
  /* credType [0] INTEGER */
1445
0
  if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1446
0
    goto out;
1447
1448
  /* credentials [1] OCTET STRING */
1449
0
  if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1450
0
    goto out;
1451
1452
0
  switch (credType)
1453
0
  {
1454
0
    case TSCREDS_SMARTCARD:
1455
0
    {
1456
0
      struct
1457
0
      {
1458
0
        WinPrAsn1_tagId tag;
1459
0
        size_t setting_id;
1460
0
      } cspData_fields[] = { { 1, FreeRDP_CardName },
1461
0
                           { 2, FreeRDP_ReaderName },
1462
0
                           { 3, FreeRDP_ContainerName },
1463
0
                           { 4, FreeRDP_CspName } };
1464
0
      WinPrAsn1_OctetString octet_string = { 0 };
1465
1466
      /* TSSmartCardCreds */
1467
0
      if (!WinPrAsn1EncSeqContainer(enc))
1468
0
        goto out;
1469
1470
      /* pin [0] OCTET STRING */
1471
0
      size_t ss = 0;
1472
0
      octet_string.data =
1473
0
          (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1474
0
      octet_string.len = ss * sizeof(WCHAR);
1475
0
      const BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1476
0
      free(octet_string.data);
1477
0
      if (!res)
1478
0
        goto out;
1479
1480
      /* cspData [1] SEQUENCE */
1481
0
      if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1482
0
        goto out;
1483
1484
      /* keySpec [0] INTEGER */
1485
0
      if (!WinPrAsn1EncContextualInteger(
1486
0
              enc, 0, freerdp_settings_get_uint32(settings, FreeRDP_KeySpec)))
1487
0
        goto out;
1488
1489
0
      for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1490
0
      {
1491
0
        size_t len = 0;
1492
1493
0
        octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1494
0
            settings, cspData_fields[i].setting_id, &len);
1495
0
        octet_string.len = len * sizeof(WCHAR);
1496
0
        if (octet_string.len)
1497
0
        {
1498
0
          const BOOL res2 = WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag,
1499
0
                                                              &octet_string) > 0;
1500
0
          free(octet_string.data);
1501
0
          if (!res2)
1502
0
            goto out;
1503
0
        }
1504
0
      }
1505
1506
      /* End cspData */
1507
0
      if (!WinPrAsn1EncEndContainer(enc))
1508
0
        goto out;
1509
1510
      /* End TSSmartCardCreds */
1511
0
      if (!WinPrAsn1EncEndContainer(enc))
1512
0
        goto out;
1513
0
      break;
1514
0
    }
1515
0
    case TSCREDS_USER_PASSWD:
1516
0
    {
1517
0
      WinPrAsn1_OctetString username = { 0 };
1518
0
      WinPrAsn1_OctetString domain = { 0 };
1519
0
      WinPrAsn1_OctetString password = { 0 };
1520
1521
      /* TSPasswordCreds */
1522
0
      if (!WinPrAsn1EncSeqContainer(enc))
1523
0
        goto out;
1524
1525
0
      if (!settings->DisableCredentialsDelegation && nla->identity)
1526
0
      {
1527
0
        username.len = nla->identity->UserLength * sizeof(WCHAR);
1528
0
        username.data = (BYTE*)nla->identity->User;
1529
1530
0
        domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1531
0
        domain.data = (BYTE*)nla->identity->Domain;
1532
1533
0
        password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1534
0
        password.data = (BYTE*)nla->identity->Password;
1535
0
      }
1536
1537
0
      if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1538
0
        goto out;
1539
0
      if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1540
0
        goto out;
1541
0
      if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1542
0
        goto out;
1543
1544
      /* End TSPasswordCreds */
1545
0
      if (!WinPrAsn1EncEndContainer(enc))
1546
0
        goto out;
1547
0
      break;
1548
0
    }
1549
0
    case TSCREDS_REMOTEGUARD:
1550
0
    default:
1551
0
      goto out;
1552
0
  }
1553
1554
  /* End credentials | End TSCredentials */
1555
0
  if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1556
0
    goto out;
1557
1558
0
  if (!WinPrAsn1EncStreamSize(enc, &length))
1559
0
    goto out;
1560
1561
0
  if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1562
0
  {
1563
0
    WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1564
0
    goto out;
1565
0
  }
1566
1567
0
  Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1568
1569
0
  ret = WinPrAsn1EncToStream(enc, &s);
1570
1571
0
out:
1572
0
  WinPrAsn1Encoder_Free(&enc);
1573
0
  return ret;
1574
0
}
1575
1576
static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1577
0
{
1578
0
  WINPR_ASSERT(nla);
1579
1580
0
  if (!nla_encode_ts_credentials(nla))
1581
0
    return FALSE;
1582
1583
0
  sspi_SecBufferFree(&nla->authInfo);
1584
0
  if (!credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, NULL,
1585
0
                            nla->sendSeqNum++))
1586
0
    return FALSE;
1587
1588
0
  return TRUE;
1589
0
}
1590
1591
static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1592
0
{
1593
0
  WINPR_ASSERT(nla);
1594
1595
0
  if (nla->authInfo.cbBuffer < 1)
1596
0
  {
1597
0
    WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1598
0
    return FALSE;
1599
0
  }
1600
1601
0
  sspi_SecBufferFree(&nla->tsCredentials);
1602
0
  if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1603
0
    return FALSE;
1604
1605
0
  if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1606
0
    return FALSE;
1607
1608
0
  return TRUE;
1609
0
}
1610
1611
static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1612
                                   WinPrAsn1_tagId tagId, const char* msg)
1613
0
{
1614
0
  BOOL res = FALSE;
1615
1616
0
  WINPR_ASSERT(enc);
1617
0
  WINPR_ASSERT(buffer);
1618
0
  WINPR_ASSERT(msg);
1619
1620
0
  if (buffer->cbBuffer > 0)
1621
0
  {
1622
0
    size_t rc = 0;
1623
0
    WinPrAsn1_OctetString octet_string = { 0 };
1624
1625
0
    WLog_DBG(TAG, "   ----->> %s", msg);
1626
0
    octet_string.data = buffer->pvBuffer;
1627
0
    octet_string.len = buffer->cbBuffer;
1628
0
    rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1629
0
    if (rc != 0)
1630
0
      res = TRUE;
1631
0
  }
1632
1633
0
  return res;
1634
0
}
1635
1636
static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1637
                                        WinPrAsn1_tagId tagId, const char* msg)
1638
0
{
1639
0
  const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1640
0
  sspi_SecBufferFree(buffer);
1641
0
  return rc;
1642
0
}
1643
1644
/**
1645
 * Send CredSSP message.
1646
 *
1647
 * @param nla A pointer to the NLA to use
1648
 *
1649
 * @return \b TRUE for success, \b FALSE otherwise
1650
 */
1651
1652
BOOL nla_send(rdpNla* nla)
1653
0
{
1654
0
  BOOL rc = FALSE;
1655
0
  wStream* s = NULL;
1656
0
  size_t length = 0;
1657
0
  WinPrAsn1Encoder* enc = NULL;
1658
1659
0
  WINPR_ASSERT(nla);
1660
1661
0
  enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1662
0
  if (!enc)
1663
0
    return FALSE;
1664
1665
  /* TSRequest */
1666
0
  WLog_DBG(TAG, "----->> sending...");
1667
0
  if (!WinPrAsn1EncSeqContainer(enc))
1668
0
    goto fail;
1669
1670
  /* version [0] INTEGER */
1671
0
  WLog_DBG(TAG, "   ----->> protocol version %" PRIu32, nla->version);
1672
0
  if (!WinPrAsn1EncContextualInteger(enc, 0, nla->version))
1673
0
    goto fail;
1674
1675
  /* negoTokens [1] SEQUENCE OF SEQUENCE */
1676
0
  if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
1677
0
  {
1678
0
    const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
1679
1680
0
    if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
1681
0
      goto fail;
1682
1683
    /* negoToken [0] OCTET STRING */
1684
0
    if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
1685
0
      goto fail;
1686
1687
    /* End negoTokens (SEQUENCE OF SEQUENCE) */
1688
0
    if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1689
0
      goto fail;
1690
0
  }
1691
1692
  /* authInfo [2] OCTET STRING */
1693
0
  if (nla->authInfo.cbBuffer > 0)
1694
0
  {
1695
0
    if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
1696
0
      goto fail;
1697
0
  }
1698
1699
  /* pubKeyAuth [3] OCTET STRING */
1700
0
  if (nla->pubKeyAuth.cbBuffer > 0)
1701
0
  {
1702
0
    if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
1703
0
      goto fail;
1704
0
  }
1705
1706
  /* errorCode [4] INTEGER */
1707
0
  if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
1708
0
  {
1709
0
    WLog_DBG(TAG, "   ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1710
0
             nla->errorCode);
1711
0
    if (!WinPrAsn1EncContextualInteger(enc, 4, nla->errorCode))
1712
0
      goto fail;
1713
0
  }
1714
1715
  /* clientNonce [5] OCTET STRING */
1716
0
  if (!nla->server && nla->ClientNonce.cbBuffer > 0)
1717
0
  {
1718
0
    if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
1719
0
      goto fail;
1720
0
  }
1721
1722
  /* End TSRequest */
1723
0
  if (!WinPrAsn1EncEndContainer(enc))
1724
0
    goto fail;
1725
1726
0
  if (!WinPrAsn1EncStreamSize(enc, &length))
1727
0
    goto fail;
1728
1729
0
  s = Stream_New(NULL, length);
1730
0
  if (!s)
1731
0
    goto fail;
1732
1733
0
  if (!WinPrAsn1EncToStream(enc, s))
1734
0
    goto fail;
1735
1736
0
  WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
1737
0
  if (transport_write(nla->transport, s) < 0)
1738
0
    goto fail;
1739
0
  rc = TRUE;
1740
1741
0
fail:
1742
0
  Stream_Free(s, TRUE);
1743
0
  WinPrAsn1Encoder_Free(&enc);
1744
0
  return rc;
1745
0
}
1746
1747
static int nla_decode_ts_request(rdpNla* nla, wStream* s)
1748
13.2k
{
1749
13.2k
  WinPrAsn1Decoder dec = { 0 };
1750
13.2k
  WinPrAsn1Decoder dec2 = { 0 };
1751
13.2k
  BOOL error = FALSE;
1752
13.2k
  WinPrAsn1_tagId tag = { 0 };
1753
13.2k
  WinPrAsn1_INTEGER val = { 0 };
1754
13.2k
  UINT32 version = 0;
1755
1756
13.2k
  WINPR_ASSERT(nla);
1757
13.2k
  WINPR_ASSERT(s);
1758
1759
13.2k
  WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
1760
1761
13.2k
  WLog_DBG(TAG, "<<----- receiving...");
1762
1763
  /* TSRequest */
1764
13.2k
  const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
1765
13.2k
  if (offset == 0)
1766
13.0k
    return -1;
1767
195
  dec = dec2;
1768
1769
  /* version [0] INTEGER */
1770
195
  if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
1771
65
    return -1;
1772
1773
130
  if (!Stream_SafeSeek(s, offset))
1774
0
    return -1;
1775
1776
130
  version = (UINT)val;
1777
130
  WLog_DBG(TAG, "   <<----- protocol version %" PRIu32, version);
1778
1779
130
  if (nla->peerVersion == 0)
1780
130
    nla->peerVersion = version;
1781
1782
  /* if the peer suddenly changed its version - kick it */
1783
130
  if (nla->peerVersion != version)
1784
0
  {
1785
0
    WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
1786
0
             nla->peerVersion, version);
1787
0
    return -1;
1788
0
  }
1789
1790
233
  while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
1791
140
  {
1792
140
    WinPrAsn1Decoder dec3 = { 0 };
1793
140
    WinPrAsn1_OctetString octet_string = { 0 };
1794
1795
140
    switch (tag)
1796
140
    {
1797
3
      case 1:
1798
3
        WLog_DBG(TAG, "   <<----- nego token");
1799
        /* negoTokens [1] SEQUENCE OF SEQUENCE */
1800
3
        if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
1801
3
            (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
1802
3
          return -1;
1803
        /* negoToken [0] OCTET STRING */
1804
0
        if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
1805
0
                                                   FALSE) == 0) &&
1806
0
            error)
1807
0
          return -1;
1808
0
        if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
1809
0
                                            octet_string.len))
1810
0
          return -1;
1811
0
        break;
1812
10
      case 2:
1813
10
        WLog_DBG(TAG, "   <<----- auth info");
1814
        /* authInfo [2] OCTET STRING */
1815
10
        if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1816
6
          return -1;
1817
4
        if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
1818
4
                                            octet_string.len))
1819
0
          return -1;
1820
4
        break;
1821
9
      case 3:
1822
9
        WLog_DBG(TAG, "   <<----- public key auth");
1823
        /* pubKeyAuth [3] OCTET STRING */
1824
9
        if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1825
6
          return -1;
1826
3
        if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
1827
3
                                            octet_string.len))
1828
0
          return -1;
1829
3
        break;
1830
102
      case 4:
1831
        /* errorCode [4] INTEGER */
1832
102
        if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
1833
11
          return -1;
1834
91
        nla->errorCode = (UINT)val;
1835
91
        WLog_DBG(TAG, "   <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1836
91
                 nla->errorCode);
1837
91
        break;
1838
10
      case 5:
1839
10
        WLog_DBG(TAG, "   <<----- client nonce");
1840
        /* clientNonce [5] OCTET STRING */
1841
10
        if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
1842
5
          return -1;
1843
5
        if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
1844
5
                                            octet_string.len))
1845
0
          return -1;
1846
5
        break;
1847
6
      default:
1848
6
        return -1;
1849
140
    }
1850
140
  }
1851
1852
93
  return 1;
1853
130
}
1854
1855
int nla_recv_pdu(rdpNla* nla, wStream* s)
1856
13.2k
{
1857
13.2k
  WINPR_ASSERT(nla);
1858
13.2k
  WINPR_ASSERT(s);
1859
1860
13.2k
  if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
1861
0
  {
1862
0
    UINT32 code = 0;
1863
0
    Stream_Read_UINT32(s, code);
1864
0
    if (code != AUTHZ_SUCCESS)
1865
0
    {
1866
0
      WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
1867
0
      code = FREERDP_ERROR_AUTHENTICATION_FAILED;
1868
0
      freerdp_set_last_error_log(nla->rdpcontext, code);
1869
0
      return -1;
1870
0
    }
1871
0
    else
1872
0
      WLog_DBG(TAG, "Early User Auth active: SUCCESS");
1873
0
  }
1874
13.2k
  else
1875
13.2k
  {
1876
13.2k
    if (nla_decode_ts_request(nla, s) < 1)
1877
13.1k
      return -1;
1878
1879
93
    if (nla->errorCode)
1880
77
    {
1881
77
      UINT32 code = 0;
1882
1883
77
      switch (nla->errorCode)
1884
77
      {
1885
0
        case STATUS_PASSWORD_MUST_CHANGE:
1886
0
          code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
1887
0
          break;
1888
1889
0
        case STATUS_PASSWORD_EXPIRED:
1890
0
          code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
1891
0
          break;
1892
1893
0
        case STATUS_ACCOUNT_DISABLED:
1894
0
          code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
1895
0
          break;
1896
1897
0
        case STATUS_LOGON_FAILURE:
1898
0
          code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
1899
0
          break;
1900
1901
0
        case STATUS_WRONG_PASSWORD:
1902
0
          code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
1903
0
          break;
1904
1905
0
        case STATUS_ACCESS_DENIED:
1906
0
          code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
1907
0
          break;
1908
1909
0
        case STATUS_ACCOUNT_RESTRICTION:
1910
0
          code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
1911
0
          break;
1912
1913
0
        case STATUS_ACCOUNT_LOCKED_OUT:
1914
0
          code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
1915
0
          break;
1916
1917
0
        case STATUS_ACCOUNT_EXPIRED:
1918
0
          code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
1919
0
          break;
1920
1921
0
        case STATUS_LOGON_TYPE_NOT_GRANTED:
1922
0
          code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
1923
0
          break;
1924
1925
77
        default:
1926
77
          WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]",
1927
77
                   NtStatus2Tag(nla->errorCode), nla->errorCode);
1928
77
          code = FREERDP_ERROR_AUTHENTICATION_FAILED;
1929
77
          break;
1930
77
      }
1931
1932
77
      freerdp_set_last_error_log(nla->rdpcontext, code);
1933
77
      return -1;
1934
77
    }
1935
93
  }
1936
1937
16
  return nla_client_recv(nla);
1938
13.2k
}
1939
1940
int nla_server_recv(rdpNla* nla)
1941
0
{
1942
0
  int status = -1;
1943
1944
0
  WINPR_ASSERT(nla);
1945
1946
0
  wStream* s = nla_server_recv_stream(nla);
1947
0
  if (!s)
1948
0
    goto fail;
1949
0
  status = nla_decode_ts_request(nla, s);
1950
1951
0
fail:
1952
0
  Stream_Free(s, TRUE);
1953
0
  return status;
1954
0
}
1955
1956
/**
1957
 * Create new CredSSP state machine.
1958
 *
1959
 * @param context A pointer to the rdp context to use
1960
 * @param transport A pointer to the transport to use
1961
 *
1962
 * @return new CredSSP state machine.
1963
 */
1964
1965
rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
1966
13.2k
{
1967
13.2k
  WINPR_ASSERT(transport);
1968
13.2k
  WINPR_ASSERT(context);
1969
1970
13.2k
  rdpSettings* settings = context->settings;
1971
13.2k
  WINPR_ASSERT(settings);
1972
1973
13.2k
  rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
1974
1975
13.2k
  if (!nla)
1976
0
    return NULL;
1977
1978
13.2k
  nla->rdpcontext = context;
1979
13.2k
  nla->server = settings->ServerMode;
1980
13.2k
  nla->transport = transport;
1981
13.2k
  nla->sendSeqNum = 0;
1982
13.2k
  nla->recvSeqNum = 0;
1983
13.2k
  nla->version = 6;
1984
13.2k
  nla->earlyUserAuth = FALSE;
1985
1986
13.2k
  nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
1987
13.2k
  if (!nla->identity)
1988
0
    goto cleanup;
1989
1990
13.2k
  nla->auth = credssp_auth_new(context);
1991
13.2k
  if (!nla->auth)
1992
0
    goto cleanup;
1993
1994
  /* init to 0 or we end up freeing a bad pointer if the alloc fails */
1995
13.2k
  if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
1996
0
    goto cleanup;
1997
1998
  /* generate random 32-byte nonce */
1999
13.2k
  if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2000
0
    goto cleanup;
2001
2002
13.2k
  return nla;
2003
0
cleanup:
2004
0
  WINPR_PRAGMA_DIAG_PUSH
2005
0
  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2006
0
  nla_free(nla);
2007
0
  WINPR_PRAGMA_DIAG_POP
2008
0
  return NULL;
2009
13.2k
}
2010
2011
/**
2012
 * Free CredSSP state machine.
2013
 * @param nla The NLA instance to free
2014
 */
2015
2016
void nla_free(rdpNla* nla)
2017
66.3k
{
2018
66.3k
  if (!nla)
2019
53.0k
    return;
2020
2021
13.2k
  smartcardCertInfo_Free(nla->smartcardCert);
2022
13.2k
  nla_buffer_free(nla);
2023
13.2k
  sspi_SecBufferFree(&nla->tsCredentials);
2024
13.2k
  credssp_auth_free(nla->auth);
2025
2026
13.2k
  sspi_FreeAuthIdentity(nla->identity);
2027
13.2k
  free(nla->pkinitArgs);
2028
13.2k
  free(nla->identity);
2029
13.2k
  free(nla);
2030
13.2k
}
2031
2032
SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2033
0
{
2034
0
  if (!nla)
2035
0
    return NULL;
2036
2037
0
  return nla->identity;
2038
0
}
2039
2040
NLA_STATE nla_get_state(rdpNla* nla)
2041
13.3k
{
2042
13.3k
  if (!nla)
2043
0
    return NLA_STATE_FINAL;
2044
2045
13.3k
  return nla->state;
2046
13.3k
}
2047
2048
BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2049
0
{
2050
0
  if (!nla)
2051
0
    return FALSE;
2052
2053
0
  WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2054
0
  nla->state = state;
2055
0
  return TRUE;
2056
0
}
2057
2058
BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2059
0
{
2060
0
  if (!credssp_auth_set_spn(nla->auth, service, hostname))
2061
0
    return FALSE;
2062
0
  return TRUE;
2063
0
}
2064
2065
BOOL nla_impersonate(rdpNla* nla)
2066
0
{
2067
0
  return credssp_auth_impersonate(nla->auth);
2068
0
}
2069
2070
BOOL nla_revert_to_self(rdpNla* nla)
2071
0
{
2072
0
  return credssp_auth_revert_to_self(nla->auth);
2073
0
}
2074
2075
const char* nla_get_state_str(NLA_STATE state)
2076
16
{
2077
16
  switch (state)
2078
16
  {
2079
16
    case NLA_STATE_INITIAL:
2080
16
      return "NLA_STATE_INITIAL";
2081
0
    case NLA_STATE_NEGO_TOKEN:
2082
0
      return "NLA_STATE_NEGO_TOKEN";
2083
0
    case NLA_STATE_PUB_KEY_AUTH:
2084
0
      return "NLA_STATE_PUB_KEY_AUTH";
2085
0
    case NLA_STATE_AUTH_INFO:
2086
0
      return "NLA_STATE_AUTH_INFO";
2087
0
    case NLA_STATE_POST_NEGO:
2088
0
      return "NLA_STATE_POST_NEGO";
2089
0
    case NLA_STATE_EARLY_USER_AUTH:
2090
0
      return "NLA_STATE_EARLY_USER_AUTH";
2091
0
    case NLA_STATE_FINAL:
2092
0
      return "NLA_STATE_FINAL";
2093
0
    default:
2094
0
      return "UNKNOWN";
2095
16
  }
2096
16
}
2097
2098
DWORD nla_get_error(rdpNla* nla)
2099
0
{
2100
0
  if (!nla)
2101
0
    return ERROR_INTERNAL_ERROR;
2102
0
  return nla->errorCode;
2103
0
}
2104
2105
UINT32 nla_get_sspi_error(rdpNla* nla)
2106
0
{
2107
0
  WINPR_ASSERT(nla);
2108
0
  return credssp_auth_sspi_error(nla->auth);
2109
0
}