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