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