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