Coverage Report

Created: 2024-05-20 06:11

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