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