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 != (ER_TAG_CONTEXTUAL | 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
1199WINPR_ATTR_MALLOC(free, 1)
1200static MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* nla_read_NtlmCreds(WINPR_ATTR_UNUSED rdpNla* nla,
1201 wStream* s)
1202{
1203 WINPR_ASSERT(nla);
1204 WINPR_ASSERT(s);
1205
1206 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1207 return NULL;
1208
1209 size_t pos = Stream_GetPosition(s);
1210 Stream_Seek(s, 32);
1211
1212 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1213 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1214 return NULL;
1215
1216 Stream_SetPosition(s, pos);
1217
1219 1, sizeof(MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL) - 1 + EncryptedCredsSize);
1220 if (!ret)
1221 return NULL;
1222
1223 ret->Version = Stream_Get_UINT32(s);
1224 ret->Flags = Stream_Get_UINT32(s);
1225 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1226 ret->CredentialKeyType = Stream_Get_UINT32(s);
1227 ret->EncryptedCredsSize = EncryptedCredsSize;
1228 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1229
1230 return ret;
1231}
1232
1234typedef enum
1235{
1236 RCG_TYPE_NONE,
1237 RCG_TYPE_KERB,
1238 RCG_TYPE_NTLM
1239} RemoteGuardPackageCredType;
1240
1241static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla, WinPrAsn1Decoder* dec,
1242 RemoteGuardPackageCredType* credsType,
1243 wStream* payload)
1244{
1245 WinPrAsn1_OctetString packageName = { 0 };
1246 WinPrAsn1_OctetString credBuffer = { 0 };
1247 BOOL error = FALSE;
1248 char packageNameStr[100] = { 0 };
1249
1250 WINPR_ASSERT(nla);
1251 WINPR_ASSERT(dec);
1252 WINPR_ASSERT(credsType);
1253 WINPR_ASSERT(payload);
1254
1255 *credsType = RCG_TYPE_NONE;
1256
1257 /* packageName [0] OCTET STRING */
1258 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1259 return FALSE;
1260
1261 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
1262 packageNameStr, sizeof(packageNameStr));
1263 WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1264
1265 /* credBuffer [1] OCTET STRING, */
1266 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1267 return FALSE;
1268
1269 if (_stricmp(packageNameStr, "Kerberos") == 0)
1270 {
1271 *credsType = RCG_TYPE_KERB;
1272 }
1273 else if (_stricmp(packageNameStr, "NTLM") == 0)
1274 {
1275 *credsType = RCG_TYPE_NTLM;
1276 }
1277 else
1278 {
1279 WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1280 return FALSE;
1281 }
1282
1283 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1284 return TRUE;
1285}
1286
1288typedef enum
1289{
1290 TSCREDS_INVALID = 0,
1291 TSCREDS_USER_PASSWD = 1,
1292 TSCREDS_SMARTCARD = 2,
1293 TSCREDS_REMOTEGUARD = 6
1294} TsCredentialsType;
1295
1296static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1297{
1298 WinPrAsn1Decoder dec = { 0 };
1299 WinPrAsn1Decoder dec2 = { 0 };
1300 WinPrAsn1_OctetString credentials = { 0 };
1301 BOOL error = FALSE;
1302 WinPrAsn1_INTEGER credType = -1;
1303 BOOL ret = TRUE;
1304
1305 WINPR_ASSERT(nla);
1306 WINPR_ASSERT(data);
1307
1308 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1309
1310 /* TSCredentials */
1311 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1312 return FALSE;
1313 dec = dec2;
1314
1315 /* credType [0] INTEGER */
1316 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1317 return FALSE;
1318
1319 /* credentials [1] OCTET STRING */
1320 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1321 return FALSE;
1322
1323 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1324
1325 rdpSettings* settings = nla->rdpcontext->settings;
1326 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1327 credType != TSCREDS_REMOTEGUARD)
1328 {
1329 WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1330 return FALSE;
1331 }
1332
1333 switch (credType)
1334 {
1335 case TSCREDS_USER_PASSWD:
1336 {
1337 /* TSPasswordCreds */
1338 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1339 return FALSE;
1340 dec = dec2;
1341
1342 /* domainName [0] OCTET STRING */
1343 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1344 return FALSE;
1345
1346 /* userName [1] OCTET STRING */
1347 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1348 return FALSE;
1349
1350 /* password [2] OCTET STRING */
1351 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1352 }
1353 case TSCREDS_SMARTCARD:
1354 {
1355 /* TSSmartCardCreds */
1356 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1357 return FALSE;
1358 dec = dec2;
1359
1360 /* pin [0] OCTET STRING, */
1361 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1362 return FALSE;
1363 settings->PasswordIsSmartcardPin = TRUE;
1364
1365 /* cspData [1] TSCspDataDetail */
1366 WinPrAsn1Decoder cspDetails = { 0 };
1367 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1368 return FALSE;
1369 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1370 return FALSE;
1371
1372 /* userHint [2] OCTET STRING OPTIONAL */
1373 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1374 return FALSE;
1375
1376 /* domainHint [3] OCTET STRING OPTIONAL */
1377 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1378 }
1379 case TSCREDS_REMOTEGUARD:
1380 {
1381 /* TSRemoteGuardCreds */
1382 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1383 return FALSE;
1384
1385 /* logonCred[0] TSRemoteGuardPackageCred */
1386 KERB_TICKET_LOGON kerbLogon = { 0 };
1387 WinPrAsn1Decoder logonCredsSeq = { 0 };
1388 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1389 return FALSE;
1390
1391 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1392 wStream logonPayload = { 0 };
1393 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1394 &logonPayload))
1395 return FALSE;
1396 if (logonCredsType != RCG_TYPE_KERB)
1397 {
1398 WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1399 return FALSE;
1400 }
1401
1402 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1403 {
1404 WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1405 return FALSE;
1406 }
1407
1408 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1409 MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds = NULL;
1410 WinPrAsn1Decoder suppCredsSeq = { 0 };
1411
1412 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1413 Stream_GetRemainingLength(&suppCredsSeq.source))
1414 {
1415 WinPrAsn1Decoder ntlmCredsSeq = { 0 };
1416 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1417 return FALSE;
1418
1419 RemoteGuardPackageCredType suppCredsType = { 0 };
1420 wStream ntlmPayload = { 0 };
1421 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1422 &ntlmPayload))
1423 return FALSE;
1424
1425 if (suppCredsType != RCG_TYPE_NTLM)
1426 {
1427 WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1428 return FALSE;
1429 }
1430
1431 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1432 if (!suppCreds)
1433 {
1434 WLog_ERR(TAG, "invalid supplementalCreds");
1435 return FALSE;
1436 }
1437 }
1438 else if (error)
1439 {
1440 WLog_ERR(TAG, "invalid supplementalCreds");
1441 return FALSE;
1442 }
1443
1444 freerdp_peer* peer = nla->rdpcontext->peer;
1445 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1446 free(suppCreds);
1447 break;
1448 }
1449 default:
1450 WLog_DBG(TAG, "TSCredentials type " PRIu32 " not supported for now", credType);
1451 ret = FALSE;
1452 break;
1453 }
1454
1455 return ret;
1456}
1457
1458static BOOL nla_write_KERB_TICKET_LOGON(wStream* s, const KERB_TICKET_LOGON* ticket)
1459{
1460 WINPR_ASSERT(ticket);
1461
1462 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1463 ticket->TicketGrantingTicketLength))
1464 return FALSE;
1465
1466 Stream_Write_UINT32(s, KerbTicketLogon);
1467 Stream_Write_UINT32(s, ticket->Flags);
1468 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1469 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1470
1471 Stream_Write_UINT64(s, 0x20); /* offset of TGS in the packet */
1472 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength); /* offset of TGT in packet */
1473
1474 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1475 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1476 return TRUE;
1477}
1478
1479static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla, KERB_TICKET_LOGON* logonTicket)
1480{
1481 WINPR_ASSERT(nla);
1482 WINPR_ASSERT(logonTicket);
1483
1484 SecurityFunctionTable* table = NULL;
1485 CtxtHandle context = { 0 };
1486 credssp_auth_tableAndContext(nla->auth, &table, &context);
1487 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1488 SEC_E_OK;
1489}
1490
1491static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1492{
1493 BOOL ret = FALSE;
1494 wStream* s = NULL;
1495 char kerberos[] = { 'K', '\0', 'e', '\0', 'r', '\0', 'b', '\0',
1496 'e', '\0', 'r', '\0', 'o', '\0', 's', '\0' };
1497 WinPrAsn1_OctetString packageName = { sizeof(kerberos), (BYTE*)kerberos };
1498 WinPrAsn1_OctetString credBuffer;
1499 KERB_TICKET_LOGON logonTicket;
1500
1501 logonTicket.ServiceTicket = NULL;
1502 logonTicket.TicketGrantingTicket = NULL;
1503
1504 /* packageName [0] OCTET STRING */
1505 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1506 goto out;
1507
1508 /* credBuffer [1] OCTET STRING */
1509 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1510 goto out;
1511
1512 s = Stream_New(NULL, 2000);
1513 if (!s)
1514 goto out;
1515
1516 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1517 goto out;
1518
1519 credBuffer.len = Stream_GetPosition(s);
1520 credBuffer.data = Stream_Buffer(s);
1521 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1522
1523out:
1524 free(logonTicket.ServiceTicket);
1525 free(logonTicket.TicketGrantingTicket);
1526 Stream_Free(s, TRUE);
1527 return ret;
1528}
1529
1530static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1532{
1533 WINPR_UNUSED(nla);
1534 BOOL ret = FALSE;
1535 BYTE ntlm[] = { 'N', '\0', 'T', '\0', 'L', '\0', 'M', '\0' };
1536 const WinPrAsn1_OctetString packageName = { sizeof(ntlm), ntlm };
1537
1538 /* packageName [0] OCTET STRING */
1539 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1540 return FALSE;
1541
1542 /* credBuffer [1] OCTET STRING */
1543 wStream* s = Stream_New(NULL, 300);
1544 if (!s)
1545 goto out;
1546
1547 Stream_Write_UINT32(s, pntlm->Version); /* Version */
1548 Stream_Write_UINT32(s, pntlm->Flags); /* Flags */
1549
1550 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1551 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1552 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1553 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1554 Stream_Zero(s, 6 + 16 * 4 + 14);
1555
1556 WinPrAsn1_OctetString credBuffer = { Stream_GetPosition(s), Stream_Buffer(s) };
1557 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1558
1559out:
1560 Stream_Free(s, TRUE);
1561 return ret;
1562}
1563
1564static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1565{
1566 struct
1567 {
1568 WinPrAsn1_tagId tag;
1569 FreeRDP_Settings_Keys_String setting_id;
1570 } cspData_fields[] = { { 1, FreeRDP_CardName },
1571 { 2, FreeRDP_ReaderName },
1572 { 3, FreeRDP_ContainerName },
1573 { 4, FreeRDP_CspName } };
1574 WinPrAsn1_OctetString octet_string = { 0 };
1575
1576 WINPR_ASSERT(nla);
1577 WINPR_ASSERT(enc);
1578 WINPR_ASSERT(nla->rdpcontext);
1579
1580 const rdpSettings* settings = nla->rdpcontext->settings;
1581 WINPR_ASSERT(settings);
1582
1583 /* TSSmartCardCreds */
1584 if (!WinPrAsn1EncSeqContainer(enc))
1585 return FALSE;
1586
1587 /* pin [0] OCTET STRING */
1588 size_t ss = 0;
1589 octet_string.data =
1590 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1591 octet_string.len = ss * sizeof(WCHAR);
1592 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1593 free(octet_string.data);
1594 if (!res)
1595 return FALSE;
1596
1597 /* cspData [1] SEQUENCE */
1598 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1599 return FALSE;
1600
1601 /* keySpec [0] INTEGER */
1602 if (!WinPrAsn1EncContextualInteger(
1603 enc, 0,
1604 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1605 freerdp_settings_get_uint32(settings, FreeRDP_KeySpec))))
1606 return FALSE;
1607
1608 for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1609 {
1610 size_t len = 0;
1611
1612 octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1613 settings, cspData_fields[i].setting_id, &len);
1614 octet_string.len = len * sizeof(WCHAR);
1615 if (octet_string.len)
1616 {
1617 const BOOL res2 =
1618 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1619 free(octet_string.data);
1620 if (!res2)
1621 return FALSE;
1622 }
1623 }
1624
1625 /* End cspData */
1626 if (!WinPrAsn1EncEndContainer(enc))
1627 return FALSE;
1628
1629 /* userHint [2] OCTET STRING OPTIONAL, */
1630 if (freerdp_settings_get_string(settings, FreeRDP_Username))
1631 {
1632 octet_string.data =
1633 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Username, &ss);
1634 octet_string.len = ss * sizeof(WCHAR);
1635 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1636 free(octet_string.data);
1637 if (!res)
1638 return FALSE;
1639 }
1640
1641 /* domainHint [3] OCTET STRING OPTIONAL */
1642 if (freerdp_settings_get_string(settings, FreeRDP_Domain))
1643 {
1644 octet_string.data =
1645 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Domain, &ss);
1646 octet_string.len = ss * sizeof(WCHAR);
1647 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1648 free(octet_string.data);
1649 if (!res)
1650 return FALSE;
1651 }
1652
1653 /* End TSSmartCardCreds */
1654 return WinPrAsn1EncEndContainer(enc) != 0;
1655}
1656
1657static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1658{
1659 WinPrAsn1_OctetString username = { 0 };
1660 WinPrAsn1_OctetString domain = { 0 };
1661 WinPrAsn1_OctetString password = { 0 };
1662
1663 WINPR_ASSERT(nla);
1664 WINPR_ASSERT(enc);
1665 WINPR_ASSERT(nla->rdpcontext);
1666
1667 const rdpSettings* settings = nla->rdpcontext->settings;
1668 WINPR_ASSERT(settings);
1669
1670 /* TSPasswordCreds */
1671 if (!WinPrAsn1EncSeqContainer(enc))
1672 return FALSE;
1673
1674 if (!settings->DisableCredentialsDelegation && nla->identity)
1675 {
1676 username.len = nla->identity->UserLength * sizeof(WCHAR);
1677 username.data = (BYTE*)nla->identity->User;
1678
1679 domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1680 domain.data = (BYTE*)nla->identity->Domain;
1681
1682 password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1683 password.data = (BYTE*)nla->identity->Password;
1684 }
1685
1686 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1687 return FALSE;
1688 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1689 return FALSE;
1690 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1691 return FALSE;
1692
1693 /* End TSPasswordCreds */
1694 return WinPrAsn1EncEndContainer(enc) != 0;
1695}
1696
1697static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1698{
1699 WINPR_ASSERT(nla);
1700 WINPR_ASSERT(enc);
1701
1702 /* TSRemoteGuardCreds */
1703 if (!WinPrAsn1EncSeqContainer(enc))
1704 return FALSE;
1705
1706 /* logonCred [0] TSRemoteGuardPackageCred, */
1707 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1708 return FALSE;
1709
1710 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1711 return FALSE;
1712
1713 /* TODO: compute the NTLM supplemental creds */
1715 if (ntlm)
1716 {
1717 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL */
1718 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1719 return FALSE;
1720
1721 if (!WinPrAsn1EncSeqContainer(enc)) /* start NTLM */
1722 return FALSE;
1723
1724 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1725 return FALSE;
1726
1727 if (!WinPrAsn1EncEndContainer(enc)) /* end NTLM */
1728 return FALSE;
1729
1730 if (!WinPrAsn1EncEndContainer(enc)) /* supplementalCreds */
1731 return FALSE;
1732 }
1733
1734 /* End TSRemoteGuardCreds */
1735 return WinPrAsn1EncEndContainer(enc) != 0;
1736}
1737
1745static BOOL nla_encode_ts_credentials(rdpNla* nla)
1746{
1747 BOOL ret = FALSE;
1748 WinPrAsn1Encoder* enc = NULL;
1749 size_t length = 0;
1750 wStream s = { 0 };
1751 TsCredentialsType credType = TSCREDS_INVALID;
1752
1753 WINPR_ASSERT(nla);
1754 WINPR_ASSERT(nla->rdpcontext);
1755
1756 rdpSettings* settings = nla->rdpcontext->settings;
1757 WINPR_ASSERT(settings);
1758
1759 if (settings->RemoteCredentialGuard)
1760 credType = TSCREDS_REMOTEGUARD;
1761 else if (settings->SmartcardLogon)
1762 credType = TSCREDS_SMARTCARD;
1763 else
1764 credType = TSCREDS_USER_PASSWD;
1765
1766 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1767 if (!enc)
1768 return FALSE;
1769
1770 /* TSCredentials */
1771 if (!WinPrAsn1EncSeqContainer(enc))
1772 goto out;
1773
1774 /* credType [0] INTEGER */
1775 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1776 goto out;
1777
1778 /* credentials [1] OCTET STRING */
1779 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1780 goto out;
1781
1782 switch (credType)
1783 {
1784 case TSCREDS_SMARTCARD:
1785 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1786 goto out;
1787 break;
1788
1789 case TSCREDS_USER_PASSWD:
1790 if (!nla_encode_ts_password_credentials(nla, enc))
1791 goto out;
1792 break;
1793
1794 case TSCREDS_REMOTEGUARD:
1795 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1796 goto out;
1797 break;
1798 default:
1799 goto out;
1800 }
1801
1802 /* End credentials | End TSCredentials */
1803 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1804 goto out;
1805
1806 if (!WinPrAsn1EncStreamSize(enc, &length))
1807 goto out;
1808
1809 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1810 {
1811 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1812 goto out;
1813 }
1814
1815 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1816
1817 ret = WinPrAsn1EncToStream(enc, &s);
1818
1819out:
1820 WinPrAsn1Encoder_Free(&enc);
1821 return ret;
1822}
1823
1824static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1825{
1826 WINPR_ASSERT(nla);
1827
1828 if (!nla_encode_ts_credentials(nla))
1829 return FALSE;
1830
1831 sspi_SecBufferFree(&nla->authInfo);
1832 if (!credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, NULL,
1833 nla->sendSeqNum++))
1834 return FALSE;
1835
1836 return TRUE;
1837}
1838
1839static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1840{
1841 WINPR_ASSERT(nla);
1842
1843 if (nla->authInfo.cbBuffer < 1)
1844 {
1845 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1846 return FALSE;
1847 }
1848
1849 sspi_SecBufferFree(&nla->tsCredentials);
1850 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1851 return FALSE;
1852
1853 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1854 return FALSE;
1855
1856 return TRUE;
1857}
1858
1859static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1860 WinPrAsn1_tagId tagId, const char* msg)
1861{
1862 BOOL res = FALSE;
1863
1864 WINPR_ASSERT(enc);
1865 WINPR_ASSERT(buffer);
1866 WINPR_ASSERT(msg);
1867
1868 if (buffer->cbBuffer > 0)
1869 {
1870 size_t rc = 0;
1871 WinPrAsn1_OctetString octet_string = { 0 };
1872
1873 WLog_DBG(TAG, " ----->> %s", msg);
1874 octet_string.data = buffer->pvBuffer;
1875 octet_string.len = buffer->cbBuffer;
1876 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1877 if (rc != 0)
1878 res = TRUE;
1879 }
1880
1881 return res;
1882}
1883
1884static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1885 WinPrAsn1_tagId tagId, const char* msg)
1886{
1887 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1888 sspi_SecBufferFree(buffer);
1889 return rc;
1890}
1891
1900BOOL nla_send(rdpNla* nla)
1901{
1902 BOOL rc = FALSE;
1903 wStream* s = NULL;
1904 size_t length = 0;
1905 WinPrAsn1Encoder* enc = NULL;
1906
1907 WINPR_ASSERT(nla);
1908
1909 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1910 if (!enc)
1911 return FALSE;
1912
1913 /* TSRequest */
1914 WLog_DBG(TAG, "----->> sending...");
1915 if (!WinPrAsn1EncSeqContainer(enc))
1916 goto fail;
1917
1918 /* version [0] INTEGER */
1919 WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
1920 if (!WinPrAsn1EncContextualInteger(enc, 0,
1921 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
1922 goto fail;
1923
1924 /* negoTokens [1] SEQUENCE OF SEQUENCE */
1925 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
1926 {
1927 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
1928
1929 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
1930 goto fail;
1931
1932 /* negoToken [0] OCTET STRING */
1933 if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
1934 goto fail;
1935
1936 /* End negoTokens (SEQUENCE OF SEQUENCE) */
1937 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1938 goto fail;
1939 }
1940
1941 /* authInfo [2] OCTET STRING */
1942 if (nla->authInfo.cbBuffer > 0)
1943 {
1944 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
1945 goto fail;
1946 }
1947
1948 /* pubKeyAuth [3] OCTET STRING */
1949 if (nla->pubKeyAuth.cbBuffer > 0)
1950 {
1951 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
1952 goto fail;
1953 }
1954
1955 /* errorCode [4] INTEGER */
1956 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
1957 {
1958 WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
1959 nla->errorCode);
1960 if (!WinPrAsn1EncContextualInteger(
1961 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
1962 goto fail;
1963 }
1964
1965 /* clientNonce [5] OCTET STRING */
1966 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
1967 {
1968 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
1969 goto fail;
1970 }
1971
1972 /* End TSRequest */
1973 if (!WinPrAsn1EncEndContainer(enc))
1974 goto fail;
1975
1976 if (!WinPrAsn1EncStreamSize(enc, &length))
1977 goto fail;
1978
1979 s = Stream_New(NULL, length);
1980 if (!s)
1981 goto fail;
1982
1983 if (!WinPrAsn1EncToStream(enc, s))
1984 goto fail;
1985
1986 WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
1987 if (transport_write(nla->transport, s) < 0)
1988 goto fail;
1989 rc = TRUE;
1990
1991fail:
1992 Stream_Free(s, TRUE);
1993 WinPrAsn1Encoder_Free(&enc);
1994 return rc;
1995}
1996
1997static int nla_decode_ts_request(rdpNla* nla, wStream* s)
1998{
1999 WinPrAsn1Decoder dec = { 0 };
2000 WinPrAsn1Decoder dec2 = { 0 };
2001 BOOL error = FALSE;
2002 WinPrAsn1_tagId tag = { 0 };
2003 WinPrAsn1_INTEGER val = { 0 };
2004 UINT32 version = 0;
2005
2006 WINPR_ASSERT(nla);
2007 WINPR_ASSERT(s);
2008
2009 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2010
2011 WLog_DBG(TAG, "<<----- receiving...");
2012
2013 /* TSRequest */
2014 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2015 if (offset == 0)
2016 return -1;
2017 dec = dec2;
2018
2019 /* version [0] INTEGER */
2020 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2021 return -1;
2022
2023 if (!Stream_SafeSeek(s, offset))
2024 return -1;
2025
2026 version = (UINT)val;
2027 WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
2028
2029 if (nla->peerVersion == 0)
2030 nla->peerVersion = version;
2031
2032 /* if the peer suddenly changed its version - kick it */
2033 if (nla->peerVersion != version)
2034 {
2035 WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
2036 nla->peerVersion, version);
2037 return -1;
2038 }
2039
2040 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2041 {
2042 WinPrAsn1Decoder dec3 = { 0 };
2043 WinPrAsn1_OctetString octet_string = { 0 };
2044
2045 switch (tag)
2046 {
2047 case 1:
2048 WLog_DBG(TAG, " <<----- nego token");
2049 /* negoTokens [1] SEQUENCE OF SEQUENCE */
2050 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2051 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2052 return -1;
2053 /* negoToken [0] OCTET STRING */
2054 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2055 FALSE) == 0) &&
2056 error)
2057 return -1;
2058 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2059 octet_string.len))
2060 return -1;
2061 break;
2062 case 2:
2063 WLog_DBG(TAG, " <<----- auth info");
2064 /* authInfo [2] OCTET STRING */
2065 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2066 return -1;
2067 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2068 octet_string.len))
2069 return -1;
2070 break;
2071 case 3:
2072 WLog_DBG(TAG, " <<----- public key auth");
2073 /* pubKeyAuth [3] OCTET STRING */
2074 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2075 return -1;
2076 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2077 octet_string.len))
2078 return -1;
2079 break;
2080 case 4:
2081 /* errorCode [4] INTEGER */
2082 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2083 return -1;
2084 nla->errorCode = val;
2085 WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2086 nla->errorCode);
2087 break;
2088 case 5:
2089 WLog_DBG(TAG, " <<----- client nonce");
2090 /* clientNonce [5] OCTET STRING */
2091 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2092 return -1;
2093 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2094 octet_string.len))
2095 return -1;
2096 break;
2097 default:
2098 return -1;
2099 }
2100 }
2101
2102 return 1;
2103}
2104
2105int nla_recv_pdu(rdpNla* nla, wStream* s)
2106{
2107 WINPR_ASSERT(nla);
2108 WINPR_ASSERT(s);
2109
2110 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2111 {
2112 UINT32 code = 0;
2113 Stream_Read_UINT32(s, code);
2114 if (code != AUTHZ_SUCCESS)
2115 {
2116 WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
2117 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2118 freerdp_set_last_error_log(nla->rdpcontext, code);
2119 return -1;
2120 }
2121 else
2122 WLog_DBG(TAG, "Early User Auth active: SUCCESS");
2123 }
2124 else
2125 {
2126 if (nla_decode_ts_request(nla, s) < 1)
2127 return -1;
2128
2129 if (nla->errorCode)
2130 {
2131 UINT32 code = 0;
2132
2133 switch (nla->errorCode)
2134 {
2135 case STATUS_PASSWORD_MUST_CHANGE:
2136 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2137 break;
2138
2139 case STATUS_PASSWORD_EXPIRED:
2140 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2141 break;
2142
2143 case STATUS_ACCOUNT_DISABLED:
2144 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2145 break;
2146
2147 case STATUS_LOGON_FAILURE:
2148 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2149 break;
2150
2151 case STATUS_WRONG_PASSWORD:
2152 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2153 break;
2154
2155 case STATUS_ACCESS_DENIED:
2156 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2157 break;
2158
2159 case STATUS_ACCOUNT_RESTRICTION:
2160 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2161 break;
2162
2163 case STATUS_ACCOUNT_LOCKED_OUT:
2164 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2165 break;
2166
2167 case STATUS_ACCOUNT_EXPIRED:
2168 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2169 break;
2170
2171 case STATUS_LOGON_TYPE_NOT_GRANTED:
2172 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2173 break;
2174
2175 default:
2176 WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIX32 "]",
2177 NtStatus2Tag(nla->errorCode), nla->errorCode);
2178 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2179 break;
2180 }
2181
2182 freerdp_set_last_error_log(nla->rdpcontext, code);
2183 return -1;
2184 }
2185 }
2186
2187 return nla_client_recv(nla);
2188}
2189
2190int nla_server_recv(rdpNla* nla)
2191{
2192 int status = -1;
2193
2194 WINPR_ASSERT(nla);
2195
2196 wStream* s = nla_server_recv_stream(nla);
2197 if (!s)
2198 goto fail;
2199 status = nla_decode_ts_request(nla, s);
2200
2201fail:
2202 Stream_Free(s, TRUE);
2203 return status;
2204}
2205
2215rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2216{
2217 WINPR_ASSERT(transport);
2218 WINPR_ASSERT(context);
2219
2220 rdpSettings* settings = context->settings;
2221 WINPR_ASSERT(settings);
2222
2223 rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2224
2225 if (!nla)
2226 return NULL;
2227
2228 nla->rdpcontext = context;
2229 nla->server = settings->ServerMode;
2230 nla->transport = transport;
2231 nla->sendSeqNum = 0;
2232 nla->recvSeqNum = 0;
2233 nla->version = 6;
2234 nla->earlyUserAuth = FALSE;
2235
2236 nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2237 if (!nla->identity)
2238 goto cleanup;
2239
2240 nla->auth = credssp_auth_new(context);
2241 if (!nla->auth)
2242 goto cleanup;
2243
2244 /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2245 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2246 goto cleanup;
2247
2248 /* generate random 32-byte nonce */
2249 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2250 goto cleanup;
2251
2252 return nla;
2253cleanup:
2254 WINPR_PRAGMA_DIAG_PUSH
2255 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2256 nla_free(nla);
2257 WINPR_PRAGMA_DIAG_POP
2258 return NULL;
2259}
2260
2266void nla_free(rdpNla* nla)
2267{
2268 if (!nla)
2269 return;
2270
2271 smartcardCertInfo_Free(nla->smartcardCert);
2272 nla_buffer_free(nla);
2273 sspi_SecBufferFree(&nla->tsCredentials);
2274 credssp_auth_free(nla->auth);
2275
2276 sspi_FreeAuthIdentity(nla->identity);
2277 free(nla->pkinitArgs);
2278 free(nla->identity);
2279 free(nla);
2280}
2281
2282SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2283{
2284 if (!nla)
2285 return NULL;
2286
2287 return nla->identity;
2288}
2289
2290NLA_STATE nla_get_state(const rdpNla* nla)
2291{
2292 if (!nla)
2293 return NLA_STATE_FINAL;
2294
2295 return nla->state;
2296}
2297
2298BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2299{
2300 if (!nla)
2301 return FALSE;
2302
2303 WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2304 nla->state = state;
2305 return TRUE;
2306}
2307
2308BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2309{
2310 if (!credssp_auth_set_spn(nla->auth, service, hostname))
2311 return FALSE;
2312 return TRUE;
2313}
2314
2315BOOL nla_impersonate(rdpNla* nla)
2316{
2317 return credssp_auth_impersonate(nla->auth);
2318}
2319
2320BOOL nla_revert_to_self(rdpNla* nla)
2321{
2322 return credssp_auth_revert_to_self(nla->auth);
2323}
2324
2325const char* nla_get_state_str(NLA_STATE state)
2326{
2327 switch (state)
2328 {
2329 case NLA_STATE_INITIAL:
2330 return "NLA_STATE_INITIAL";
2331 case NLA_STATE_NEGO_TOKEN:
2332 return "NLA_STATE_NEGO_TOKEN";
2333 case NLA_STATE_PUB_KEY_AUTH:
2334 return "NLA_STATE_PUB_KEY_AUTH";
2335 case NLA_STATE_AUTH_INFO:
2336 return "NLA_STATE_AUTH_INFO";
2337 case NLA_STATE_POST_NEGO:
2338 return "NLA_STATE_POST_NEGO";
2339 case NLA_STATE_EARLY_USER_AUTH:
2340 return "NLA_STATE_EARLY_USER_AUTH";
2341 case NLA_STATE_FINAL:
2342 return "NLA_STATE_FINAL";
2343 default:
2344 return "UNKNOWN";
2345 }
2346}
2347
2348DWORD nla_get_error(const rdpNla* nla)
2349{
2350 if (!nla)
2351 return ERROR_INTERNAL_ERROR;
2352 return (UINT32)nla->errorCode;
2353}
2354
2355INT32 nla_get_sspi_error(const rdpNla* nla)
2356{
2357 WINPR_ASSERT(nla);
2358 return credssp_auth_sspi_error(nla->auth);
2359}
2360
2361BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2362{
2363 WINPR_ASSERT(nla);
2364 WINPR_ASSERT(inBuffer);
2365 WINPR_ASSERT(outBuffer);
2366 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, NULL, nla->sendSeqNum++);
2367}
2368
2369BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2370{
2371 WINPR_ASSERT(nla);
2372 WINPR_ASSERT(inBuffer);
2373 WINPR_ASSERT(outBuffer);
2374 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2375}
2376
2377SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2378{
2379 WINPR_ASSERT(nla);
2380
2381 SecurityFunctionTable* table = NULL;
2382 CtxtHandle context = { 0 };
2383 credssp_auth_tableAndContext(nla->auth, &table, &context);
2384
2385 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2386}
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.