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