FreeRDP
Loading...
Searching...
No Matches
nla.c
1
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 NLA_AUTH_PKG NEGO_SSP_NAME
58
59typedef enum
60{
61 AUTHZ_SUCCESS = 0x00000000,
62 AUTHZ_ACCESS_DENIED = 0x00000005,
63} AUTHZ_RESULT;
64
108struct rdp_nla
109{
110 BOOL server;
111 NLA_STATE state;
112 ULONG sendSeqNum;
113 ULONG recvSeqNum;
114 rdpContext* rdpcontext;
115 rdpTransport* transport;
116 UINT32 version;
117 UINT32 peerVersion;
118 INT32 errorCode;
119
120 /* Lifetime of buffer nla_new -> nla_free */
121 SecBuffer ClientNonce; /* Depending on protocol version a random nonce or a value read from the
122 server. */
123
124 SecBuffer negoToken;
125 SecBuffer pubKeyAuth;
126 SecBuffer authInfo;
127 SecBuffer PublicKey;
128 SecBuffer tsCredentials;
129
130 SEC_WINNT_AUTH_IDENTITY* identity;
131
132 rdpCredsspAuth* auth;
133 char* pkinitArgs;
134 SmartcardCertInfo* smartcardCert;
135 BYTE certSha1[20];
136 BOOL earlyUserAuth;
137};
138
139static BOOL nla_send(rdpNla* nla);
140static int nla_server_recv(rdpNla* nla);
141static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
142static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
143static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
144static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
145static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
146static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
147
148void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
149{
150 WINPR_ASSERT(nla);
151 WLog_DBG(TAG, "Early User Auth active: %s", earlyUserAuth ? "true" : "false");
152 nla->earlyUserAuth = earlyUserAuth;
153}
154
155static void nla_buffer_free(rdpNla* nla)
156{
157 WINPR_ASSERT(nla);
158 sspi_SecBufferFree(&nla->pubKeyAuth);
159 sspi_SecBufferFree(&nla->authInfo);
160 sspi_SecBufferFree(&nla->negoToken);
161 sspi_SecBufferFree(&nla->ClientNonce);
162 sspi_SecBufferFree(&nla->PublicKey);
163}
164
165static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx, const SecBuffer* buffer)
166{
167 if (!buffer)
168 return FALSE;
169 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
170}
171
172static BOOL nla_sec_buffer_alloc(SecBuffer* buffer, size_t size)
173{
174 WINPR_ASSERT(buffer);
175 sspi_SecBufferFree(buffer);
176 if (size > UINT32_MAX)
177 return FALSE;
178 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
179 return FALSE;
180
181 WINPR_ASSERT(buffer);
182 buffer->BufferType = SECBUFFER_TOKEN;
183 return TRUE;
184}
185
186static BOOL nla_sec_buffer_alloc_from_data(SecBuffer* buffer, const BYTE* data, size_t offset,
187 size_t size)
188{
189 if (!nla_sec_buffer_alloc(buffer, offset + size))
190 return FALSE;
191
192 WINPR_ASSERT(buffer);
193 BYTE* pb = buffer->pvBuffer;
194 memcpy(&pb[offset], data, size);
195 return TRUE;
196}
197
198/* CredSSP Client-To-Server Binding Hash\0 */
199static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
200 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
201 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
202 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
203 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
204
205/* CredSSP Server-To-Client Binding Hash\0 */
206static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
207 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
208 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
209 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
210 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
211
212static const UINT32 NonceLength = 32;
213
214static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
215{
216 BOOL ret = FALSE;
217
218 WINPR_ASSERT(nla);
219 WINPR_ASSERT(nla->rdpcontext);
220
221 rdpSettings* settings = nla->rdpcontext->settings;
222 WINPR_ASSERT(settings);
223
224 if (!settings->SmartcardLogon)
225 return TRUE;
226
227 smartcardCertInfo_Free(nla->smartcardCert);
228
229 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
230 {
231 WLog_ERR(TAG, "unable to get smartcard certificate for logon");
232 return FALSE;
233 }
234
235 if (!settings->CspName)
236 {
237 /* Use KSP instead of legacy CSP — the CSP does not support ECC keys,
238 * which are common on modern PIV smartcards. The KSP supports both RSA and ECC. */
239 if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_CspName,
240 MS_SMART_CARD_KEY_STORAGE_PROVIDER))
241 {
242 WLog_ERR(TAG, "unable to set CSP name");
243 goto out;
244 }
245 }
246
247 if (!settings->ReaderName && nla->smartcardCert->reader)
248 {
249 if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ReaderName,
250 nla->smartcardCert->reader))
251 {
252 WLog_ERR(TAG, "unable to copy reader name");
253 goto out;
254 }
255 }
256
257 if (!settings->ContainerName && nla->smartcardCert->containerName)
258 {
259 if (!freerdp_settings_set_string_from_utf16(settings, FreeRDP_ContainerName,
260 nla->smartcardCert->containerName))
261 {
262 WLog_ERR(TAG, "unable to copy container name");
263 goto out;
264 }
265 }
266
267 /* KSP uses KeySpec=0 for CNG keys; AT_KEYEXCHANGE is only valid for legacy CSP RSA */
268 if (!freerdp_settings_set_uint32(settings, FreeRDP_KeySpec, 0))
269 {
270 WLog_ERR(TAG, "unable to set KeySpec");
271 goto out;
272 }
273
274 WLog_DBG(TAG, "Smartcard logon: Provider='%s' Reader='%s' Container='%s' KeySpec=%" PRIu32,
275 freerdp_settings_get_string(settings, FreeRDP_CspName),
276 freerdp_settings_get_string(settings, FreeRDP_ReaderName),
277 freerdp_settings_get_string(settings, FreeRDP_ContainerName),
278 freerdp_settings_get_uint32(settings, FreeRDP_KeySpec));
279
280 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash, sizeof(nla->certSha1));
281
282 if (nla->smartcardCert->pkinitArgs)
283 {
284 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
285 if (!nla->pkinitArgs)
286 {
287 WLog_ERR(TAG, "unable to copy pkinitArgs");
288 goto out;
289 }
290 }
291
292 ret = TRUE;
293out:
294 return ret;
295}
296
297static BOOL nla_client_setup_identity(rdpNla* nla)
298{
299 BOOL PromptPassword = FALSE;
300
301 WINPR_ASSERT(nla);
302 WINPR_ASSERT(nla->rdpcontext);
303
304 rdpSettings* settings = nla->rdpcontext->settings;
305 WINPR_ASSERT(settings);
306
307 freerdp* instance = nla->rdpcontext->instance;
308 WINPR_ASSERT(instance);
309
310 /* */
311 if ((utils_str_is_empty(settings->Username) ||
312 (utils_str_is_empty(settings->Password) &&
313 utils_str_is_empty((const char*)settings->RedirectionPassword))))
314 {
315 PromptPassword = TRUE;
316 }
317
318 if (PromptPassword && !utils_str_is_empty(settings->Username))
319 {
320 WINPR_SAM* sam = SamOpen(nullptr, TRUE);
321 if (sam)
322 {
323 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
324 WINPR_SAM_ENTRY* entry =
325 SamLookupUserA(sam, settings->Username,
326 userLength + 1 /* ensure '\0' is checked too */, nullptr, 0);
327 if (entry)
328 {
333 PromptPassword = FALSE;
334 SamFreeEntry(sam, entry);
335 }
336
337 SamClose(sam);
338 }
339 }
340
341 if (PromptPassword)
342 {
343 if (settings->RestrictedAdminModeRequired)
344 {
345 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
346 PromptPassword = FALSE;
347 }
348
349 if (settings->RemoteCredentialGuard)
350 PromptPassword = FALSE;
351 }
352
353 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
354 if (PromptPassword)
355 {
356 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
357 {
358 case AUTH_SKIP:
359 case AUTH_SUCCESS:
360 break;
361 case AUTH_CANCELLED:
362 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
363 return FALSE;
364 case AUTH_NO_CREDENTIALS:
365 WLog_INFO(TAG, "No credentials provided - using nullptr identity");
366 break;
367 default:
368 return FALSE;
369 }
370 }
371
372 if (!settings->Username)
373 {
374 sspi_FreeAuthIdentity(nla->identity);
375 free(nla->identity);
376 nla->identity = nullptr;
377 }
378 else if (settings->SmartcardLogon)
379 {
380 if (smartCardLogonWasDisabled)
381 {
382 if (!nla_adjust_settings_from_smartcard(nla))
383 return FALSE;
384 }
385
386 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
387 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
388 sizeof(nla->certSha1)))
389 return FALSE;
390 }
391 else
392 {
393 BOOL usePassword = TRUE;
394
395 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
396 {
397 const WCHAR* wstr =
398 WINPR_PACKED_ALIGN_CAST(const WCHAR*, settings->RedirectionPassword);
399 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength / sizeof(WCHAR));
400
401 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
402 FreeRDP_Domain, wstr, len))
403 return FALSE;
404
405 usePassword = FALSE;
406 }
407
408 if (settings->RestrictedAdminModeRequired)
409 {
410 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
411 {
412 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
413 FreeRDP_Domain, FreeRDP_PasswordHash))
414 return FALSE;
415
416 nla->identity->Flags |= SEC_WINPR_AUTH_IDENTITY_PASSWORD_HASH;
417 usePassword = FALSE;
418 }
419 }
420
421 if (usePassword)
422 {
423 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
424 FreeRDP_Domain, FreeRDP_Password))
425 return FALSE;
426 }
427 }
428
429 return TRUE;
430}
431
432static int nla_client_init(rdpNla* nla)
433{
434 WINPR_ASSERT(nla);
435 WINPR_ASSERT(nla->rdpcontext);
436
437 rdpSettings* settings = nla->rdpcontext->settings;
438 WINPR_ASSERT(settings);
439
440 nla_set_state(nla, NLA_STATE_INITIAL);
441
442 if (!nla_adjust_settings_from_smartcard(nla))
443 return -1;
444
445 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, nullptr))
446 return -1;
447
448 if (!nla_client_setup_identity(nla))
449 return -1;
450
451 const char* hostname = freerdp_settings_get_server_name(settings);
452
453 if (!credssp_auth_setup_client(nla->auth, "TERMSRV", hostname, nla->identity, nla->pkinitArgs))
454 return -1;
455
456 const BYTE* data = nullptr;
457 DWORD length = 0;
458 if (!transport_get_public_key(nla->transport, &data, &length))
459 {
460 WLog_ERR(TAG, "Failed to get public key");
461 return -1;
462 }
463
464 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
465 {
466 WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
467 return -1;
468 }
469
470 return 1;
471}
472
473int nla_client_begin(rdpNla* nla)
474{
475 WINPR_ASSERT(nla);
476
477 if (nla_client_init(nla) < 1)
478 return -1;
479
480 if (nla_get_state(nla) != NLA_STATE_INITIAL)
481 return -1;
482
483 /*
484 * from tspkg.dll: 0x00000132
485 * ISC_REQ_MUTUAL_AUTH
486 * ISC_REQ_CONFIDENTIALITY
487 * ISC_REQ_USE_SESSION_KEY
488 * ISC_REQ_ALLOCATE_MEMORY
489 */
490 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
491
492 const int rc = credssp_auth_authenticate(nla->auth);
493
494 switch (rc)
495 {
496 case 0:
497 if (!nla_send(nla))
498 return -1;
499 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
500 break;
501 case 1:
502 if (credssp_auth_have_output_token(nla->auth))
503 {
504 if (!nla_send(nla))
505 return -1;
506 }
507 nla_set_state(nla, NLA_STATE_FINAL);
508 break;
509 default:
510 switch (credssp_auth_sspi_error(nla->auth))
511 {
512 case SEC_E_LOGON_DENIED:
513 case SEC_E_NO_CREDENTIALS:
514 freerdp_set_last_error_log(nla->rdpcontext,
515 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
516 break;
517 default:
518 break;
519 }
520 return -1;
521 }
522
523 return 1;
524}
525
526static int nla_client_recv_nego_token(rdpNla* nla)
527{
528 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
529 const int rc = credssp_auth_authenticate(nla->auth);
530
531 switch (rc)
532 {
533 case 0:
534 if (!nla_send(nla))
535 return -1;
536 break;
537 case 1: /* completed */
538 {
539 int res = -1;
540 if (nla->peerVersion < 5)
541 res = nla_encrypt_public_key_echo(nla);
542 else
543 res = nla_encrypt_public_key_hash(nla);
544
545 if (!res)
546 return -1;
547
548 if (!nla_send(nla))
549 return -1;
550
551 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
552 }
553 break;
554
555 default:
556 return -1;
557 }
558
559 return 1;
560}
561
562static int nla_client_recv_pub_key_auth(rdpNla* nla)
563{
564 BOOL rc = FALSE;
565
566 WINPR_ASSERT(nla);
567
568 /* Verify Server Public Key Echo */
569 if (nla->peerVersion < 5)
570 rc = nla_decrypt_public_key_echo(nla);
571 else
572 rc = nla_decrypt_public_key_hash(nla);
573
574 sspi_SecBufferFree(&nla->pubKeyAuth);
575
576 if (!rc)
577 return -1;
578
579 /* Send encrypted credentials */
580 rc = nla_encrypt_ts_credentials(nla);
581 if (!rc)
582 return -1;
583
584 if (!nla_send(nla))
585 return -1;
586
587 if (nla->earlyUserAuth)
588 {
589 transport_set_early_user_auth_mode(nla->transport, TRUE);
590 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
591 }
592 else
593 nla_set_state(nla, NLA_STATE_AUTH_INFO);
594 return 1;
595}
596
597static int nla_client_recv_early_user_auth(rdpNla* nla)
598{
599 WINPR_ASSERT(nla);
600
601 transport_set_early_user_auth_mode(nla->transport, FALSE);
602 nla_set_state(nla, NLA_STATE_AUTH_INFO);
603 return 1;
604}
605
606static int nla_client_recv(rdpNla* nla)
607{
608 WINPR_ASSERT(nla);
609
610 switch (nla_get_state(nla))
611 {
612 case NLA_STATE_NEGO_TOKEN:
613 return nla_client_recv_nego_token(nla);
614
615 case NLA_STATE_PUB_KEY_AUTH:
616 return nla_client_recv_pub_key_auth(nla);
617
618 case NLA_STATE_EARLY_USER_AUTH:
619 return nla_client_recv_early_user_auth(nla);
620
621 case NLA_STATE_FINAL:
622 default:
623 WLog_ERR(TAG, "NLA in invalid client receive state %s",
624 nla_get_state_str(nla_get_state(nla)));
625 return -1;
626 }
627}
628
629static int nla_client_authenticate(rdpNla* nla)
630{
631 int rc = -1;
632
633 WINPR_ASSERT(nla);
634
635 wStream* s = Stream_New(nullptr, 4096);
636
637 if (!s)
638 {
639 WLog_ERR(TAG, "Stream_New failed!");
640 return -1;
641 }
642
643 if (nla_client_begin(nla) < 1)
644 goto fail;
645
646 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
647 {
648 Stream_ResetPosition(s);
649 const int status = transport_read_pdu(nla->transport, s);
650
651 if (status < 0)
652 {
653 WLog_ERR(TAG, "nla_client_authenticate failure");
654 goto fail;
655 }
656
657 const int status2 = nla_recv_pdu(nla, s);
658
659 if (status2 < 0)
660 goto fail;
661 }
662
663 rc = 1;
664fail:
665 Stream_Free(s, TRUE);
666 return rc;
667}
668
673static int nla_server_init(rdpNla* nla)
674{
675 WINPR_ASSERT(nla);
676
677 const BYTE* data = nullptr;
678 DWORD length = 0;
679 if (!transport_get_public_key(nla->transport, &data, &length))
680 {
681 WLog_ERR(TAG, "Failed to get public key");
682 return -1;
683 }
684
685 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
686 {
687 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
688 return -1;
689 }
690
691 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, nullptr))
692 return -1;
693
694 if (!credssp_auth_setup_server(nla->auth))
695 return -1;
696
697 nla_set_state(nla, NLA_STATE_INITIAL);
698 return 1;
699}
700
701static wStream* nla_server_recv_stream(rdpNla* nla)
702{
703 wStream* s = nullptr;
704 int status = -1;
705
706 WINPR_ASSERT(nla);
707
708 s = Stream_New(nullptr, 4096);
709
710 if (!s)
711 goto fail;
712
713 status = transport_read_pdu(nla->transport, s);
714
715fail:
716 if (status < 0)
717 {
718 WLog_ERR(TAG, "nla_recv() error: %d", status);
719 Stream_Free(s, TRUE);
720 return nullptr;
721 }
722
723 return s;
724}
725
726static BOOL nla_server_recv_credentials(rdpNla* nla)
727{
728 WINPR_ASSERT(nla);
729
730 if (nla_server_recv(nla) < 0)
731 return FALSE;
732
733 if (!nla_decrypt_ts_credentials(nla))
734 return FALSE;
735
736 if (!nla_impersonate(nla))
737 return FALSE;
738
739 if (!nla_revert_to_self(nla))
740 return FALSE;
741
742 return TRUE;
743}
744
752static int nla_server_authenticate(rdpNla* nla)
753{
754 int ret = -1;
755
756 WINPR_ASSERT(nla);
757
758 if (nla_server_init(nla) < 1)
759 goto fail;
760
761 /*
762 * from tspkg.dll: 0x00000112
763 * ASC_REQ_MUTUAL_AUTH
764 * ASC_REQ_CONFIDENTIALITY
765 * ASC_REQ_ALLOCATE_MEMORY
766 */
767 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
768 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
769 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
770
771 /* Client is starting, here es the state machine:
772 *
773 * -- NLA_STATE_INITIAL --> NLA_STATE_INITIAL
774 * ----->> sending...
775 * ----->> protocol version 6
776 * ----->> nego token
777 * ----->> client nonce
778 * <<----- receiving...
779 * <<----- protocol version 6
780 * <<----- nego token
781 * ----->> sending...
782 * ----->> protocol version 6
783 * ----->> nego token
784 * ----->> public key auth
785 * ----->> client nonce
786 * -- NLA_STATE_NEGO_TOKEN --> NLA_STATE_PUB_KEY_AUTH
787 * <<----- receiving...
788 * <<----- protocol version 6
789 * <<----- public key info
790 * ----->> sending...
791 * ----->> protocol version 6
792 * ----->> auth info
793 * ----->> client nonce
794 * -- NLA_STATE_PUB_KEY_AUTH --> NLA_STATE
795 */
796
797 while (TRUE)
798 {
799 int res = -1;
800
801 if (nla_server_recv(nla) < 0)
802 goto fail;
803
804 WLog_DBG(TAG, "Receiving Authentication Token");
805 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
806
807 res = credssp_auth_authenticate(nla->auth);
808
809 if (res == -1)
810 {
811 /* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
812 unfortunately does not map directly to the corresponding NTSTATUS values
813 */
814 switch (GetLastError())
815 {
816 case ERROR_PASSWORD_MUST_CHANGE:
817 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
818 break;
819
820 case ERROR_PASSWORD_EXPIRED:
821 nla->errorCode = STATUS_PASSWORD_EXPIRED;
822 break;
823
824 case ERROR_ACCOUNT_DISABLED:
825 nla->errorCode = STATUS_ACCOUNT_DISABLED;
826 break;
827
828 default:
829 {
830 nla->errorCode = STATUS_LOGON_FAILURE;
831 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
832 if (sspi != SEC_E_OK)
833 WLog_DBG(TAG, "[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
834 GetSecurityStatusString(sspi));
835 }
836 break;
837 }
838
839 (void)nla_send(nla);
840 /* Access Denied */
841 goto fail;
842 }
843
844 if (res == 1)
845 {
846 /* Process final part of the nego token exchange */
847 if (credssp_auth_have_output_token(nla->auth))
848 {
849 if (!nla_send(nla))
850 goto fail;
851
852 if (nla_server_recv(nla) < 0)
853 goto fail;
854
855 WLog_DBG(TAG, "Receiving pubkey Token");
856 }
857
858 if (nla->peerVersion < 5)
859 res = nla_decrypt_public_key_echo(nla);
860 else
861 res = nla_decrypt_public_key_hash(nla);
862
863 if (!res)
864 goto fail;
865
866 /* Clear nego token buffer or we will send it again to the client */
867 sspi_SecBufferFree(&nla->negoToken);
868
869 if (nla->peerVersion < 5)
870 res = nla_encrypt_public_key_echo(nla);
871 else
872 res = nla_encrypt_public_key_hash(nla);
873
874 if (!res)
875 goto fail;
876 }
877
878 /* send authentication token */
879 WLog_DBG(TAG, "Sending Authentication Token");
880
881 if (!nla_send(nla))
882 goto fail;
883
884 if (res == 1)
885 {
886 ret = 1;
887 break;
888 }
889 }
890
891 /* Receive encrypted credentials */
892 if (!nla_server_recv_credentials(nla))
893 ret = -1;
894
895fail:
896 nla_buffer_free(nla);
897 return ret;
898}
899
907int nla_authenticate(rdpNla* nla)
908{
909 WINPR_ASSERT(nla);
910
911 if (nla->server)
912 return nla_server_authenticate(nla);
913 else
914 return nla_client_authenticate(nla);
915}
916
917static void ap_integer_increment_le(BYTE* number, size_t size)
918{
919 WINPR_ASSERT(number || (size == 0));
920
921 for (size_t index = 0; index < size; index++)
922 {
923 if (number[index] < 0xFF)
924 {
925 number[index]++;
926 break;
927 }
928 else
929 {
930 number[index] = 0;
931 continue;
932 }
933 }
934}
935
936static void ap_integer_decrement_le(BYTE* number, size_t size)
937{
938 WINPR_ASSERT(number || (size == 0));
939
940 for (size_t index = 0; index < size; index++)
941 {
942 if (number[index] > 0)
943 {
944 number[index]--;
945 break;
946 }
947 else
948 {
949 number[index] = 0xFF;
950 continue;
951 }
952 }
953}
954
955BOOL nla_encrypt_public_key_echo(rdpNla* nla)
956{
957 BOOL status = FALSE;
958
959 WINPR_ASSERT(nla);
960
961 sspi_SecBufferFree(&nla->pubKeyAuth);
962 if (nla->server)
963 {
964 SecBuffer buf = WINPR_C_ARRAY_INIT;
965 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
966 return FALSE;
967 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
968 status =
969 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, nullptr, nla->sendSeqNum++);
970 sspi_SecBufferFree(&buf);
971 }
972 else
973 {
974 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth, nullptr,
975 nla->sendSeqNum++);
976 }
977
978 return status;
979}
980
981BOOL nla_encrypt_public_key_hash(rdpNla* nla)
982{
983 BOOL status = FALSE;
984 WINPR_DIGEST_CTX* sha256 = nullptr;
985 SecBuffer buf = WINPR_C_ARRAY_INIT;
986
987 WINPR_ASSERT(nla);
988
989 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
990 const size_t hashSize =
991 nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
992
993 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
994 return FALSE;
995
996 /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
997 if (!(sha256 = winpr_Digest_New()))
998 goto out;
999
1000 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1001 goto out;
1002
1003 /* include trailing \0 from hashMagic */
1004 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1005 goto out;
1006
1007 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1008 goto out;
1009
1010 /* SubjectPublicKey */
1011 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1012 goto out;
1013
1014 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1015 goto out;
1016
1017 sspi_SecBufferFree(&nla->pubKeyAuth);
1018 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, nullptr, nla->sendSeqNum++))
1019 goto out;
1020
1021 status = TRUE;
1022
1023out:
1024 winpr_Digest_Free(sha256);
1025 sspi_SecBufferFree(&buf);
1026 return status;
1027}
1028
1029BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1030{
1031 BOOL status = FALSE;
1032 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1033
1034 if (!nla)
1035 goto fail;
1036
1037 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1038 return FALSE;
1039
1040 if (!nla->server)
1041 {
1042 /* server echos the public key +1 */
1043 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1044 }
1045
1046 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1047 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1048 {
1049 WLog_ERR(TAG, "Could not verify server's public key echo");
1050#if defined(WITH_DEBUG_NLA)
1051 WLog_ERR(TAG, "Expected (length = %" PRIu32 "):", nla->PublicKey.cbBuffer);
1052 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1053 WLog_ERR(TAG, "Actual (length = %" PRIu32 "):", public_key.cbBuffer);
1054 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1055#endif
1056 /* DO NOT SEND CREDENTIALS! */
1057 goto fail;
1058 }
1059
1060 status = TRUE;
1061fail:
1062 sspi_SecBufferFree(&public_key);
1063 return status;
1064}
1065
1066BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1067{
1068 WINPR_DIGEST_CTX* sha256 = nullptr;
1069 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1070 BOOL status = FALSE;
1071
1072 WINPR_ASSERT(nla);
1073
1074 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1075 const size_t hashSize =
1076 nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1077 SecBuffer hash = WINPR_C_ARRAY_INIT;
1078
1079 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1080 return FALSE;
1081
1082 /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1083 if (!(sha256 = winpr_Digest_New()))
1084 goto fail;
1085
1086 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1087 goto fail;
1088
1089 /* include trailing \0 from hashMagic */
1090 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1091 goto fail;
1092
1093 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1094 goto fail;
1095
1096 /* SubjectPublicKey */
1097 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1098 goto fail;
1099
1100 if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1101 goto fail;
1102
1103 /* verify hash */
1104 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1105 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1106 {
1107 WLog_ERR(TAG, "Could not verify server's hash");
1108 /* DO NOT SEND CREDENTIALS! */
1109 goto fail;
1110 }
1111
1112 status = TRUE;
1113fail:
1114 winpr_Digest_Free(sha256);
1115 sspi_SecBufferFree(&hash);
1116 return status;
1117}
1118
1119static BOOL set_creds_octetstring_to_settings(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1120 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1121 rdpSettings* settings)
1122{
1123 if (optional)
1124 {
1125 WinPrAsn1_tagId itemTag = 0;
1126 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1127 return TRUE;
1128 }
1129
1130 BOOL error = FALSE;
1132 /* note: not checking "error" value, as the not present optional item case is handled above
1133 * if the function fails it's because of a real error not because the item is not present
1134 */
1135 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1136 return FALSE;
1137
1139 settings, settingId, WINPR_PACKED_ALIGN_CAST(const WCHAR*, value.data),
1140 value.len / sizeof(WCHAR));
1141}
1142
1143static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* settings)
1144{
1145 BOOL error = FALSE;
1146
1147 /* keySpec [0] INTEGER */
1148 WinPrAsn1_INTEGER keyspec = 0;
1149 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1150 return FALSE;
1151 settings->KeySpec = (UINT32)keyspec;
1152
1153 /* cardName [1] OCTET STRING OPTIONAL */
1154 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1155 return FALSE;
1156
1157 /* readerName [2] OCTET STRING OPTIONAL */
1158 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1159 return FALSE;
1160
1161 /* containerName [3] OCTET STRING OPTIONAL */
1162 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1163 return FALSE;
1164
1165 /* cspName [4] OCTET STRING OPTIONAL */
1166 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1167}
1168
1169static BOOL nla_messageTypeValid(UINT32 type)
1170{
1171 switch (type)
1172 {
1173 case KerbInvalidValue:
1174 case KerbInteractiveLogon:
1175 case KerbSmartCardLogon:
1176 case KerbWorkstationUnlockLogon:
1177 case KerbSmartCardUnlockLogon:
1178 case KerbProxyLogon:
1179 case KerbTicketLogon:
1180 case KerbTicketUnlockLogon:
1181#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1182 case KerbS4ULogon:
1183#endif
1184#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1185 case KerbCertificateLogon:
1186 case KerbCertificateS4ULogon:
1187 case KerbCertificateUnlockLogon:
1188#endif
1189#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1190 case KerbNoElevationLogon:
1191 case KerbLuidLogon:
1192#endif
1193 return TRUE;
1194 default:
1195 WLog_ERR(TAG, "Invalid message type %" PRIu32, type);
1196 return FALSE;
1197 }
1198}
1199
1200static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla, wStream* s,
1201 KERB_TICKET_LOGON* ticket)
1202{
1203 WINPR_ASSERT(nla);
1204
1205 if (!ticket)
1206 return FALSE;
1207
1208 /* mysterious extra 16 bytes before TGS/TGT content */
1209 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1210 return FALSE;
1211
1212 {
1213 const UINT32 type = Stream_Get_UINT32(s);
1214 if (!nla_messageTypeValid(type))
1215 return FALSE;
1216
1217 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1218 }
1219 Stream_Read_UINT32(s, ticket->Flags);
1220 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1221 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1222
1223 if (ticket->MessageType != KerbTicketLogon)
1224 {
1225 WLog_ERR(TAG, "Not a KerbTicketLogon");
1226 return FALSE;
1227 }
1228
1229 if (!Stream_CheckAndLogRequiredLength(
1230 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1231 return FALSE;
1232
1233 /* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
1234 Stream_Seek(s, 16);
1235
1236 /*WLog_INFO(TAG, "TGS");
1237 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
1238 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1239 Stream_Seek(s, ticket->ServiceTicketLength);
1240
1241 /*WLog_INFO(TAG, "TGT");
1242 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
1243 ticket->TicketGrantingTicketLength);*/
1244 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1245 return TRUE;
1246}
1247
1248static BOOL nla_credentialTypeValid(UINT32 type)
1249{
1250 switch (type)
1251 {
1252 case InvalidCredKey:
1253 case DeprecatedIUMCredKey:
1254 case DomainUserCredKey:
1255 case LocalUserCredKey:
1256 case ExternallySuppliedCredKey:
1257 return TRUE;
1258 default:
1259 WLog_ERR(TAG, "Invalid credential type %" PRIu32, type);
1260 return FALSE;
1261 }
1262}
1263
1264WINPR_ATTR_MALLOC(free, 1)
1265WINPR_ATTR_NODISCARD
1266static MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* nla_read_NtlmCreds(WINPR_ATTR_UNUSED rdpNla* nla,
1267 wStream* s)
1268{
1269 WINPR_ASSERT(nla);
1270 WINPR_ASSERT(s);
1271
1272 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1273 return nullptr;
1274
1275 size_t pos = Stream_GetPosition(s);
1276 Stream_Seek(s, 32);
1277
1278 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1279 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1280 return nullptr;
1281
1282 if (!Stream_SetPosition(s, pos))
1283 return nullptr;
1284
1286 1, sizeof(MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL) - 1 + EncryptedCredsSize);
1287 if (!ret)
1288 return nullptr;
1289
1290 ret->Version = Stream_Get_UINT32(s);
1291 ret->Flags = Stream_Get_UINT32(s);
1292 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1293 {
1294 const UINT32 val = Stream_Get_UINT32(s);
1295 if (!nla_credentialTypeValid(val))
1296 {
1297 free(ret);
1298 return nullptr;
1299 }
1300 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1301 }
1302 ret->EncryptedCredsSize = EncryptedCredsSize;
1303 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1304
1305 return ret;
1306}
1307
1309typedef enum
1310{
1311 RCG_TYPE_NONE,
1312 RCG_TYPE_KERB,
1313 RCG_TYPE_NTLM
1314} RemoteGuardPackageCredType;
1315
1316static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla, WinPrAsn1Decoder* dec,
1317 RemoteGuardPackageCredType* credsType,
1318 wStream* payload)
1319{
1320 WinPrAsn1_OctetString packageName = WINPR_C_ARRAY_INIT;
1321 WinPrAsn1_OctetString credBuffer = WINPR_C_ARRAY_INIT;
1322 BOOL error = FALSE;
1323 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1324
1325 WINPR_ASSERT(nla);
1326 WINPR_ASSERT(dec);
1327 WINPR_ASSERT(credsType);
1328 WINPR_ASSERT(payload);
1329
1330 *credsType = RCG_TYPE_NONE;
1331
1332 /* packageName [0] OCTET STRING */
1333 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1334 return FALSE;
1335
1336 ConvertMszWCharNToUtf8(WINPR_PACKED_ALIGN_CAST(WCHAR*, packageName.data),
1337 packageName.len / sizeof(WCHAR), packageNameStr, sizeof(packageNameStr));
1338 WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1339
1340 /* credBuffer [1] OCTET STRING, */
1341 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1342 return FALSE;
1343
1344 if (_stricmp(packageNameStr, "Kerberos") == 0)
1345 {
1346 *credsType = RCG_TYPE_KERB;
1347 }
1348 else if (_stricmp(packageNameStr, "NTLM") == 0)
1349 {
1350 *credsType = RCG_TYPE_NTLM;
1351 }
1352 else
1353 {
1354 WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1355 return FALSE;
1356 }
1357
1358 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1359 return TRUE;
1360}
1361
1363typedef enum
1364{
1365 TSCREDS_INVALID = 0,
1366 TSCREDS_USER_PASSWD = 1,
1367 TSCREDS_SMARTCARD = 2,
1368 TSCREDS_REMOTEGUARD = 6
1369} TsCredentialsType;
1370
1371static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1372{
1373 WinPrAsn1Decoder dec = WinPrAsn1Decoder_init();
1374 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
1375 WinPrAsn1_OctetString credentials = WINPR_C_ARRAY_INIT;
1376 BOOL error = FALSE;
1377 WinPrAsn1_INTEGER credType = -1;
1378 BOOL ret = TRUE;
1379
1380 WINPR_ASSERT(nla);
1381 WINPR_ASSERT(data);
1382
1383 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1384
1385 /* TSCredentials */
1386 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1387 return FALSE;
1388 dec = dec2;
1389
1390 /* credType [0] INTEGER */
1391 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1392 return FALSE;
1393
1394 /* credentials [1] OCTET STRING */
1395 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1396 return FALSE;
1397
1398 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1399
1400 rdpSettings* settings = nla->rdpcontext->settings;
1401 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1402 credType != TSCREDS_REMOTEGUARD)
1403 {
1404 WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1405 return FALSE;
1406 }
1407
1408 switch (credType)
1409 {
1410 case TSCREDS_USER_PASSWD:
1411 {
1412 /* TSPasswordCreds */
1413 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1414 return FALSE;
1415 dec = dec2;
1416
1417 /* domainName [0] OCTET STRING */
1418 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1419 return FALSE;
1420
1421 /* userName [1] OCTET STRING */
1422 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1423 return FALSE;
1424
1425 /* password [2] OCTET STRING */
1426 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1427 }
1428 case TSCREDS_SMARTCARD:
1429 {
1430 /* TSSmartCardCreds */
1431 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1432 return FALSE;
1433 dec = dec2;
1434
1435 /* pin [0] OCTET STRING, */
1436 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1437 return FALSE;
1438 settings->PasswordIsSmartcardPin = TRUE;
1439
1440 /* cspData [1] TSCspDataDetail */
1441 WinPrAsn1Decoder cspDetails = WinPrAsn1Decoder_init();
1442 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1443 return FALSE;
1444 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1445 return FALSE;
1446
1447 /* userHint [2] OCTET STRING OPTIONAL */
1448 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1449 return FALSE;
1450
1451 /* domainHint [3] OCTET STRING OPTIONAL */
1452 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1453 }
1454 case TSCREDS_REMOTEGUARD:
1455 {
1456 /* TSRemoteGuardCreds */
1457 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1458 return FALSE;
1459
1460 /* logonCred[0] TSRemoteGuardPackageCred */
1461 KERB_TICKET_LOGON kerbLogon = { .MessageType = KerbInvalidValue,
1462 .Flags = 0,
1463 .ServiceTicketLength = 0,
1464 .TicketGrantingTicketLength = 0,
1465 .ServiceTicket = nullptr,
1466 .TicketGrantingTicket = nullptr };
1467
1468 WinPrAsn1Decoder logonCredsSeq = WinPrAsn1Decoder_init();
1469
1470 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1471 return FALSE;
1472
1473 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1474 wStream logonPayload = WINPR_C_ARRAY_INIT;
1475 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1476 &logonPayload))
1477 return FALSE;
1478 if (logonCredsType != RCG_TYPE_KERB)
1479 {
1480 WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1481 return FALSE;
1482 }
1483
1484 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1485 {
1486 WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1487 return FALSE;
1488 }
1489
1490 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1491 MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds = nullptr;
1492 WinPrAsn1Decoder suppCredsSeq = WinPrAsn1Decoder_init();
1493
1494 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1495 Stream_GetRemainingLength(&suppCredsSeq.source))
1496 {
1497 WinPrAsn1Decoder ntlmCredsSeq = WinPrAsn1Decoder_init();
1498 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1499 return FALSE;
1500
1501 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1502 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1503 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1504 &ntlmPayload))
1505 return FALSE;
1506
1507 if (suppCredsType != RCG_TYPE_NTLM)
1508 {
1509 WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1510 return FALSE;
1511 }
1512
1513 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1514 if (!suppCreds)
1515 {
1516 WLog_ERR(TAG, "invalid supplementalCreds");
1517 return FALSE;
1518 }
1519 }
1520 else if (error)
1521 {
1522 WLog_ERR(TAG, "invalid supplementalCreds");
1523 return FALSE;
1524 }
1525
1526 freerdp_peer* peer = nla->rdpcontext->peer;
1527 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1528 free(suppCreds);
1529 break;
1530 }
1531 default:
1532 WLog_DBG(TAG, "TSCredentials type %d not supported for now", credType);
1533 ret = FALSE;
1534 break;
1535 }
1536
1537 return ret;
1538}
1539
1540static BOOL nla_write_KERB_TICKET_LOGON(wStream* s, const KERB_TICKET_LOGON* ticket)
1541{
1542 WINPR_ASSERT(ticket);
1543
1544 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1545 ticket->TicketGrantingTicketLength))
1546 return FALSE;
1547
1548 Stream_Write_UINT32(s, KerbTicketLogon);
1549 Stream_Write_UINT32(s, ticket->Flags);
1550 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1551 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1552
1553 Stream_Write_UINT64(s, 0x20); /* offset of TGS in the packet */
1554 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength); /* offset of TGT in packet */
1555
1556 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1557 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1558 return TRUE;
1559}
1560
1561static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla, KERB_TICKET_LOGON* logonTicket)
1562{
1563 WINPR_ASSERT(nla);
1564 WINPR_ASSERT(logonTicket);
1565
1566 SecurityFunctionTable* table = nullptr;
1567 CtxtHandle context = WINPR_C_ARRAY_INIT;
1568 credssp_auth_tableAndContext(nla->auth, &table, &context);
1569 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1570 SEC_E_OK;
1571}
1572
1573static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1574{
1575 BOOL ret = FALSE;
1576 wStream* s = nullptr;
1577 char kerberos[] = { 'K', '\0', 'e', '\0', 'r', '\0', 'b', '\0',
1578 'e', '\0', 'r', '\0', 'o', '\0', 's', '\0' };
1579 WinPrAsn1_OctetString packageName = { sizeof(kerberos), (BYTE*)kerberos };
1580 WinPrAsn1_OctetString credBuffer;
1581 KERB_TICKET_LOGON logonTicket;
1582
1583 logonTicket.ServiceTicket = nullptr;
1584 logonTicket.TicketGrantingTicket = nullptr;
1585
1586 /* packageName [0] OCTET STRING */
1587 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1588 goto out;
1589
1590 /* credBuffer [1] OCTET STRING */
1591 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1592 goto out;
1593
1594 s = Stream_New(nullptr, 2000);
1595 if (!s)
1596 goto out;
1597
1598 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1599 goto out;
1600
1601 credBuffer.len = Stream_GetPosition(s);
1602 credBuffer.data = Stream_Buffer(s);
1603 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1604
1605out:
1606 free(logonTicket.ServiceTicket);
1607 free(logonTicket.TicketGrantingTicket);
1608 Stream_Free(s, TRUE);
1609 return ret;
1610}
1611
1612static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1614{
1615 WINPR_UNUSED(nla);
1616 BOOL ret = FALSE;
1617 BYTE ntlm[] = { 'N', '\0', 'T', '\0', 'L', '\0', 'M', '\0' };
1618 const WinPrAsn1_OctetString packageName = { sizeof(ntlm), ntlm };
1619
1620 /* packageName [0] OCTET STRING */
1621 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1622 return FALSE;
1623
1624 /* credBuffer [1] OCTET STRING */
1625 wStream* s = Stream_New(nullptr, 300);
1626 if (!s)
1627 goto out;
1628
1629 Stream_Write_UINT32(s, pntlm->Version); /* Version */
1630 Stream_Write_UINT32(s, pntlm->Flags); /* Flags */
1631
1632 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1633 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1634 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1635 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1636 Stream_Zero(s, 6 + 16 * 4 + 14);
1637
1638 {
1639 WinPrAsn1_OctetString credBuffer = { Stream_GetPosition(s), Stream_Buffer(s) };
1640 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1641 }
1642
1643out:
1644 Stream_Free(s, TRUE);
1645 return ret;
1646}
1647
1648static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1649{
1650 struct
1651 {
1652 WinPrAsn1_tagId tag;
1653 FreeRDP_Settings_Keys_String setting_id;
1654 } cspData_fields[] = { { 1, FreeRDP_CardName },
1655 { 2, FreeRDP_ReaderName },
1656 { 3, FreeRDP_ContainerName },
1657 { 4, FreeRDP_CspName } };
1658 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
1659
1660 WINPR_ASSERT(nla);
1661 WINPR_ASSERT(enc);
1662 WINPR_ASSERT(nla->rdpcontext);
1663
1664 const rdpSettings* settings = nla->rdpcontext->settings;
1665 WINPR_ASSERT(settings);
1666
1667 /* TSSmartCardCreds */
1668 if (!WinPrAsn1EncSeqContainer(enc))
1669 return FALSE;
1670
1671 /* pin [0] OCTET STRING */
1672 size_t ss = 0;
1673 octet_string.data =
1674 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1675 octet_string.len = ss * sizeof(WCHAR);
1676 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1677 WinPrAsn1FreeOctetString(&octet_string);
1678 if (!res)
1679 return FALSE;
1680
1681 /* cspData [1] SEQUENCE */
1682 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1683 return FALSE;
1684
1685 /* keySpec [0] INTEGER */
1686 if (!WinPrAsn1EncContextualInteger(
1687 enc, 0,
1688 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1689 freerdp_settings_get_uint32(settings, FreeRDP_KeySpec))))
1690 return FALSE;
1691
1692 for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1693 {
1694 size_t len = 0;
1695
1696 octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1697 settings, cspData_fields[i].setting_id, &len);
1698 octet_string.len = len * sizeof(WCHAR);
1699 if (octet_string.len)
1700 {
1701 const BOOL res2 =
1702 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1703 WinPrAsn1FreeOctetString(&octet_string);
1704 if (!res2)
1705 return FALSE;
1706 }
1707 }
1708
1709 /* End cspData */
1710 if (!WinPrAsn1EncEndContainer(enc))
1711 return FALSE;
1712
1713 /* userHint [2] OCTET STRING OPTIONAL, */
1714 if (freerdp_settings_get_string(settings, FreeRDP_Username))
1715 {
1716 octet_string.data =
1717 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Username, &ss);
1718 octet_string.len = ss * sizeof(WCHAR);
1719 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1720 WinPrAsn1FreeOctetString(&octet_string);
1721 if (!res)
1722 return FALSE;
1723 }
1724
1725 /* domainHint [3] OCTET STRING OPTIONAL */
1726 if (freerdp_settings_get_string(settings, FreeRDP_Domain))
1727 {
1728 octet_string.data =
1729 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Domain, &ss);
1730 octet_string.len = ss * sizeof(WCHAR);
1731 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1732 WinPrAsn1FreeOctetString(&octet_string);
1733 if (!res)
1734 return FALSE;
1735 }
1736
1737 /* End TSSmartCardCreds */
1738 return WinPrAsn1EncEndContainer(enc) != 0;
1739}
1740
1741static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1742{
1743 WinPrAsn1_OctetString username = WINPR_C_ARRAY_INIT;
1744 WinPrAsn1_OctetString domain = WINPR_C_ARRAY_INIT;
1745 WinPrAsn1_OctetString password = WINPR_C_ARRAY_INIT;
1746
1747 WINPR_ASSERT(nla);
1748 WINPR_ASSERT(enc);
1749 WINPR_ASSERT(nla->rdpcontext);
1750
1751 const rdpSettings* settings = nla->rdpcontext->settings;
1752 WINPR_ASSERT(settings);
1753
1754 /* TSPasswordCreds */
1755 if (!WinPrAsn1EncSeqContainer(enc))
1756 return FALSE;
1757
1758 if (!settings->DisableCredentialsDelegation && nla->identity)
1759 {
1760 username.len = nla->identity->UserLength * sizeof(WCHAR);
1761 username.data = (BYTE*)nla->identity->User;
1762
1763 domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1764 domain.data = (BYTE*)nla->identity->Domain;
1765
1766 password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1767 password.data = (BYTE*)nla->identity->Password;
1768 }
1769
1770 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1771 return FALSE;
1772 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1773 return FALSE;
1774 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1775 return FALSE;
1776
1777 /* End TSPasswordCreds */
1778 return WinPrAsn1EncEndContainer(enc) != 0;
1779}
1780
1781static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1782{
1783 WINPR_ASSERT(nla);
1784 WINPR_ASSERT(enc);
1785
1786 /* TSRemoteGuardCreds */
1787 if (!WinPrAsn1EncSeqContainer(enc))
1788 return FALSE;
1789
1790 /* logonCred [0] TSRemoteGuardPackageCred, */
1791 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1792 return FALSE;
1793
1794 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1795 return FALSE;
1796
1797 /* TODO: compute the NTLM supplemental creds */
1799 if (ntlm)
1800 {
1801 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL */
1802 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1803 return FALSE;
1804
1805 if (!WinPrAsn1EncSeqContainer(enc)) /* start NTLM */
1806 return FALSE;
1807
1808 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1809 return FALSE;
1810
1811 if (!WinPrAsn1EncEndContainer(enc)) /* end NTLM */
1812 return FALSE;
1813
1814 if (!WinPrAsn1EncEndContainer(enc)) /* supplementalCreds */
1815 return FALSE;
1816 }
1817
1818 /* End TSRemoteGuardCreds */
1819 return WinPrAsn1EncEndContainer(enc) != 0;
1820}
1821
1829static BOOL nla_encode_ts_credentials(rdpNla* nla)
1830{
1831 BOOL ret = FALSE;
1832 WinPrAsn1Encoder* enc = nullptr;
1833 size_t length = 0;
1834 wStream s = WINPR_C_ARRAY_INIT;
1835 TsCredentialsType credType = TSCREDS_INVALID;
1836
1837 WINPR_ASSERT(nla);
1838 WINPR_ASSERT(nla->rdpcontext);
1839
1840 rdpSettings* settings = nla->rdpcontext->settings;
1841 WINPR_ASSERT(settings);
1842
1843 if (settings->RemoteCredentialGuard)
1844 credType = TSCREDS_REMOTEGUARD;
1845 else if (settings->SmartcardLogon)
1846 credType = TSCREDS_SMARTCARD;
1847 else
1848 credType = TSCREDS_USER_PASSWD;
1849
1850 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1851 if (!enc)
1852 return FALSE;
1853
1854 /* TSCredentials */
1855 if (!WinPrAsn1EncSeqContainer(enc))
1856 goto out;
1857
1858 /* credType [0] INTEGER */
1859 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1860 goto out;
1861
1862 /* credentials [1] OCTET STRING */
1863 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1864 goto out;
1865
1866 switch (credType)
1867 {
1868 case TSCREDS_SMARTCARD:
1869 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1870 goto out;
1871 break;
1872
1873 case TSCREDS_USER_PASSWD:
1874 if (!nla_encode_ts_password_credentials(nla, enc))
1875 goto out;
1876 break;
1877
1878 case TSCREDS_REMOTEGUARD:
1879 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1880 goto out;
1881 break;
1882 default:
1883 goto out;
1884 }
1885
1886 /* End credentials | End TSCredentials */
1887 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1888 goto out;
1889
1890 if (!WinPrAsn1EncStreamSize(enc, &length))
1891 goto out;
1892
1893 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1894 {
1895 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1896 goto out;
1897 }
1898
1899 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1900
1901 ret = WinPrAsn1EncToStream(enc, &s);
1902
1903out:
1904 WinPrAsn1Encoder_Free(&enc);
1905 return ret;
1906}
1907
1908static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1909{
1910 WINPR_ASSERT(nla);
1911
1912 if (!nla_encode_ts_credentials(nla))
1913 return FALSE;
1914
1915 sspi_SecBufferFree(&nla->authInfo);
1916 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, nullptr,
1917 nla->sendSeqNum++));
1918}
1919
1920static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1921{
1922 WINPR_ASSERT(nla);
1923
1924 if (nla->authInfo.cbBuffer < 1)
1925 {
1926 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1927 return FALSE;
1928 }
1929
1930 sspi_SecBufferFree(&nla->tsCredentials);
1931 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1932 return FALSE;
1933
1934 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1935 return FALSE;
1936
1937 return TRUE;
1938}
1939
1940static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1941 WinPrAsn1_tagId tagId, const char* msg)
1942{
1943 BOOL res = FALSE;
1944
1945 WINPR_ASSERT(enc);
1946 WINPR_ASSERT(buffer);
1947 WINPR_ASSERT(msg);
1948
1949 if (buffer->cbBuffer > 0)
1950 {
1951 size_t rc = 0;
1952 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
1953
1954 WLog_DBG(TAG, " ----->> %s", msg);
1955 octet_string.data = buffer->pvBuffer;
1956 octet_string.len = buffer->cbBuffer;
1957 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1958 if (rc != 0)
1959 res = TRUE;
1960 }
1961
1962 return res;
1963}
1964
1965static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1966 WinPrAsn1_tagId tagId, const char* msg)
1967{
1968 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1969 sspi_SecBufferFree(buffer);
1970 return rc;
1971}
1972
1981BOOL nla_send(rdpNla* nla)
1982{
1983 BOOL rc = FALSE;
1984 wStream* s = nullptr;
1985 size_t length = 0;
1986 WinPrAsn1Encoder* enc = nullptr;
1987
1988 WINPR_ASSERT(nla);
1989
1990 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1991 if (!enc)
1992 return FALSE;
1993
1994 /* TSRequest */
1995 WLog_DBG(TAG, "----->> sending...");
1996 if (!WinPrAsn1EncSeqContainer(enc))
1997 goto fail;
1998
1999 /* version [0] INTEGER */
2000 WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
2001 if (!WinPrAsn1EncContextualInteger(enc, 0,
2002 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2003 goto fail;
2004
2005 /* negoTokens [1] SEQUENCE OF SEQUENCE */
2006 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2007 {
2008 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2009
2010 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2011 goto fail;
2012
2013 /* negoToken [0] OCTET STRING */
2014 if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
2015 goto fail;
2016
2017 /* End negoTokens (SEQUENCE OF SEQUENCE) */
2018 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2019 goto fail;
2020 }
2021
2022 /* authInfo [2] OCTET STRING */
2023 if (nla->authInfo.cbBuffer > 0)
2024 {
2025 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
2026 goto fail;
2027 }
2028
2029 /* pubKeyAuth [3] OCTET STRING */
2030 if (nla->pubKeyAuth.cbBuffer > 0)
2031 {
2032 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
2033 goto fail;
2034 }
2035
2036 /* errorCode [4] INTEGER */
2037 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2038 {
2039 WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2040 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2041 if (!WinPrAsn1EncContextualInteger(
2042 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2043 goto fail;
2044 }
2045
2046 /* clientNonce [5] OCTET STRING */
2047 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2048 {
2049 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
2050 goto fail;
2051 }
2052
2053 /* End TSRequest */
2054 if (!WinPrAsn1EncEndContainer(enc))
2055 goto fail;
2056
2057 if (!WinPrAsn1EncStreamSize(enc, &length))
2058 goto fail;
2059
2060 s = Stream_New(nullptr, length);
2061 if (!s)
2062 goto fail;
2063
2064 if (!WinPrAsn1EncToStream(enc, s))
2065 goto fail;
2066
2067 WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
2068 if (transport_write(nla->transport, s) < 0)
2069 goto fail;
2070 rc = TRUE;
2071
2072fail:
2073 Stream_Free(s, TRUE);
2074 WinPrAsn1Encoder_Free(&enc);
2075 return rc;
2076}
2077
2078static int nla_decode_ts_request(rdpNla* nla, wStream* s)
2079{
2080 WinPrAsn1Decoder dec = WinPrAsn1Decoder_init();
2081 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
2082 BOOL error = FALSE;
2083 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2084 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2085 UINT32 version = 0;
2086
2087 WINPR_ASSERT(nla);
2088 WINPR_ASSERT(s);
2089
2090 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2091
2092 WLog_DBG(TAG, "<<----- receiving...");
2093
2094 /* TSRequest */
2095 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2096 if (offset == 0)
2097 return -1;
2098 dec = dec2;
2099
2100 /* version [0] INTEGER */
2101 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2102 return -1;
2103
2104 if (!Stream_SafeSeek(s, offset))
2105 return -1;
2106
2107 version = (UINT)val;
2108 WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
2109
2110 if (nla->peerVersion == 0)
2111 nla->peerVersion = version;
2112
2113 /* if the peer suddenly changed its version - kick it */
2114 if (nla->peerVersion != version)
2115 {
2116 WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
2117 nla->peerVersion, version);
2118 return -1;
2119 }
2120
2121 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2122 {
2123 WinPrAsn1Decoder dec3 = WinPrAsn1Decoder_init();
2124 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
2125
2126 switch (tag)
2127 {
2128 case 1:
2129 WLog_DBG(TAG, " <<----- nego token");
2130 /* negoTokens [1] SEQUENCE OF SEQUENCE */
2131 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2132 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2133 return -1;
2134 /* negoToken [0] OCTET STRING */
2135 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2136 FALSE) == 0) &&
2137 error)
2138 return -1;
2139 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2140 octet_string.len))
2141 return -1;
2142 break;
2143 case 2:
2144 WLog_DBG(TAG, " <<----- auth info");
2145 /* authInfo [2] OCTET STRING */
2146 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2147 return -1;
2148 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2149 octet_string.len))
2150 return -1;
2151 break;
2152 case 3:
2153 WLog_DBG(TAG, " <<----- public key auth");
2154 /* pubKeyAuth [3] OCTET STRING */
2155 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2156 return -1;
2157 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2158 octet_string.len))
2159 return -1;
2160 break;
2161 case 4:
2162 /* errorCode [4] INTEGER */
2163 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2164 return -1;
2165 nla->errorCode = val;
2166 WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2167 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2168 break;
2169 case 5:
2170 WLog_DBG(TAG, " <<----- client nonce");
2171 /* clientNonce [5] OCTET STRING */
2172 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2173 return -1;
2174 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2175 octet_string.len))
2176 return -1;
2177 break;
2178 default:
2179 return -1;
2180 }
2181 }
2182
2183 return 1;
2184}
2185
2186int nla_recv_pdu(rdpNla* nla, wStream* s)
2187{
2188 WINPR_ASSERT(nla);
2189 WINPR_ASSERT(s);
2190
2191 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2192 {
2193 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2194 return -1;
2195
2196 const UINT32 authzResult = Stream_Get_UINT32(s);
2197 if (authzResult != AUTHZ_SUCCESS)
2198 {
2199 UINT32 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2200
2201 switch (authzResult)
2202 {
2203 case AUTHZ_ACCESS_DENIED:
2204 /* The user authenticated successfully but is not authorized to open a
2205 * session on this host, e.g. it lacks the 'Allow log on through Remote
2206 * Desktop Services' right. */
2207 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2208 break;
2209 default:
2210 break;
2211 }
2212
2213 WLog_ERR(TAG, "Early User Auth active: FAILURE authorization result 0x%08" PRIX32 "",
2214 authzResult);
2215 freerdp_set_last_error_log(nla->rdpcontext, code);
2216 return -1;
2217 }
2218 else
2219 WLog_DBG(TAG, "Early User Auth active: SUCCESS");
2220 }
2221 else
2222 {
2223 if (nla_decode_ts_request(nla, s) < 1)
2224 return -1;
2225
2226 if (nla->errorCode)
2227 {
2228 UINT32 code = 0;
2229
2230 switch (nla->errorCode)
2231 {
2232 case STATUS_PASSWORD_MUST_CHANGE:
2233 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2234 break;
2235
2236 case STATUS_PASSWORD_EXPIRED:
2237 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2238 break;
2239
2240 case STATUS_ACCOUNT_DISABLED:
2241 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2242 break;
2243
2244 case STATUS_LOGON_FAILURE:
2245 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2246 break;
2247
2248 case STATUS_WRONG_PASSWORD:
2249 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2250 break;
2251
2252 case STATUS_ACCESS_DENIED:
2253 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2254 break;
2255
2256 case STATUS_ACCOUNT_RESTRICTION:
2257 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2258 break;
2259
2260 case STATUS_ACCOUNT_LOCKED_OUT:
2261 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2262 break;
2263
2264 case STATUS_ACCOUNT_EXPIRED:
2265 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2266 break;
2267
2268 case STATUS_LOGON_TYPE_NOT_GRANTED:
2269 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2270 break;
2271
2272 default:
2273 WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32 "]",
2274 NtStatus2Tag(nla->errorCode),
2275 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2276 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2277 break;
2278 }
2279
2280 freerdp_set_last_error_log(nla->rdpcontext, code);
2281 return -1;
2282 }
2283 }
2284
2285 return nla_client_recv(nla);
2286}
2287
2288int nla_server_recv(rdpNla* nla)
2289{
2290 int status = -1;
2291
2292 WINPR_ASSERT(nla);
2293
2294 wStream* s = nla_server_recv_stream(nla);
2295 if (!s)
2296 goto fail;
2297 status = nla_decode_ts_request(nla, s);
2298
2299fail:
2300 Stream_Free(s, TRUE);
2301 return status;
2302}
2303
2313rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2314{
2315 WINPR_ASSERT(transport);
2316 WINPR_ASSERT(context);
2317
2318 rdpSettings* settings = context->settings;
2319 WINPR_ASSERT(settings);
2320
2321 rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2322
2323 if (!nla)
2324 return nullptr;
2325
2326 nla->rdpcontext = context;
2327 nla->server = settings->ServerMode;
2328 nla->transport = transport;
2329 nla->sendSeqNum = 0;
2330 nla->recvSeqNum = 0;
2331 nla->version = 6;
2332 nla->earlyUserAuth = FALSE;
2333
2334 nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2335 if (!nla->identity)
2336 goto cleanup;
2337
2338 nla->auth = credssp_auth_new(context);
2339 if (!nla->auth)
2340 goto cleanup;
2341
2342 /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2343 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2344 goto cleanup;
2345
2346 /* generate random 32-byte nonce */
2347 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2348 goto cleanup;
2349
2350 return nla;
2351cleanup:
2352 WINPR_PRAGMA_DIAG_PUSH
2353 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2354 nla_free(nla);
2355 WINPR_PRAGMA_DIAG_POP
2356 return nullptr;
2357}
2358
2364void nla_free(rdpNla* nla)
2365{
2366 if (!nla)
2367 return;
2368
2369 smartcardCertInfo_Free(nla->smartcardCert);
2370 nla_buffer_free(nla);
2371 sspi_SecBufferFree(&nla->tsCredentials);
2372 credssp_auth_free(nla->auth);
2373
2374 sspi_FreeAuthIdentity(nla->identity);
2375 free(nla->pkinitArgs);
2376 free(nla->identity);
2377 free(nla);
2378}
2379
2380SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2381{
2382 if (!nla)
2383 return nullptr;
2384
2385 return nla->identity;
2386}
2387
2388NLA_STATE nla_get_state(const rdpNla* nla)
2389{
2390 if (!nla)
2391 return NLA_STATE_FINAL;
2392
2393 return nla->state;
2394}
2395
2396BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2397{
2398 if (!nla)
2399 return FALSE;
2400
2401 WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2402 nla->state = state;
2403 return TRUE;
2404}
2405
2406BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2407{
2408 return (credssp_auth_set_spn(nla->auth, service, hostname));
2409}
2410
2411BOOL nla_impersonate(rdpNla* nla)
2412{
2413 return credssp_auth_impersonate(nla->auth);
2414}
2415
2416BOOL nla_revert_to_self(rdpNla* nla)
2417{
2418 return credssp_auth_revert_to_self(nla->auth);
2419}
2420
2421const char* nla_get_state_str(NLA_STATE state)
2422{
2423 switch (state)
2424 {
2425 case NLA_STATE_INITIAL:
2426 return "NLA_STATE_INITIAL";
2427 case NLA_STATE_NEGO_TOKEN:
2428 return "NLA_STATE_NEGO_TOKEN";
2429 case NLA_STATE_PUB_KEY_AUTH:
2430 return "NLA_STATE_PUB_KEY_AUTH";
2431 case NLA_STATE_AUTH_INFO:
2432 return "NLA_STATE_AUTH_INFO";
2433 case NLA_STATE_POST_NEGO:
2434 return "NLA_STATE_POST_NEGO";
2435 case NLA_STATE_EARLY_USER_AUTH:
2436 return "NLA_STATE_EARLY_USER_AUTH";
2437 case NLA_STATE_FINAL:
2438 return "NLA_STATE_FINAL";
2439 default:
2440 return "UNKNOWN";
2441 }
2442}
2443
2444DWORD nla_get_error(const rdpNla* nla)
2445{
2446 if (!nla)
2447 return ERROR_INTERNAL_ERROR;
2448 return (UINT32)nla->errorCode;
2449}
2450
2451INT32 nla_get_sspi_error(const rdpNla* nla)
2452{
2453 WINPR_ASSERT(nla);
2454 return credssp_auth_sspi_error(nla->auth);
2455}
2456
2457BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2458{
2459 WINPR_ASSERT(nla);
2460 WINPR_ASSERT(inBuffer);
2461 WINPR_ASSERT(outBuffer);
2462 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, nullptr, nla->sendSeqNum++);
2463}
2464
2465BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2466{
2467 WINPR_ASSERT(nla);
2468 WINPR_ASSERT(inBuffer);
2469 WINPR_ASSERT(outBuffer);
2470 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2471}
2472
2473SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2474{
2475 WINPR_ASSERT(nla);
2476
2477 SecurityFunctionTable* table = nullptr;
2478 CtxtHandle context = WINPR_C_ARRAY_INIT;
2479 credssp_auth_tableAndContext(nla->auth, &table, &context);
2480
2481 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2482}
2483
2484SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2485{
2486 WINPR_ASSERT(nla);
2487
2488 SecurityFunctionTable* table = nullptr;
2489 CtxtHandle context = WINPR_C_ARRAY_INIT;
2490 credssp_auth_tableAndContext(nla->auth, &table, &context);
2491
2492 return table->FreeContextBuffer(pBuffer);
2493}
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string_from_utf16N(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param, size_t length)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_server_name(const rdpSettings *settings)
A helper function to return the correct server name.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string_from_utf16(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const WCHAR *param)
Sets a string settings value. The param is converted to UTF-8 and the copy stored.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.