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