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(nullptr, TRUE);
312 if (sam)
313 {
314 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
315 WINPR_SAM_ENTRY* entry =
316 SamLookupUserA(sam, settings->Username,
317 userLength + 1 /* ensure '\0' is checked too */, nullptr, 0);
318 if (entry)
319 {
324 PromptPassword = FALSE;
325 SamFreeEntry(sam, entry);
326 }
327
328 SamClose(sam);
329 }
330 }
331
332 if (PromptPassword)
333 {
334 if (settings->RestrictedAdminModeRequired)
335 {
336 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
337 PromptPassword = FALSE;
338 }
339
340 if (settings->RemoteCredentialGuard)
341 PromptPassword = FALSE;
342 }
343
344 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
345 if (PromptPassword)
346 {
347 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
348 {
349 case AUTH_SKIP:
350 case AUTH_SUCCESS:
351 break;
352 case AUTH_CANCELLED:
353 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
354 return FALSE;
355 case AUTH_NO_CREDENTIALS:
356 WLog_INFO(TAG, "No credentials provided - using nullptr identity");
357 break;
358 default:
359 return FALSE;
360 }
361 }
362
363 if (!settings->Username)
364 {
365 sspi_FreeAuthIdentity(nla->identity);
366 free(nla->identity);
367 nla->identity = nullptr;
368 }
369 else if (settings->SmartcardLogon)
370 {
371 if (smartCardLogonWasDisabled)
372 {
373 if (!nla_adjust_settings_from_smartcard(nla))
374 return FALSE;
375 }
376
377 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
378 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
379 sizeof(nla->certSha1)))
380 return FALSE;
381 }
382 else
383 {
384 BOOL usePassword = TRUE;
385
386 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
387 {
388 const WCHAR* wstr = (const WCHAR*)settings->RedirectionPassword;
389 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength / sizeof(WCHAR));
390
391 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
392 FreeRDP_Domain, wstr, len))
393 return FALSE;
394
395 usePassword = FALSE;
396 }
397
398 if (settings->RestrictedAdminModeRequired)
399 {
400 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
401 {
402 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
403 FreeRDP_Domain, FreeRDP_PasswordHash))
404 return FALSE;
405
411 nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
412 usePassword = FALSE;
413 }
414 }
415
416 if (usePassword)
417 {
418 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
419 FreeRDP_Domain, FreeRDP_Password))
420 return FALSE;
421 }
422 }
423
424 return TRUE;
425}
426
427static int nla_client_init(rdpNla* nla)
428{
429 WINPR_ASSERT(nla);
430 WINPR_ASSERT(nla->rdpcontext);
431
432 rdpSettings* settings = nla->rdpcontext->settings;
433 WINPR_ASSERT(settings);
434
435 nla_set_state(nla, NLA_STATE_INITIAL);
436
437 if (!nla_adjust_settings_from_smartcard(nla))
438 return -1;
439
440 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, nullptr))
441 return -1;
442
443 if (!nla_client_setup_identity(nla))
444 return -1;
445
446 const char* hostname = freerdp_settings_get_server_name(settings);
447
448 if (!credssp_auth_setup_client(nla->auth, "TERMSRV", hostname, nla->identity, nla->pkinitArgs))
449 return -1;
450
451 const BYTE* data = nullptr;
452 DWORD length = 0;
453 if (!transport_get_public_key(nla->transport, &data, &length))
454 {
455 WLog_ERR(TAG, "Failed to get public key");
456 return -1;
457 }
458
459 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
460 {
461 WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
462 return -1;
463 }
464
465 return 1;
466}
467
468int nla_client_begin(rdpNla* nla)
469{
470 WINPR_ASSERT(nla);
471
472 if (nla_client_init(nla) < 1)
473 return -1;
474
475 if (nla_get_state(nla) != NLA_STATE_INITIAL)
476 return -1;
477
478 /*
479 * from tspkg.dll: 0x00000132
480 * ISC_REQ_MUTUAL_AUTH
481 * ISC_REQ_CONFIDENTIALITY
482 * ISC_REQ_USE_SESSION_KEY
483 * ISC_REQ_ALLOCATE_MEMORY
484 */
485 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
486
487 const int rc = credssp_auth_authenticate(nla->auth);
488
489 switch (rc)
490 {
491 case 0:
492 if (!nla_send(nla))
493 return -1;
494 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
495 break;
496 case 1:
497 if (credssp_auth_have_output_token(nla->auth))
498 {
499 if (!nla_send(nla))
500 return -1;
501 }
502 nla_set_state(nla, NLA_STATE_FINAL);
503 break;
504 default:
505 switch (credssp_auth_sspi_error(nla->auth))
506 {
507 case SEC_E_LOGON_DENIED:
508 case SEC_E_NO_CREDENTIALS:
509 freerdp_set_last_error_log(nla->rdpcontext,
510 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
511 break;
512 default:
513 break;
514 }
515 return -1;
516 }
517
518 return 1;
519}
520
521static int nla_client_recv_nego_token(rdpNla* nla)
522{
523 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
524 const int rc = credssp_auth_authenticate(nla->auth);
525
526 switch (rc)
527 {
528 case 0:
529 if (!nla_send(nla))
530 return -1;
531 break;
532 case 1: /* completed */
533 {
534 int res = -1;
535 if (nla->peerVersion < 5)
536 res = nla_encrypt_public_key_echo(nla);
537 else
538 res = nla_encrypt_public_key_hash(nla);
539
540 if (!res)
541 return -1;
542
543 if (!nla_send(nla))
544 return -1;
545
546 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
547 }
548 break;
549
550 default:
551 return -1;
552 }
553
554 return 1;
555}
556
557static int nla_client_recv_pub_key_auth(rdpNla* nla)
558{
559 BOOL rc = FALSE;
560
561 WINPR_ASSERT(nla);
562
563 /* Verify Server Public Key Echo */
564 if (nla->peerVersion < 5)
565 rc = nla_decrypt_public_key_echo(nla);
566 else
567 rc = nla_decrypt_public_key_hash(nla);
568
569 sspi_SecBufferFree(&nla->pubKeyAuth);
570
571 if (!rc)
572 return -1;
573
574 /* Send encrypted credentials */
575 rc = nla_encrypt_ts_credentials(nla);
576 if (!rc)
577 return -1;
578
579 if (!nla_send(nla))
580 return -1;
581
582 if (nla->earlyUserAuth)
583 {
584 transport_set_early_user_auth_mode(nla->transport, TRUE);
585 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
586 }
587 else
588 nla_set_state(nla, NLA_STATE_AUTH_INFO);
589 return 1;
590}
591
592static int nla_client_recv_early_user_auth(rdpNla* nla)
593{
594 WINPR_ASSERT(nla);
595
596 transport_set_early_user_auth_mode(nla->transport, FALSE);
597 nla_set_state(nla, NLA_STATE_AUTH_INFO);
598 return 1;
599}
600
601static int nla_client_recv(rdpNla* nla)
602{
603 WINPR_ASSERT(nla);
604
605 switch (nla_get_state(nla))
606 {
607 case NLA_STATE_NEGO_TOKEN:
608 return nla_client_recv_nego_token(nla);
609
610 case NLA_STATE_PUB_KEY_AUTH:
611 return nla_client_recv_pub_key_auth(nla);
612
613 case NLA_STATE_EARLY_USER_AUTH:
614 return nla_client_recv_early_user_auth(nla);
615
616 case NLA_STATE_FINAL:
617 default:
618 WLog_ERR(TAG, "NLA in invalid client receive state %s",
619 nla_get_state_str(nla_get_state(nla)));
620 return -1;
621 }
622}
623
624static int nla_client_authenticate(rdpNla* nla)
625{
626 int rc = -1;
627
628 WINPR_ASSERT(nla);
629
630 wStream* s = Stream_New(nullptr, 4096);
631
632 if (!s)
633 {
634 WLog_ERR(TAG, "Stream_New failed!");
635 return -1;
636 }
637
638 if (nla_client_begin(nla) < 1)
639 goto fail;
640
641 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
642 {
643 Stream_ResetPosition(s);
644 const int status = transport_read_pdu(nla->transport, s);
645
646 if (status < 0)
647 {
648 WLog_ERR(TAG, "nla_client_authenticate failure");
649 goto fail;
650 }
651
652 const int status2 = nla_recv_pdu(nla, s);
653
654 if (status2 < 0)
655 goto fail;
656 }
657
658 rc = 1;
659fail:
660 Stream_Free(s, TRUE);
661 return rc;
662}
663
668static int nla_server_init(rdpNla* nla)
669{
670 WINPR_ASSERT(nla);
671
672 const BYTE* data = nullptr;
673 DWORD length = 0;
674 if (!transport_get_public_key(nla->transport, &data, &length))
675 {
676 WLog_ERR(TAG, "Failed to get public key");
677 return -1;
678 }
679
680 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
681 {
682 WLog_ERR(TAG, "Failed to allocate SecBuffer for public key");
683 return -1;
684 }
685
686 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG, nullptr))
687 return -1;
688
689 if (!credssp_auth_setup_server(nla->auth))
690 return -1;
691
692 nla_set_state(nla, NLA_STATE_INITIAL);
693 return 1;
694}
695
696static wStream* nla_server_recv_stream(rdpNla* nla)
697{
698 wStream* s = nullptr;
699 int status = -1;
700
701 WINPR_ASSERT(nla);
702
703 s = Stream_New(nullptr, 4096);
704
705 if (!s)
706 goto fail;
707
708 status = transport_read_pdu(nla->transport, s);
709
710fail:
711 if (status < 0)
712 {
713 WLog_ERR(TAG, "nla_recv() error: %d", status);
714 Stream_Free(s, TRUE);
715 return nullptr;
716 }
717
718 return s;
719}
720
721static BOOL nla_server_recv_credentials(rdpNla* nla)
722{
723 WINPR_ASSERT(nla);
724
725 if (nla_server_recv(nla) < 0)
726 return FALSE;
727
728 if (!nla_decrypt_ts_credentials(nla))
729 return FALSE;
730
731 if (!nla_impersonate(nla))
732 return FALSE;
733
734 if (!nla_revert_to_self(nla))
735 return FALSE;
736
737 return TRUE;
738}
739
747static int nla_server_authenticate(rdpNla* nla)
748{
749 int ret = -1;
750
751 WINPR_ASSERT(nla);
752
753 if (nla_server_init(nla) < 1)
754 goto fail;
755
756 /*
757 * from tspkg.dll: 0x00000112
758 * ASC_REQ_MUTUAL_AUTH
759 * ASC_REQ_CONFIDENTIALITY
760 * ASC_REQ_ALLOCATE_MEMORY
761 */
762 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
763 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
764 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
765
766 /* Client is starting, here es the state machine:
767 *
768 * -- NLA_STATE_INITIAL --> NLA_STATE_INITIAL
769 * ----->> sending...
770 * ----->> protocol version 6
771 * ----->> nego token
772 * ----->> client nonce
773 * <<----- receiving...
774 * <<----- protocol version 6
775 * <<----- nego token
776 * ----->> sending...
777 * ----->> protocol version 6
778 * ----->> nego token
779 * ----->> public key auth
780 * ----->> client nonce
781 * -- NLA_STATE_NEGO_TOKEN --> NLA_STATE_PUB_KEY_AUTH
782 * <<----- receiving...
783 * <<----- protocol version 6
784 * <<----- public key info
785 * ----->> sending...
786 * ----->> protocol version 6
787 * ----->> auth info
788 * ----->> client nonce
789 * -- NLA_STATE_PUB_KEY_AUTH --> NLA_STATE
790 */
791
792 while (TRUE)
793 {
794 int res = -1;
795
796 if (nla_server_recv(nla) < 0)
797 goto fail;
798
799 WLog_DBG(TAG, "Receiving Authentication Token");
800 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
801
802 res = credssp_auth_authenticate(nla->auth);
803
804 if (res == -1)
805 {
806 /* Special handling of these specific error codes as NTSTATUS_FROM_WIN32
807 unfortunately does not map directly to the corresponding NTSTATUS values
808 */
809 switch (GetLastError())
810 {
811 case ERROR_PASSWORD_MUST_CHANGE:
812 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
813 break;
814
815 case ERROR_PASSWORD_EXPIRED:
816 nla->errorCode = STATUS_PASSWORD_EXPIRED;
817 break;
818
819 case ERROR_ACCOUNT_DISABLED:
820 nla->errorCode = STATUS_ACCOUNT_DISABLED;
821 break;
822
823 default:
824 nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
825 break;
826 }
827
828 (void)nla_send(nla);
829 /* Access Denied */
830 goto fail;
831 }
832
833 if (res == 1)
834 {
835 /* Process final part of the nego token exchange */
836 if (credssp_auth_have_output_token(nla->auth))
837 {
838 if (!nla_send(nla))
839 goto fail;
840
841 if (nla_server_recv(nla) < 0)
842 goto fail;
843
844 WLog_DBG(TAG, "Receiving pubkey Token");
845 }
846
847 if (nla->peerVersion < 5)
848 res = nla_decrypt_public_key_echo(nla);
849 else
850 res = nla_decrypt_public_key_hash(nla);
851
852 if (!res)
853 goto fail;
854
855 /* Clear nego token buffer or we will send it again to the client */
856 sspi_SecBufferFree(&nla->negoToken);
857
858 if (nla->peerVersion < 5)
859 res = nla_encrypt_public_key_echo(nla);
860 else
861 res = nla_encrypt_public_key_hash(nla);
862
863 if (!res)
864 goto fail;
865 }
866
867 /* send authentication token */
868 WLog_DBG(TAG, "Sending Authentication Token");
869
870 if (!nla_send(nla))
871 goto fail;
872
873 if (res == 1)
874 {
875 ret = 1;
876 break;
877 }
878 }
879
880 /* Receive encrypted credentials */
881 if (!nla_server_recv_credentials(nla))
882 ret = -1;
883
884fail:
885 nla_buffer_free(nla);
886 return ret;
887}
888
896int nla_authenticate(rdpNla* nla)
897{
898 WINPR_ASSERT(nla);
899
900 if (nla->server)
901 return nla_server_authenticate(nla);
902 else
903 return nla_client_authenticate(nla);
904}
905
906static void ap_integer_increment_le(BYTE* number, size_t size)
907{
908 WINPR_ASSERT(number || (size == 0));
909
910 for (size_t index = 0; index < size; index++)
911 {
912 if (number[index] < 0xFF)
913 {
914 number[index]++;
915 break;
916 }
917 else
918 {
919 number[index] = 0;
920 continue;
921 }
922 }
923}
924
925static void ap_integer_decrement_le(BYTE* number, size_t size)
926{
927 WINPR_ASSERT(number || (size == 0));
928
929 for (size_t index = 0; index < size; index++)
930 {
931 if (number[index] > 0)
932 {
933 number[index]--;
934 break;
935 }
936 else
937 {
938 number[index] = 0xFF;
939 continue;
940 }
941 }
942}
943
944BOOL nla_encrypt_public_key_echo(rdpNla* nla)
945{
946 BOOL status = FALSE;
947
948 WINPR_ASSERT(nla);
949
950 sspi_SecBufferFree(&nla->pubKeyAuth);
951 if (nla->server)
952 {
953 SecBuffer buf = WINPR_C_ARRAY_INIT;
954 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
955 return FALSE;
956 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
957 status =
958 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, nullptr, nla->sendSeqNum++);
959 sspi_SecBufferFree(&buf);
960 }
961 else
962 {
963 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth, nullptr,
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 = nullptr;
974 SecBuffer buf = WINPR_C_ARRAY_INIT;
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, nullptr, 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 = WINPR_C_ARRAY_INIT;
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 = nullptr;
1058 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
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 = WINPR_C_ARRAY_INIT;
1067
1068 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1069 return FALSE;
1070
1071 /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1072 if (!(sha256 = winpr_Digest_New()))
1073 goto fail;
1074
1075 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1076 goto fail;
1077
1078 /* include trailing \0 from hashMagic */
1079 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1080 goto fail;
1081
1082 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1083 goto fail;
1084
1085 /* SubjectPublicKey */
1086 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1087 goto fail;
1088
1089 if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1090 goto fail;
1091
1092 /* verify hash */
1093 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1094 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1095 {
1096 WLog_ERR(TAG, "Could not verify server's hash");
1097 /* DO NOT SEND CREDENTIALS! */
1098 goto fail;
1099 }
1100
1101 status = TRUE;
1102fail:
1103 winpr_Digest_Free(sha256);
1104 sspi_SecBufferFree(&hash);
1105 return status;
1106}
1107
1108static BOOL set_creds_octetstring_to_settings(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1109 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1110 rdpSettings* settings)
1111{
1112 if (optional)
1113 {
1114 WinPrAsn1_tagId itemTag = 0;
1115 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1116 return TRUE;
1117 }
1118
1119 BOOL error = FALSE;
1121 /* note: not checking "error" value, as the not present optional item case is handled above
1122 * if the function fails it's because of a real error not because the item is not present
1123 */
1124 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1125 return FALSE;
1126
1127 return freerdp_settings_set_string_from_utf16N(settings, settingId, (const WCHAR*)value.data,
1128 value.len / sizeof(WCHAR));
1129}
1130
1131static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* settings)
1132{
1133 BOOL error = FALSE;
1134
1135 /* keySpec [0] INTEGER */
1136 WinPrAsn1_INTEGER keyspec = 0;
1137 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1138 return FALSE;
1139 settings->KeySpec = (UINT32)keyspec;
1140
1141 /* cardName [1] OCTET STRING OPTIONAL */
1142 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1143 return FALSE;
1144
1145 /* readerName [2] OCTET STRING OPTIONAL */
1146 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1147 return FALSE;
1148
1149 /* containerName [3] OCTET STRING OPTIONAL */
1150 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1151 return FALSE;
1152
1153 /* cspName [4] OCTET STRING OPTIONAL */
1154 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1155}
1156
1157static BOOL nla_messageTypeValid(UINT32 type)
1158{
1159 switch (type)
1160 {
1161 case KerbInvalidValue:
1162 case KerbInteractiveLogon:
1163 case KerbSmartCardLogon:
1164 case KerbWorkstationUnlockLogon:
1165 case KerbSmartCardUnlockLogon:
1166 case KerbProxyLogon:
1167 case KerbTicketLogon:
1168 case KerbTicketUnlockLogon:
1169#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1170 case KerbS4ULogon:
1171#endif
1172#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1173 case KerbCertificateLogon:
1174 case KerbCertificateS4ULogon:
1175 case KerbCertificateUnlockLogon:
1176#endif
1177#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1178 case KerbNoElevationLogon:
1179 case KerbLuidLogon:
1180#endif
1181 return TRUE;
1182 default:
1183 WLog_ERR(TAG, "Invalid message type %" PRIu32, type);
1184 return FALSE;
1185 }
1186}
1187
1188static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla, wStream* s,
1189 KERB_TICKET_LOGON* ticket)
1190{
1191 WINPR_ASSERT(nla);
1192
1193 if (!ticket)
1194 return FALSE;
1195
1196 /* mysterious extra 16 bytes before TGS/TGT content */
1197 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1198 return FALSE;
1199
1200 {
1201 const UINT32 type = Stream_Get_UINT32(s);
1202 if (!nla_messageTypeValid(type))
1203 return FALSE;
1204
1205 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1206 }
1207 Stream_Read_UINT32(s, ticket->Flags);
1208 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1209 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1210
1211 if (ticket->MessageType != KerbTicketLogon)
1212 {
1213 WLog_ERR(TAG, "Not a KerbTicketLogon");
1214 return FALSE;
1215 }
1216
1217 if (!Stream_CheckAndLogRequiredLength(
1218 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1219 return FALSE;
1220
1221 /* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
1222 Stream_Seek(s, 16);
1223
1224 /*WLog_INFO(TAG, "TGS");
1225 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
1226 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1227 Stream_Seek(s, ticket->ServiceTicketLength);
1228
1229 /*WLog_INFO(TAG, "TGT");
1230 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
1231 ticket->TicketGrantingTicketLength);*/
1232 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1233 return TRUE;
1234}
1235
1236static BOOL nla_credentialTypeValid(UINT32 type)
1237{
1238 switch (type)
1239 {
1240 case InvalidCredKey:
1241 case DeprecatedIUMCredKey:
1242 case DomainUserCredKey:
1243 case LocalUserCredKey:
1244 case ExternallySuppliedCredKey:
1245 return TRUE;
1246 default:
1247 WLog_ERR(TAG, "Invalid credential type %" PRIu32, type);
1248 return FALSE;
1249 }
1250}
1251
1252WINPR_ATTR_MALLOC(free, 1)
1253WINPR_ATTR_NODISCARD
1254static MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* nla_read_NtlmCreds(WINPR_ATTR_UNUSED rdpNla* nla,
1255 wStream* s)
1256{
1257 WINPR_ASSERT(nla);
1258 WINPR_ASSERT(s);
1259
1260 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1261 return nullptr;
1262
1263 size_t pos = Stream_GetPosition(s);
1264 Stream_Seek(s, 32);
1265
1266 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1267 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1268 return nullptr;
1269
1270 if (!Stream_SetPosition(s, pos))
1271 return nullptr;
1272
1274 1, sizeof(MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL) - 1 + EncryptedCredsSize);
1275 if (!ret)
1276 return nullptr;
1277
1278 ret->Version = Stream_Get_UINT32(s);
1279 ret->Flags = Stream_Get_UINT32(s);
1280 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1281 {
1282 const UINT32 val = Stream_Get_UINT32(s);
1283 if (!nla_credentialTypeValid(val))
1284 {
1285 free(ret);
1286 return nullptr;
1287 }
1288 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1289 }
1290 ret->EncryptedCredsSize = EncryptedCredsSize;
1291 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1292
1293 return ret;
1294}
1295
1297typedef enum
1298{
1299 RCG_TYPE_NONE,
1300 RCG_TYPE_KERB,
1301 RCG_TYPE_NTLM
1302} RemoteGuardPackageCredType;
1303
1304static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla, WinPrAsn1Decoder* dec,
1305 RemoteGuardPackageCredType* credsType,
1306 wStream* payload)
1307{
1308 WinPrAsn1_OctetString packageName = WINPR_C_ARRAY_INIT;
1309 WinPrAsn1_OctetString credBuffer = WINPR_C_ARRAY_INIT;
1310 BOOL error = FALSE;
1311 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1312
1313 WINPR_ASSERT(nla);
1314 WINPR_ASSERT(dec);
1315 WINPR_ASSERT(credsType);
1316 WINPR_ASSERT(payload);
1317
1318 *credsType = RCG_TYPE_NONE;
1319
1320 /* packageName [0] OCTET STRING */
1321 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1322 return FALSE;
1323
1324 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
1325 packageNameStr, sizeof(packageNameStr));
1326 WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1327
1328 /* credBuffer [1] OCTET STRING, */
1329 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1330 return FALSE;
1331
1332 if (_stricmp(packageNameStr, "Kerberos") == 0)
1333 {
1334 *credsType = RCG_TYPE_KERB;
1335 }
1336 else if (_stricmp(packageNameStr, "NTLM") == 0)
1337 {
1338 *credsType = RCG_TYPE_NTLM;
1339 }
1340 else
1341 {
1342 WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1343 return FALSE;
1344 }
1345
1346 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1347 return TRUE;
1348}
1349
1351typedef enum
1352{
1353 TSCREDS_INVALID = 0,
1354 TSCREDS_USER_PASSWD = 1,
1355 TSCREDS_SMARTCARD = 2,
1356 TSCREDS_REMOTEGUARD = 6
1357} TsCredentialsType;
1358
1359static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1360{
1361 WinPrAsn1Decoder dec = WinPrAsn1Decoder_init();
1362 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
1363 WinPrAsn1_OctetString credentials = WINPR_C_ARRAY_INIT;
1364 BOOL error = FALSE;
1365 WinPrAsn1_INTEGER credType = -1;
1366 BOOL ret = TRUE;
1367
1368 WINPR_ASSERT(nla);
1369 WINPR_ASSERT(data);
1370
1371 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1372
1373 /* TSCredentials */
1374 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1375 return FALSE;
1376 dec = dec2;
1377
1378 /* credType [0] INTEGER */
1379 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1380 return FALSE;
1381
1382 /* credentials [1] OCTET STRING */
1383 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1384 return FALSE;
1385
1386 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1387
1388 rdpSettings* settings = nla->rdpcontext->settings;
1389 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1390 credType != TSCREDS_REMOTEGUARD)
1391 {
1392 WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1393 return FALSE;
1394 }
1395
1396 switch (credType)
1397 {
1398 case TSCREDS_USER_PASSWD:
1399 {
1400 /* TSPasswordCreds */
1401 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1402 return FALSE;
1403 dec = dec2;
1404
1405 /* domainName [0] OCTET STRING */
1406 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1407 return FALSE;
1408
1409 /* userName [1] OCTET STRING */
1410 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1411 return FALSE;
1412
1413 /* password [2] OCTET STRING */
1414 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1415 }
1416 case TSCREDS_SMARTCARD:
1417 {
1418 /* TSSmartCardCreds */
1419 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1420 return FALSE;
1421 dec = dec2;
1422
1423 /* pin [0] OCTET STRING, */
1424 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1425 return FALSE;
1426 settings->PasswordIsSmartcardPin = TRUE;
1427
1428 /* cspData [1] TSCspDataDetail */
1429 WinPrAsn1Decoder cspDetails = WinPrAsn1Decoder_init();
1430 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1431 return FALSE;
1432 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1433 return FALSE;
1434
1435 /* userHint [2] OCTET STRING OPTIONAL */
1436 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1437 return FALSE;
1438
1439 /* domainHint [3] OCTET STRING OPTIONAL */
1440 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1441 }
1442 case TSCREDS_REMOTEGUARD:
1443 {
1444 /* TSRemoteGuardCreds */
1445 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1446 return FALSE;
1447
1448 /* logonCred[0] TSRemoteGuardPackageCred */
1449 KERB_TICKET_LOGON kerbLogon = { .MessageType = KerbInvalidValue,
1450 .Flags = 0,
1451 .ServiceTicketLength = 0,
1452 .TicketGrantingTicketLength = 0,
1453 .ServiceTicket = nullptr,
1454 .TicketGrantingTicket = nullptr };
1455
1456 WinPrAsn1Decoder logonCredsSeq = WinPrAsn1Decoder_init();
1457
1458 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1459 return FALSE;
1460
1461 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1462 wStream logonPayload = WINPR_C_ARRAY_INIT;
1463 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1464 &logonPayload))
1465 return FALSE;
1466 if (logonCredsType != RCG_TYPE_KERB)
1467 {
1468 WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1469 return FALSE;
1470 }
1471
1472 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1473 {
1474 WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1475 return FALSE;
1476 }
1477
1478 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1479 MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds = nullptr;
1480 WinPrAsn1Decoder suppCredsSeq = WinPrAsn1Decoder_init();
1481
1482 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1483 Stream_GetRemainingLength(&suppCredsSeq.source))
1484 {
1485 WinPrAsn1Decoder ntlmCredsSeq = WinPrAsn1Decoder_init();
1486 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1487 return FALSE;
1488
1489 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1490 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1491 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1492 &ntlmPayload))
1493 return FALSE;
1494
1495 if (suppCredsType != RCG_TYPE_NTLM)
1496 {
1497 WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1498 return FALSE;
1499 }
1500
1501 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1502 if (!suppCreds)
1503 {
1504 WLog_ERR(TAG, "invalid supplementalCreds");
1505 return FALSE;
1506 }
1507 }
1508 else if (error)
1509 {
1510 WLog_ERR(TAG, "invalid supplementalCreds");
1511 return FALSE;
1512 }
1513
1514 freerdp_peer* peer = nla->rdpcontext->peer;
1515 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1516 free(suppCreds);
1517 break;
1518 }
1519 default:
1520 WLog_DBG(TAG, "TSCredentials type %d not supported for now", credType);
1521 ret = FALSE;
1522 break;
1523 }
1524
1525 return ret;
1526}
1527
1528static BOOL nla_write_KERB_TICKET_LOGON(wStream* s, const KERB_TICKET_LOGON* ticket)
1529{
1530 WINPR_ASSERT(ticket);
1531
1532 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1533 ticket->TicketGrantingTicketLength))
1534 return FALSE;
1535
1536 Stream_Write_UINT32(s, KerbTicketLogon);
1537 Stream_Write_UINT32(s, ticket->Flags);
1538 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1539 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1540
1541 Stream_Write_UINT64(s, 0x20); /* offset of TGS in the packet */
1542 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength); /* offset of TGT in packet */
1543
1544 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1545 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1546 return TRUE;
1547}
1548
1549static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla, KERB_TICKET_LOGON* logonTicket)
1550{
1551 WINPR_ASSERT(nla);
1552 WINPR_ASSERT(logonTicket);
1553
1554 SecurityFunctionTable* table = nullptr;
1555 CtxtHandle context = WINPR_C_ARRAY_INIT;
1556 credssp_auth_tableAndContext(nla->auth, &table, &context);
1557 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1558 SEC_E_OK;
1559}
1560
1561static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1562{
1563 BOOL ret = FALSE;
1564 wStream* s = nullptr;
1565 char kerberos[] = { 'K', '\0', 'e', '\0', 'r', '\0', 'b', '\0',
1566 'e', '\0', 'r', '\0', 'o', '\0', 's', '\0' };
1567 WinPrAsn1_OctetString packageName = { sizeof(kerberos), (BYTE*)kerberos };
1568 WinPrAsn1_OctetString credBuffer;
1569 KERB_TICKET_LOGON logonTicket;
1570
1571 logonTicket.ServiceTicket = nullptr;
1572 logonTicket.TicketGrantingTicket = nullptr;
1573
1574 /* packageName [0] OCTET STRING */
1575 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1576 goto out;
1577
1578 /* credBuffer [1] OCTET STRING */
1579 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1580 goto out;
1581
1582 s = Stream_New(nullptr, 2000);
1583 if (!s)
1584 goto out;
1585
1586 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1587 goto out;
1588
1589 credBuffer.len = Stream_GetPosition(s);
1590 credBuffer.data = Stream_Buffer(s);
1591 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1592
1593out:
1594 free(logonTicket.ServiceTicket);
1595 free(logonTicket.TicketGrantingTicket);
1596 Stream_Free(s, TRUE);
1597 return ret;
1598}
1599
1600static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1602{
1603 WINPR_UNUSED(nla);
1604 BOOL ret = FALSE;
1605 BYTE ntlm[] = { 'N', '\0', 'T', '\0', 'L', '\0', 'M', '\0' };
1606 const WinPrAsn1_OctetString packageName = { sizeof(ntlm), ntlm };
1607
1608 /* packageName [0] OCTET STRING */
1609 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1610 return FALSE;
1611
1612 /* credBuffer [1] OCTET STRING */
1613 wStream* s = Stream_New(nullptr, 300);
1614 if (!s)
1615 goto out;
1616
1617 Stream_Write_UINT32(s, pntlm->Version); /* Version */
1618 Stream_Write_UINT32(s, pntlm->Flags); /* Flags */
1619
1620 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1621 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1622 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1623 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1624 Stream_Zero(s, 6 + 16 * 4 + 14);
1625
1626 {
1627 WinPrAsn1_OctetString credBuffer = { Stream_GetPosition(s), Stream_Buffer(s) };
1628 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1629 }
1630
1631out:
1632 Stream_Free(s, TRUE);
1633 return ret;
1634}
1635
1636static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1637{
1638 struct
1639 {
1640 WinPrAsn1_tagId tag;
1641 FreeRDP_Settings_Keys_String setting_id;
1642 } cspData_fields[] = { { 1, FreeRDP_CardName },
1643 { 2, FreeRDP_ReaderName },
1644 { 3, FreeRDP_ContainerName },
1645 { 4, FreeRDP_CspName } };
1646 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
1647
1648 WINPR_ASSERT(nla);
1649 WINPR_ASSERT(enc);
1650 WINPR_ASSERT(nla->rdpcontext);
1651
1652 const rdpSettings* settings = nla->rdpcontext->settings;
1653 WINPR_ASSERT(settings);
1654
1655 /* TSSmartCardCreds */
1656 if (!WinPrAsn1EncSeqContainer(enc))
1657 return FALSE;
1658
1659 /* pin [0] OCTET STRING */
1660 size_t ss = 0;
1661 octet_string.data =
1662 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1663 octet_string.len = ss * sizeof(WCHAR);
1664 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1665 free(octet_string.data);
1666 if (!res)
1667 return FALSE;
1668
1669 /* cspData [1] SEQUENCE */
1670 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1671 return FALSE;
1672
1673 /* keySpec [0] INTEGER */
1674 if (!WinPrAsn1EncContextualInteger(
1675 enc, 0,
1676 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1677 freerdp_settings_get_uint32(settings, FreeRDP_KeySpec))))
1678 return FALSE;
1679
1680 for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1681 {
1682 size_t len = 0;
1683
1684 octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1685 settings, cspData_fields[i].setting_id, &len);
1686 octet_string.len = len * sizeof(WCHAR);
1687 if (octet_string.len)
1688 {
1689 const BOOL res2 =
1690 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1691 free(octet_string.data);
1692 if (!res2)
1693 return FALSE;
1694 }
1695 }
1696
1697 /* End cspData */
1698 if (!WinPrAsn1EncEndContainer(enc))
1699 return FALSE;
1700
1701 /* userHint [2] OCTET STRING OPTIONAL, */
1702 if (freerdp_settings_get_string(settings, FreeRDP_Username))
1703 {
1704 octet_string.data =
1705 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Username, &ss);
1706 octet_string.len = ss * sizeof(WCHAR);
1707 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1708 free(octet_string.data);
1709 if (!res)
1710 return FALSE;
1711 }
1712
1713 /* domainHint [3] OCTET STRING OPTIONAL */
1714 if (freerdp_settings_get_string(settings, FreeRDP_Domain))
1715 {
1716 octet_string.data =
1717 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Domain, &ss);
1718 octet_string.len = ss * sizeof(WCHAR);
1719 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1720 free(octet_string.data);
1721 if (!res)
1722 return FALSE;
1723 }
1724
1725 /* End TSSmartCardCreds */
1726 return WinPrAsn1EncEndContainer(enc) != 0;
1727}
1728
1729static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1730{
1731 WinPrAsn1_OctetString username = WINPR_C_ARRAY_INIT;
1732 WinPrAsn1_OctetString domain = WINPR_C_ARRAY_INIT;
1733 WinPrAsn1_OctetString password = WINPR_C_ARRAY_INIT;
1734
1735 WINPR_ASSERT(nla);
1736 WINPR_ASSERT(enc);
1737 WINPR_ASSERT(nla->rdpcontext);
1738
1739 const rdpSettings* settings = nla->rdpcontext->settings;
1740 WINPR_ASSERT(settings);
1741
1742 /* TSPasswordCreds */
1743 if (!WinPrAsn1EncSeqContainer(enc))
1744 return FALSE;
1745
1746 if (!settings->DisableCredentialsDelegation && nla->identity)
1747 {
1748 username.len = nla->identity->UserLength * sizeof(WCHAR);
1749 username.data = (BYTE*)nla->identity->User;
1750
1751 domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1752 domain.data = (BYTE*)nla->identity->Domain;
1753
1754 password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1755 password.data = (BYTE*)nla->identity->Password;
1756 }
1757
1758 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1759 return FALSE;
1760 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1761 return FALSE;
1762 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1763 return FALSE;
1764
1765 /* End TSPasswordCreds */
1766 return WinPrAsn1EncEndContainer(enc) != 0;
1767}
1768
1769static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1770{
1771 WINPR_ASSERT(nla);
1772 WINPR_ASSERT(enc);
1773
1774 /* TSRemoteGuardCreds */
1775 if (!WinPrAsn1EncSeqContainer(enc))
1776 return FALSE;
1777
1778 /* logonCred [0] TSRemoteGuardPackageCred, */
1779 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1780 return FALSE;
1781
1782 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1783 return FALSE;
1784
1785 /* TODO: compute the NTLM supplemental creds */
1787 if (ntlm)
1788 {
1789 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL */
1790 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1791 return FALSE;
1792
1793 if (!WinPrAsn1EncSeqContainer(enc)) /* start NTLM */
1794 return FALSE;
1795
1796 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1797 return FALSE;
1798
1799 if (!WinPrAsn1EncEndContainer(enc)) /* end NTLM */
1800 return FALSE;
1801
1802 if (!WinPrAsn1EncEndContainer(enc)) /* supplementalCreds */
1803 return FALSE;
1804 }
1805
1806 /* End TSRemoteGuardCreds */
1807 return WinPrAsn1EncEndContainer(enc) != 0;
1808}
1809
1817static BOOL nla_encode_ts_credentials(rdpNla* nla)
1818{
1819 BOOL ret = FALSE;
1820 WinPrAsn1Encoder* enc = nullptr;
1821 size_t length = 0;
1822 wStream s = WINPR_C_ARRAY_INIT;
1823 TsCredentialsType credType = TSCREDS_INVALID;
1824
1825 WINPR_ASSERT(nla);
1826 WINPR_ASSERT(nla->rdpcontext);
1827
1828 rdpSettings* settings = nla->rdpcontext->settings;
1829 WINPR_ASSERT(settings);
1830
1831 if (settings->RemoteCredentialGuard)
1832 credType = TSCREDS_REMOTEGUARD;
1833 else if (settings->SmartcardLogon)
1834 credType = TSCREDS_SMARTCARD;
1835 else
1836 credType = TSCREDS_USER_PASSWD;
1837
1838 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1839 if (!enc)
1840 return FALSE;
1841
1842 /* TSCredentials */
1843 if (!WinPrAsn1EncSeqContainer(enc))
1844 goto out;
1845
1846 /* credType [0] INTEGER */
1847 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1848 goto out;
1849
1850 /* credentials [1] OCTET STRING */
1851 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1852 goto out;
1853
1854 switch (credType)
1855 {
1856 case TSCREDS_SMARTCARD:
1857 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1858 goto out;
1859 break;
1860
1861 case TSCREDS_USER_PASSWD:
1862 if (!nla_encode_ts_password_credentials(nla, enc))
1863 goto out;
1864 break;
1865
1866 case TSCREDS_REMOTEGUARD:
1867 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1868 goto out;
1869 break;
1870 default:
1871 goto out;
1872 }
1873
1874 /* End credentials | End TSCredentials */
1875 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1876 goto out;
1877
1878 if (!WinPrAsn1EncStreamSize(enc, &length))
1879 goto out;
1880
1881 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1882 {
1883 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1884 goto out;
1885 }
1886
1887 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1888
1889 ret = WinPrAsn1EncToStream(enc, &s);
1890
1891out:
1892 WinPrAsn1Encoder_Free(&enc);
1893 return ret;
1894}
1895
1896static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1897{
1898 WINPR_ASSERT(nla);
1899
1900 if (!nla_encode_ts_credentials(nla))
1901 return FALSE;
1902
1903 sspi_SecBufferFree(&nla->authInfo);
1904 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, nullptr,
1905 nla->sendSeqNum++));
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 = WINPR_C_ARRAY_INIT;
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 = nullptr;
1973 size_t length = 0;
1974 WinPrAsn1Encoder* enc = nullptr;
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(nullptr, 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 = WinPrAsn1Decoder_init();
2069 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
2070 BOOL error = FALSE;
2071 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2072 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
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 = WinPrAsn1Decoder_init();
2112 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
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 nullptr;
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 nullptr;
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 nullptr;
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 return (credssp_auth_set_spn(nla->auth, service, hostname));
2381}
2382
2383BOOL nla_impersonate(rdpNla* nla)
2384{
2385 return credssp_auth_impersonate(nla->auth);
2386}
2387
2388BOOL nla_revert_to_self(rdpNla* nla)
2389{
2390 return credssp_auth_revert_to_self(nla->auth);
2391}
2392
2393const char* nla_get_state_str(NLA_STATE state)
2394{
2395 switch (state)
2396 {
2397 case NLA_STATE_INITIAL:
2398 return "NLA_STATE_INITIAL";
2399 case NLA_STATE_NEGO_TOKEN:
2400 return "NLA_STATE_NEGO_TOKEN";
2401 case NLA_STATE_PUB_KEY_AUTH:
2402 return "NLA_STATE_PUB_KEY_AUTH";
2403 case NLA_STATE_AUTH_INFO:
2404 return "NLA_STATE_AUTH_INFO";
2405 case NLA_STATE_POST_NEGO:
2406 return "NLA_STATE_POST_NEGO";
2407 case NLA_STATE_EARLY_USER_AUTH:
2408 return "NLA_STATE_EARLY_USER_AUTH";
2409 case NLA_STATE_FINAL:
2410 return "NLA_STATE_FINAL";
2411 default:
2412 return "UNKNOWN";
2413 }
2414}
2415
2416DWORD nla_get_error(const rdpNla* nla)
2417{
2418 if (!nla)
2419 return ERROR_INTERNAL_ERROR;
2420 return (UINT32)nla->errorCode;
2421}
2422
2423INT32 nla_get_sspi_error(const rdpNla* nla)
2424{
2425 WINPR_ASSERT(nla);
2426 return credssp_auth_sspi_error(nla->auth);
2427}
2428
2429BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2430{
2431 WINPR_ASSERT(nla);
2432 WINPR_ASSERT(inBuffer);
2433 WINPR_ASSERT(outBuffer);
2434 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, nullptr, nla->sendSeqNum++);
2435}
2436
2437BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2438{
2439 WINPR_ASSERT(nla);
2440 WINPR_ASSERT(inBuffer);
2441 WINPR_ASSERT(outBuffer);
2442 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2443}
2444
2445SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2446{
2447 WINPR_ASSERT(nla);
2448
2449 SecurityFunctionTable* table = nullptr;
2450 CtxtHandle context = WINPR_C_ARRAY_INIT;
2451 credssp_auth_tableAndContext(nla->auth, &table, &context);
2452
2453 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2454}
2455
2456SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2457{
2458 WINPR_ASSERT(nla);
2459
2460 SecurityFunctionTable* table = nullptr;
2461 CtxtHandle context = WINPR_C_ARRAY_INIT;
2462 credssp_auth_tableAndContext(nla->auth, &table, &context);
2463
2464 return table->FreeContextBuffer(pBuffer);
2465}
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.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.