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 {
825 nla->errorCode = STATUS_LOGON_FAILURE;
826 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
827 if (sspi != SEC_E_OK)
828 WLog_DBG(TAG, "[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
829 GetSecurityStatusString(sspi));
830 }
831 break;
832 }
833
834 (void)nla_send(nla);
835 /* Access Denied */
836 goto fail;
837 }
838
839 if (res == 1)
840 {
841 /* Process final part of the nego token exchange */
842 if (credssp_auth_have_output_token(nla->auth))
843 {
844 if (!nla_send(nla))
845 goto fail;
846
847 if (nla_server_recv(nla) < 0)
848 goto fail;
849
850 WLog_DBG(TAG, "Receiving pubkey Token");
851 }
852
853 if (nla->peerVersion < 5)
854 res = nla_decrypt_public_key_echo(nla);
855 else
856 res = nla_decrypt_public_key_hash(nla);
857
858 if (!res)
859 goto fail;
860
861 /* Clear nego token buffer or we will send it again to the client */
862 sspi_SecBufferFree(&nla->negoToken);
863
864 if (nla->peerVersion < 5)
865 res = nla_encrypt_public_key_echo(nla);
866 else
867 res = nla_encrypt_public_key_hash(nla);
868
869 if (!res)
870 goto fail;
871 }
872
873 /* send authentication token */
874 WLog_DBG(TAG, "Sending Authentication Token");
875
876 if (!nla_send(nla))
877 goto fail;
878
879 if (res == 1)
880 {
881 ret = 1;
882 break;
883 }
884 }
885
886 /* Receive encrypted credentials */
887 if (!nla_server_recv_credentials(nla))
888 ret = -1;
889
890fail:
891 nla_buffer_free(nla);
892 return ret;
893}
894
902int nla_authenticate(rdpNla* nla)
903{
904 WINPR_ASSERT(nla);
905
906 if (nla->server)
907 return nla_server_authenticate(nla);
908 else
909 return nla_client_authenticate(nla);
910}
911
912static void ap_integer_increment_le(BYTE* number, size_t size)
913{
914 WINPR_ASSERT(number || (size == 0));
915
916 for (size_t index = 0; index < size; index++)
917 {
918 if (number[index] < 0xFF)
919 {
920 number[index]++;
921 break;
922 }
923 else
924 {
925 number[index] = 0;
926 continue;
927 }
928 }
929}
930
931static void ap_integer_decrement_le(BYTE* number, size_t size)
932{
933 WINPR_ASSERT(number || (size == 0));
934
935 for (size_t index = 0; index < size; index++)
936 {
937 if (number[index] > 0)
938 {
939 number[index]--;
940 break;
941 }
942 else
943 {
944 number[index] = 0xFF;
945 continue;
946 }
947 }
948}
949
950BOOL nla_encrypt_public_key_echo(rdpNla* nla)
951{
952 BOOL status = FALSE;
953
954 WINPR_ASSERT(nla);
955
956 sspi_SecBufferFree(&nla->pubKeyAuth);
957 if (nla->server)
958 {
959 SecBuffer buf = WINPR_C_ARRAY_INIT;
960 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
961 return FALSE;
962 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
963 status =
964 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, nullptr, nla->sendSeqNum++);
965 sspi_SecBufferFree(&buf);
966 }
967 else
968 {
969 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth, nullptr,
970 nla->sendSeqNum++);
971 }
972
973 return status;
974}
975
976BOOL nla_encrypt_public_key_hash(rdpNla* nla)
977{
978 BOOL status = FALSE;
979 WINPR_DIGEST_CTX* sha256 = nullptr;
980 SecBuffer buf = WINPR_C_ARRAY_INIT;
981
982 WINPR_ASSERT(nla);
983
984 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
985 const size_t hashSize =
986 nla->server ? sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
987
988 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
989 return FALSE;
990
991 /* generate SHA256 of following data: ClientServerHashMagic, Nonce, SubjectPublicKey */
992 if (!(sha256 = winpr_Digest_New()))
993 goto out;
994
995 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
996 goto out;
997
998 /* include trailing \0 from hashMagic */
999 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1000 goto out;
1001
1002 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1003 goto out;
1004
1005 /* SubjectPublicKey */
1006 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1007 goto out;
1008
1009 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1010 goto out;
1011
1012 sspi_SecBufferFree(&nla->pubKeyAuth);
1013 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth, nullptr, nla->sendSeqNum++))
1014 goto out;
1015
1016 status = TRUE;
1017
1018out:
1019 winpr_Digest_Free(sha256);
1020 sspi_SecBufferFree(&buf);
1021 return status;
1022}
1023
1024BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1025{
1026 BOOL status = FALSE;
1027 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1028
1029 if (!nla)
1030 goto fail;
1031
1032 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1033 return FALSE;
1034
1035 if (!nla->server)
1036 {
1037 /* server echos the public key +1 */
1038 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1039 }
1040
1041 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1042 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1043 {
1044 WLog_ERR(TAG, "Could not verify server's public key echo");
1045#if defined(WITH_DEBUG_NLA)
1046 WLog_ERR(TAG, "Expected (length = %" PRIu32 "):", nla->PublicKey.cbBuffer);
1047 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1048 WLog_ERR(TAG, "Actual (length = %" PRIu32 "):", public_key.cbBuffer);
1049 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1050#endif
1051 /* DO NOT SEND CREDENTIALS! */
1052 goto fail;
1053 }
1054
1055 status = TRUE;
1056fail:
1057 sspi_SecBufferFree(&public_key);
1058 return status;
1059}
1060
1061BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1062{
1063 WINPR_DIGEST_CTX* sha256 = nullptr;
1064 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1065 BOOL status = FALSE;
1066
1067 WINPR_ASSERT(nla);
1068
1069 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1070 const size_t hashSize =
1071 nla->server ? sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1072 SecBuffer hash = WINPR_C_ARRAY_INIT;
1073
1074 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1075 return FALSE;
1076
1077 /* generate SHA256 of following data: ServerClientHashMagic, Nonce, SubjectPublicKey */
1078 if (!(sha256 = winpr_Digest_New()))
1079 goto fail;
1080
1081 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1082 goto fail;
1083
1084 /* include trailing \0 from hashMagic */
1085 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1086 goto fail;
1087
1088 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1089 goto fail;
1090
1091 /* SubjectPublicKey */
1092 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1093 goto fail;
1094
1095 if (!winpr_Digest_Final(sha256, serverClientHash, sizeof(serverClientHash)))
1096 goto fail;
1097
1098 /* verify hash */
1099 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1100 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1101 {
1102 WLog_ERR(TAG, "Could not verify server's hash");
1103 /* DO NOT SEND CREDENTIALS! */
1104 goto fail;
1105 }
1106
1107 status = TRUE;
1108fail:
1109 winpr_Digest_Free(sha256);
1110 sspi_SecBufferFree(&hash);
1111 return status;
1112}
1113
1114static BOOL set_creds_octetstring_to_settings(WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1115 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1116 rdpSettings* settings)
1117{
1118 if (optional)
1119 {
1120 WinPrAsn1_tagId itemTag = 0;
1121 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1122 return TRUE;
1123 }
1124
1125 BOOL error = FALSE;
1127 /* note: not checking "error" value, as the not present optional item case is handled above
1128 * if the function fails it's because of a real error not because the item is not present
1129 */
1130 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1131 return FALSE;
1132
1133 return freerdp_settings_set_string_from_utf16N(settings, settingId, (const WCHAR*)value.data,
1134 value.len / sizeof(WCHAR));
1135}
1136
1137static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* settings)
1138{
1139 BOOL error = FALSE;
1140
1141 /* keySpec [0] INTEGER */
1142 WinPrAsn1_INTEGER keyspec = 0;
1143 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1144 return FALSE;
1145 settings->KeySpec = (UINT32)keyspec;
1146
1147 /* cardName [1] OCTET STRING OPTIONAL */
1148 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1149 return FALSE;
1150
1151 /* readerName [2] OCTET STRING OPTIONAL */
1152 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1153 return FALSE;
1154
1155 /* containerName [3] OCTET STRING OPTIONAL */
1156 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1157 return FALSE;
1158
1159 /* cspName [4] OCTET STRING OPTIONAL */
1160 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1161}
1162
1163static BOOL nla_messageTypeValid(UINT32 type)
1164{
1165 switch (type)
1166 {
1167 case KerbInvalidValue:
1168 case KerbInteractiveLogon:
1169 case KerbSmartCardLogon:
1170 case KerbWorkstationUnlockLogon:
1171 case KerbSmartCardUnlockLogon:
1172 case KerbProxyLogon:
1173 case KerbTicketLogon:
1174 case KerbTicketUnlockLogon:
1175#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1176 case KerbS4ULogon:
1177#endif
1178#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1179 case KerbCertificateLogon:
1180 case KerbCertificateS4ULogon:
1181 case KerbCertificateUnlockLogon:
1182#endif
1183#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1184 case KerbNoElevationLogon:
1185 case KerbLuidLogon:
1186#endif
1187 return TRUE;
1188 default:
1189 WLog_ERR(TAG, "Invalid message type %" PRIu32, type);
1190 return FALSE;
1191 }
1192}
1193
1194static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla, wStream* s,
1195 KERB_TICKET_LOGON* ticket)
1196{
1197 WINPR_ASSERT(nla);
1198
1199 if (!ticket)
1200 return FALSE;
1201
1202 /* mysterious extra 16 bytes before TGS/TGT content */
1203 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1204 return FALSE;
1205
1206 {
1207 const UINT32 type = Stream_Get_UINT32(s);
1208 if (!nla_messageTypeValid(type))
1209 return FALSE;
1210
1211 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1212 }
1213 Stream_Read_UINT32(s, ticket->Flags);
1214 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1215 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1216
1217 if (ticket->MessageType != KerbTicketLogon)
1218 {
1219 WLog_ERR(TAG, "Not a KerbTicketLogon");
1220 return FALSE;
1221 }
1222
1223 if (!Stream_CheckAndLogRequiredLength(
1224 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1225 return FALSE;
1226
1227 /* mysterious 16 bytes in the way, maybe they would need to be interpreted... */
1228 Stream_Seek(s, 16);
1229
1230 /*WLog_INFO(TAG, "TGS");
1231 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE), ticket->ServiceTicketLength);*/
1232 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1233 Stream_Seek(s, ticket->ServiceTicketLength);
1234
1235 /*WLog_INFO(TAG, "TGT");
1236 winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, const BYTE),
1237 ticket->TicketGrantingTicketLength);*/
1238 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1239 return TRUE;
1240}
1241
1242static BOOL nla_credentialTypeValid(UINT32 type)
1243{
1244 switch (type)
1245 {
1246 case InvalidCredKey:
1247 case DeprecatedIUMCredKey:
1248 case DomainUserCredKey:
1249 case LocalUserCredKey:
1250 case ExternallySuppliedCredKey:
1251 return TRUE;
1252 default:
1253 WLog_ERR(TAG, "Invalid credential type %" PRIu32, type);
1254 return FALSE;
1255 }
1256}
1257
1258WINPR_ATTR_MALLOC(free, 1)
1259WINPR_ATTR_NODISCARD
1260static MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* nla_read_NtlmCreds(WINPR_ATTR_UNUSED rdpNla* nla,
1261 wStream* s)
1262{
1263 WINPR_ASSERT(nla);
1264 WINPR_ASSERT(s);
1265
1266 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1267 return nullptr;
1268
1269 size_t pos = Stream_GetPosition(s);
1270 Stream_Seek(s, 32);
1271
1272 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1273 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1274 return nullptr;
1275
1276 if (!Stream_SetPosition(s, pos))
1277 return nullptr;
1278
1280 1, sizeof(MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL) - 1 + EncryptedCredsSize);
1281 if (!ret)
1282 return nullptr;
1283
1284 ret->Version = Stream_Get_UINT32(s);
1285 ret->Flags = Stream_Get_UINT32(s);
1286 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1287 {
1288 const UINT32 val = Stream_Get_UINT32(s);
1289 if (!nla_credentialTypeValid(val))
1290 {
1291 free(ret);
1292 return nullptr;
1293 }
1294 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1295 }
1296 ret->EncryptedCredsSize = EncryptedCredsSize;
1297 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1298
1299 return ret;
1300}
1301
1303typedef enum
1304{
1305 RCG_TYPE_NONE,
1306 RCG_TYPE_KERB,
1307 RCG_TYPE_NTLM
1308} RemoteGuardPackageCredType;
1309
1310static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla, WinPrAsn1Decoder* dec,
1311 RemoteGuardPackageCredType* credsType,
1312 wStream* payload)
1313{
1314 WinPrAsn1_OctetString packageName = WINPR_C_ARRAY_INIT;
1315 WinPrAsn1_OctetString credBuffer = WINPR_C_ARRAY_INIT;
1316 BOOL error = FALSE;
1317 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1318
1319 WINPR_ASSERT(nla);
1320 WINPR_ASSERT(dec);
1321 WINPR_ASSERT(credsType);
1322 WINPR_ASSERT(payload);
1323
1324 *credsType = RCG_TYPE_NONE;
1325
1326 /* packageName [0] OCTET STRING */
1327 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1328 return FALSE;
1329
1330 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len / sizeof(WCHAR),
1331 packageNameStr, sizeof(packageNameStr));
1332 WLog_DBG(TAG, "TSRemoteGuardPackageCred(%s)", packageNameStr);
1333
1334 /* credBuffer [1] OCTET STRING, */
1335 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1336 return FALSE;
1337
1338 if (_stricmp(packageNameStr, "Kerberos") == 0)
1339 {
1340 *credsType = RCG_TYPE_KERB;
1341 }
1342 else if (_stricmp(packageNameStr, "NTLM") == 0)
1343 {
1344 *credsType = RCG_TYPE_NTLM;
1345 }
1346 else
1347 {
1348 WLog_INFO(TAG, "TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1349 return FALSE;
1350 }
1351
1352 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1353 return TRUE;
1354}
1355
1357typedef enum
1358{
1359 TSCREDS_INVALID = 0,
1360 TSCREDS_USER_PASSWD = 1,
1361 TSCREDS_SMARTCARD = 2,
1362 TSCREDS_REMOTEGUARD = 6
1363} TsCredentialsType;
1364
1365static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
1366{
1367 WinPrAsn1Decoder dec = WinPrAsn1Decoder_init();
1368 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
1369 WinPrAsn1_OctetString credentials = WINPR_C_ARRAY_INIT;
1370 BOOL error = FALSE;
1371 WinPrAsn1_INTEGER credType = -1;
1372 BOOL ret = TRUE;
1373
1374 WINPR_ASSERT(nla);
1375 WINPR_ASSERT(data);
1376
1377 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1378
1379 /* TSCredentials */
1380 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1381 return FALSE;
1382 dec = dec2;
1383
1384 /* credType [0] INTEGER */
1385 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1386 return FALSE;
1387
1388 /* credentials [1] OCTET STRING */
1389 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1390 return FALSE;
1391
1392 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1393
1394 rdpSettings* settings = nla->rdpcontext->settings;
1395 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1396 credType != TSCREDS_REMOTEGUARD)
1397 {
1398 WLog_ERR(TAG, "connecting with RCG but it's not TSRemoteGuard credentials");
1399 return FALSE;
1400 }
1401
1402 switch (credType)
1403 {
1404 case TSCREDS_USER_PASSWD:
1405 {
1406 /* TSPasswordCreds */
1407 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1408 return FALSE;
1409 dec = dec2;
1410
1411 /* domainName [0] OCTET STRING */
1412 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1413 return FALSE;
1414
1415 /* userName [1] OCTET STRING */
1416 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1417 return FALSE;
1418
1419 /* password [2] OCTET STRING */
1420 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1421 }
1422 case TSCREDS_SMARTCARD:
1423 {
1424 /* TSSmartCardCreds */
1425 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1426 return FALSE;
1427 dec = dec2;
1428
1429 /* pin [0] OCTET STRING, */
1430 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1431 return FALSE;
1432 settings->PasswordIsSmartcardPin = TRUE;
1433
1434 /* cspData [1] TSCspDataDetail */
1435 WinPrAsn1Decoder cspDetails = WinPrAsn1Decoder_init();
1436 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1437 return FALSE;
1438 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1439 return FALSE;
1440
1441 /* userHint [2] OCTET STRING OPTIONAL */
1442 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1443 return FALSE;
1444
1445 /* domainHint [3] OCTET STRING OPTIONAL */
1446 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1447 }
1448 case TSCREDS_REMOTEGUARD:
1449 {
1450 /* TSRemoteGuardCreds */
1451 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1452 return FALSE;
1453
1454 /* logonCred[0] TSRemoteGuardPackageCred */
1455 KERB_TICKET_LOGON kerbLogon = { .MessageType = KerbInvalidValue,
1456 .Flags = 0,
1457 .ServiceTicketLength = 0,
1458 .TicketGrantingTicketLength = 0,
1459 .ServiceTicket = nullptr,
1460 .TicketGrantingTicket = nullptr };
1461
1462 WinPrAsn1Decoder logonCredsSeq = WinPrAsn1Decoder_init();
1463
1464 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1465 return FALSE;
1466
1467 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1468 wStream logonPayload = WINPR_C_ARRAY_INIT;
1469 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1470 &logonPayload))
1471 return FALSE;
1472 if (logonCredsType != RCG_TYPE_KERB)
1473 {
1474 WLog_ERR(TAG, "logonCred must be some Kerberos creds");
1475 return FALSE;
1476 }
1477
1478 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1479 {
1480 WLog_ERR(TAG, "invalid KERB_TICKET_LOGON");
1481 return FALSE;
1482 }
1483
1484 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL, */
1485 MSV1_0_REMOTE_SUPPLEMENTAL_CREDENTIAL* suppCreds = nullptr;
1486 WinPrAsn1Decoder suppCredsSeq = WinPrAsn1Decoder_init();
1487
1488 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1489 Stream_GetRemainingLength(&suppCredsSeq.source))
1490 {
1491 WinPrAsn1Decoder ntlmCredsSeq = WinPrAsn1Decoder_init();
1492 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1493 return FALSE;
1494
1495 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1496 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1497 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1498 &ntlmPayload))
1499 return FALSE;
1500
1501 if (suppCredsType != RCG_TYPE_NTLM)
1502 {
1503 WLog_ERR(TAG, "supplementalCreds must be some NTLM creds");
1504 return FALSE;
1505 }
1506
1507 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1508 if (!suppCreds)
1509 {
1510 WLog_ERR(TAG, "invalid supplementalCreds");
1511 return FALSE;
1512 }
1513 }
1514 else if (error)
1515 {
1516 WLog_ERR(TAG, "invalid supplementalCreds");
1517 return FALSE;
1518 }
1519
1520 freerdp_peer* peer = nla->rdpcontext->peer;
1521 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1522 free(suppCreds);
1523 break;
1524 }
1525 default:
1526 WLog_DBG(TAG, "TSCredentials type %d not supported for now", credType);
1527 ret = FALSE;
1528 break;
1529 }
1530
1531 return ret;
1532}
1533
1534static BOOL nla_write_KERB_TICKET_LOGON(wStream* s, const KERB_TICKET_LOGON* ticket)
1535{
1536 WINPR_ASSERT(ticket);
1537
1538 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1539 ticket->TicketGrantingTicketLength))
1540 return FALSE;
1541
1542 Stream_Write_UINT32(s, KerbTicketLogon);
1543 Stream_Write_UINT32(s, ticket->Flags);
1544 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1545 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1546
1547 Stream_Write_UINT64(s, 0x20); /* offset of TGS in the packet */
1548 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength); /* offset of TGT in packet */
1549
1550 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1551 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1552 return TRUE;
1553}
1554
1555static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla, KERB_TICKET_LOGON* logonTicket)
1556{
1557 WINPR_ASSERT(nla);
1558 WINPR_ASSERT(logonTicket);
1559
1560 SecurityFunctionTable* table = nullptr;
1561 CtxtHandle context = WINPR_C_ARRAY_INIT;
1562 credssp_auth_tableAndContext(nla->auth, &table, &context);
1563 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1564 SEC_E_OK;
1565}
1566
1567static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1568{
1569 BOOL ret = FALSE;
1570 wStream* s = nullptr;
1571 char kerberos[] = { 'K', '\0', 'e', '\0', 'r', '\0', 'b', '\0',
1572 'e', '\0', 'r', '\0', 'o', '\0', 's', '\0' };
1573 WinPrAsn1_OctetString packageName = { sizeof(kerberos), (BYTE*)kerberos };
1574 WinPrAsn1_OctetString credBuffer;
1575 KERB_TICKET_LOGON logonTicket;
1576
1577 logonTicket.ServiceTicket = nullptr;
1578 logonTicket.TicketGrantingTicket = nullptr;
1579
1580 /* packageName [0] OCTET STRING */
1581 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1582 goto out;
1583
1584 /* credBuffer [1] OCTET STRING */
1585 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1586 goto out;
1587
1588 s = Stream_New(nullptr, 2000);
1589 if (!s)
1590 goto out;
1591
1592 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1593 goto out;
1594
1595 credBuffer.len = Stream_GetPosition(s);
1596 credBuffer.data = Stream_Buffer(s);
1597 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1598
1599out:
1600 free(logonTicket.ServiceTicket);
1601 free(logonTicket.TicketGrantingTicket);
1602 Stream_Free(s, TRUE);
1603 return ret;
1604}
1605
1606static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1608{
1609 WINPR_UNUSED(nla);
1610 BOOL ret = FALSE;
1611 BYTE ntlm[] = { 'N', '\0', 'T', '\0', 'L', '\0', 'M', '\0' };
1612 const WinPrAsn1_OctetString packageName = { sizeof(ntlm), ntlm };
1613
1614 /* packageName [0] OCTET STRING */
1615 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1616 return FALSE;
1617
1618 /* credBuffer [1] OCTET STRING */
1619 wStream* s = Stream_New(nullptr, 300);
1620 if (!s)
1621 goto out;
1622
1623 Stream_Write_UINT32(s, pntlm->Version); /* Version */
1624 Stream_Write_UINT32(s, pntlm->Flags); /* Flags */
1625
1626 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1627 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1628 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1629 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1630 Stream_Zero(s, 6 + 16 * 4 + 14);
1631
1632 {
1633 WinPrAsn1_OctetString credBuffer = { Stream_GetPosition(s), Stream_Buffer(s) };
1634 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1635 }
1636
1637out:
1638 Stream_Free(s, TRUE);
1639 return ret;
1640}
1641
1642static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1643{
1644 struct
1645 {
1646 WinPrAsn1_tagId tag;
1647 FreeRDP_Settings_Keys_String setting_id;
1648 } cspData_fields[] = { { 1, FreeRDP_CardName },
1649 { 2, FreeRDP_ReaderName },
1650 { 3, FreeRDP_ContainerName },
1651 { 4, FreeRDP_CspName } };
1652 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
1653
1654 WINPR_ASSERT(nla);
1655 WINPR_ASSERT(enc);
1656 WINPR_ASSERT(nla->rdpcontext);
1657
1658 const rdpSettings* settings = nla->rdpcontext->settings;
1659 WINPR_ASSERT(settings);
1660
1661 /* TSSmartCardCreds */
1662 if (!WinPrAsn1EncSeqContainer(enc))
1663 return FALSE;
1664
1665 /* pin [0] OCTET STRING */
1666 size_t ss = 0;
1667 octet_string.data =
1668 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Password, &ss);
1669 octet_string.len = ss * sizeof(WCHAR);
1670 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1671 WinPrAsn1FreeOctetString(&octet_string);
1672 if (!res)
1673 return FALSE;
1674
1675 /* cspData [1] SEQUENCE */
1676 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1677 return FALSE;
1678
1679 /* keySpec [0] INTEGER */
1680 if (!WinPrAsn1EncContextualInteger(
1681 enc, 0,
1682 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1683 freerdp_settings_get_uint32(settings, FreeRDP_KeySpec))))
1684 return FALSE;
1685
1686 for (size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1687 {
1688 size_t len = 0;
1689
1690 octet_string.data = (BYTE*)freerdp_settings_get_string_as_utf16(
1691 settings, cspData_fields[i].setting_id, &len);
1692 octet_string.len = len * sizeof(WCHAR);
1693 if (octet_string.len)
1694 {
1695 const BOOL res2 =
1696 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1697 WinPrAsn1FreeOctetString(&octet_string);
1698 if (!res2)
1699 return FALSE;
1700 }
1701 }
1702
1703 /* End cspData */
1704 if (!WinPrAsn1EncEndContainer(enc))
1705 return FALSE;
1706
1707 /* userHint [2] OCTET STRING OPTIONAL, */
1708 if (freerdp_settings_get_string(settings, FreeRDP_Username))
1709 {
1710 octet_string.data =
1711 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Username, &ss);
1712 octet_string.len = ss * sizeof(WCHAR);
1713 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1714 WinPrAsn1FreeOctetString(&octet_string);
1715 if (!res)
1716 return FALSE;
1717 }
1718
1719 /* domainHint [3] OCTET STRING OPTIONAL */
1720 if (freerdp_settings_get_string(settings, FreeRDP_Domain))
1721 {
1722 octet_string.data =
1723 (BYTE*)freerdp_settings_get_string_as_utf16(settings, FreeRDP_Domain, &ss);
1724 octet_string.len = ss * sizeof(WCHAR);
1725 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1726 WinPrAsn1FreeOctetString(&octet_string);
1727 if (!res)
1728 return FALSE;
1729 }
1730
1731 /* End TSSmartCardCreds */
1732 return WinPrAsn1EncEndContainer(enc) != 0;
1733}
1734
1735static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1736{
1737 WinPrAsn1_OctetString username = WINPR_C_ARRAY_INIT;
1738 WinPrAsn1_OctetString domain = WINPR_C_ARRAY_INIT;
1739 WinPrAsn1_OctetString password = WINPR_C_ARRAY_INIT;
1740
1741 WINPR_ASSERT(nla);
1742 WINPR_ASSERT(enc);
1743 WINPR_ASSERT(nla->rdpcontext);
1744
1745 const rdpSettings* settings = nla->rdpcontext->settings;
1746 WINPR_ASSERT(settings);
1747
1748 /* TSPasswordCreds */
1749 if (!WinPrAsn1EncSeqContainer(enc))
1750 return FALSE;
1751
1752 if (!settings->DisableCredentialsDelegation && nla->identity)
1753 {
1754 username.len = nla->identity->UserLength * sizeof(WCHAR);
1755 username.data = (BYTE*)nla->identity->User;
1756
1757 domain.len = nla->identity->DomainLength * sizeof(WCHAR);
1758 domain.data = (BYTE*)nla->identity->Domain;
1759
1760 password.len = nla->identity->PasswordLength * sizeof(WCHAR);
1761 password.data = (BYTE*)nla->identity->Password;
1762 }
1763
1764 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1765 return FALSE;
1766 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1767 return FALSE;
1768 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1769 return FALSE;
1770
1771 /* End TSPasswordCreds */
1772 return WinPrAsn1EncEndContainer(enc) != 0;
1773}
1774
1775static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1776{
1777 WINPR_ASSERT(nla);
1778 WINPR_ASSERT(enc);
1779
1780 /* TSRemoteGuardCreds */
1781 if (!WinPrAsn1EncSeqContainer(enc))
1782 return FALSE;
1783
1784 /* logonCred [0] TSRemoteGuardPackageCred, */
1785 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1786 return FALSE;
1787
1788 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1789 return FALSE;
1790
1791 /* TODO: compute the NTLM supplemental creds */
1793 if (ntlm)
1794 {
1795 /* supplementalCreds [1] SEQUENCE OF TSRemoteGuardPackageCred OPTIONAL */
1796 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1797 return FALSE;
1798
1799 if (!WinPrAsn1EncSeqContainer(enc)) /* start NTLM */
1800 return FALSE;
1801
1802 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1803 return FALSE;
1804
1805 if (!WinPrAsn1EncEndContainer(enc)) /* end NTLM */
1806 return FALSE;
1807
1808 if (!WinPrAsn1EncEndContainer(enc)) /* supplementalCreds */
1809 return FALSE;
1810 }
1811
1812 /* End TSRemoteGuardCreds */
1813 return WinPrAsn1EncEndContainer(enc) != 0;
1814}
1815
1823static BOOL nla_encode_ts_credentials(rdpNla* nla)
1824{
1825 BOOL ret = FALSE;
1826 WinPrAsn1Encoder* enc = nullptr;
1827 size_t length = 0;
1828 wStream s = WINPR_C_ARRAY_INIT;
1829 TsCredentialsType credType = TSCREDS_INVALID;
1830
1831 WINPR_ASSERT(nla);
1832 WINPR_ASSERT(nla->rdpcontext);
1833
1834 rdpSettings* settings = nla->rdpcontext->settings;
1835 WINPR_ASSERT(settings);
1836
1837 if (settings->RemoteCredentialGuard)
1838 credType = TSCREDS_REMOTEGUARD;
1839 else if (settings->SmartcardLogon)
1840 credType = TSCREDS_SMARTCARD;
1841 else
1842 credType = TSCREDS_USER_PASSWD;
1843
1844 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1845 if (!enc)
1846 return FALSE;
1847
1848 /* TSCredentials */
1849 if (!WinPrAsn1EncSeqContainer(enc))
1850 goto out;
1851
1852 /* credType [0] INTEGER */
1853 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1854 goto out;
1855
1856 /* credentials [1] OCTET STRING */
1857 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1858 goto out;
1859
1860 switch (credType)
1861 {
1862 case TSCREDS_SMARTCARD:
1863 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1864 goto out;
1865 break;
1866
1867 case TSCREDS_USER_PASSWD:
1868 if (!nla_encode_ts_password_credentials(nla, enc))
1869 goto out;
1870 break;
1871
1872 case TSCREDS_REMOTEGUARD:
1873 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1874 goto out;
1875 break;
1876 default:
1877 goto out;
1878 }
1879
1880 /* End credentials | End TSCredentials */
1881 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1882 goto out;
1883
1884 if (!WinPrAsn1EncStreamSize(enc, &length))
1885 goto out;
1886
1887 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1888 {
1889 WLog_ERR(TAG, "sspi_SecBufferAlloc failed!");
1890 goto out;
1891 }
1892
1893 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1894
1895 ret = WinPrAsn1EncToStream(enc, &s);
1896
1897out:
1898 WinPrAsn1Encoder_Free(&enc);
1899 return ret;
1900}
1901
1902static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1903{
1904 WINPR_ASSERT(nla);
1905
1906 if (!nla_encode_ts_credentials(nla))
1907 return FALSE;
1908
1909 sspi_SecBufferFree(&nla->authInfo);
1910 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo, nullptr,
1911 nla->sendSeqNum++));
1912}
1913
1914static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1915{
1916 WINPR_ASSERT(nla);
1917
1918 if (nla->authInfo.cbBuffer < 1)
1919 {
1920 WLog_ERR(TAG, "nla_decrypt_ts_credentials missing authInfo buffer");
1921 return FALSE;
1922 }
1923
1924 sspi_SecBufferFree(&nla->tsCredentials);
1925 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1926 return FALSE;
1927
1928 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1929 return FALSE;
1930
1931 return TRUE;
1932}
1933
1934static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc, const SecBuffer* buffer,
1935 WinPrAsn1_tagId tagId, const char* msg)
1936{
1937 BOOL res = FALSE;
1938
1939 WINPR_ASSERT(enc);
1940 WINPR_ASSERT(buffer);
1941 WINPR_ASSERT(msg);
1942
1943 if (buffer->cbBuffer > 0)
1944 {
1945 size_t rc = 0;
1946 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
1947
1948 WLog_DBG(TAG, " ----->> %s", msg);
1949 octet_string.data = buffer->pvBuffer;
1950 octet_string.len = buffer->cbBuffer;
1951 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1952 if (rc != 0)
1953 res = TRUE;
1954 }
1955
1956 return res;
1957}
1958
1959static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc, SecBuffer* buffer,
1960 WinPrAsn1_tagId tagId, const char* msg)
1961{
1962 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1963 sspi_SecBufferFree(buffer);
1964 return rc;
1965}
1966
1975BOOL nla_send(rdpNla* nla)
1976{
1977 BOOL rc = FALSE;
1978 wStream* s = nullptr;
1979 size_t length = 0;
1980 WinPrAsn1Encoder* enc = nullptr;
1981
1982 WINPR_ASSERT(nla);
1983
1984 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1985 if (!enc)
1986 return FALSE;
1987
1988 /* TSRequest */
1989 WLog_DBG(TAG, "----->> sending...");
1990 if (!WinPrAsn1EncSeqContainer(enc))
1991 goto fail;
1992
1993 /* version [0] INTEGER */
1994 WLog_DBG(TAG, " ----->> protocol version %" PRIu32, nla->version);
1995 if (!WinPrAsn1EncContextualInteger(enc, 0,
1996 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
1997 goto fail;
1998
1999 /* negoTokens [1] SEQUENCE OF SEQUENCE */
2000 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2001 {
2002 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2003
2004 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2005 goto fail;
2006
2007 /* negoToken [0] OCTET STRING */
2008 if (!nla_write_octet_string(enc, buffer, 0, "negoToken"))
2009 goto fail;
2010
2011 /* End negoTokens (SEQUENCE OF SEQUENCE) */
2012 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2013 goto fail;
2014 }
2015
2016 /* authInfo [2] OCTET STRING */
2017 if (nla->authInfo.cbBuffer > 0)
2018 {
2019 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2, "auth info"))
2020 goto fail;
2021 }
2022
2023 /* pubKeyAuth [3] OCTET STRING */
2024 if (nla->pubKeyAuth.cbBuffer > 0)
2025 {
2026 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3, "public key auth"))
2027 goto fail;
2028 }
2029
2030 /* errorCode [4] INTEGER */
2031 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2032 {
2033 WLog_DBG(TAG, " ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2034 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2035 if (!WinPrAsn1EncContextualInteger(
2036 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2037 goto fail;
2038 }
2039
2040 /* clientNonce [5] OCTET STRING */
2041 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2042 {
2043 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5, "client nonce"))
2044 goto fail;
2045 }
2046
2047 /* End TSRequest */
2048 if (!WinPrAsn1EncEndContainer(enc))
2049 goto fail;
2050
2051 if (!WinPrAsn1EncStreamSize(enc, &length))
2052 goto fail;
2053
2054 s = Stream_New(nullptr, length);
2055 if (!s)
2056 goto fail;
2057
2058 if (!WinPrAsn1EncToStream(enc, s))
2059 goto fail;
2060
2061 WLog_DBG(TAG, "[%" PRIuz " bytes]", length);
2062 if (transport_write(nla->transport, s) < 0)
2063 goto fail;
2064 rc = TRUE;
2065
2066fail:
2067 Stream_Free(s, TRUE);
2068 WinPrAsn1Encoder_Free(&enc);
2069 return rc;
2070}
2071
2072static int nla_decode_ts_request(rdpNla* nla, wStream* s)
2073{
2074 WinPrAsn1Decoder dec = WinPrAsn1Decoder_init();
2075 WinPrAsn1Decoder dec2 = WinPrAsn1Decoder_init();
2076 BOOL error = FALSE;
2077 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2078 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2079 UINT32 version = 0;
2080
2081 WINPR_ASSERT(nla);
2082 WINPR_ASSERT(s);
2083
2084 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2085
2086 WLog_DBG(TAG, "<<----- receiving...");
2087
2088 /* TSRequest */
2089 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2090 if (offset == 0)
2091 return -1;
2092 dec = dec2;
2093
2094 /* version [0] INTEGER */
2095 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2096 return -1;
2097
2098 if (!Stream_SafeSeek(s, offset))
2099 return -1;
2100
2101 version = (UINT)val;
2102 WLog_DBG(TAG, " <<----- protocol version %" PRIu32, version);
2103
2104 if (nla->peerVersion == 0)
2105 nla->peerVersion = version;
2106
2107 /* if the peer suddenly changed its version - kick it */
2108 if (nla->peerVersion != version)
2109 {
2110 WLog_ERR(TAG, "CredSSP peer changed protocol version from %" PRIu32 " to %" PRIu32,
2111 nla->peerVersion, version);
2112 return -1;
2113 }
2114
2115 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2116 {
2117 WinPrAsn1Decoder dec3 = WinPrAsn1Decoder_init();
2118 WinPrAsn1_OctetString octet_string = WINPR_C_ARRAY_INIT;
2119
2120 switch (tag)
2121 {
2122 case 1:
2123 WLog_DBG(TAG, " <<----- nego token");
2124 /* negoTokens [1] SEQUENCE OF SEQUENCE */
2125 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2126 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2127 return -1;
2128 /* negoToken [0] OCTET STRING */
2129 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2130 FALSE) == 0) &&
2131 error)
2132 return -1;
2133 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2134 octet_string.len))
2135 return -1;
2136 break;
2137 case 2:
2138 WLog_DBG(TAG, " <<----- auth info");
2139 /* authInfo [2] OCTET STRING */
2140 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2141 return -1;
2142 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2143 octet_string.len))
2144 return -1;
2145 break;
2146 case 3:
2147 WLog_DBG(TAG, " <<----- public key auth");
2148 /* pubKeyAuth [3] OCTET STRING */
2149 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2150 return -1;
2151 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2152 octet_string.len))
2153 return -1;
2154 break;
2155 case 4:
2156 /* errorCode [4] INTEGER */
2157 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2158 return -1;
2159 nla->errorCode = val;
2160 WLog_DBG(TAG, " <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2161 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2162 break;
2163 case 5:
2164 WLog_DBG(TAG, " <<----- client nonce");
2165 /* clientNonce [5] OCTET STRING */
2166 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2167 return -1;
2168 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2169 octet_string.len))
2170 return -1;
2171 break;
2172 default:
2173 return -1;
2174 }
2175 }
2176
2177 return 1;
2178}
2179
2180int nla_recv_pdu(rdpNla* nla, wStream* s)
2181{
2182 WINPR_ASSERT(nla);
2183 WINPR_ASSERT(s);
2184
2185 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2186 {
2187 UINT32 code = 0;
2188 Stream_Read_UINT32(s, code);
2189 if (code != AUTHZ_SUCCESS)
2190 {
2191 WLog_DBG(TAG, "Early User Auth active: FAILURE code 0x%08" PRIX32 "", code);
2192 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2193 freerdp_set_last_error_log(nla->rdpcontext, code);
2194 return -1;
2195 }
2196 else
2197 WLog_DBG(TAG, "Early User Auth active: SUCCESS");
2198 }
2199 else
2200 {
2201 if (nla_decode_ts_request(nla, s) < 1)
2202 return -1;
2203
2204 if (nla->errorCode)
2205 {
2206 UINT32 code = 0;
2207
2208 switch (nla->errorCode)
2209 {
2210 case STATUS_PASSWORD_MUST_CHANGE:
2211 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2212 break;
2213
2214 case STATUS_PASSWORD_EXPIRED:
2215 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2216 break;
2217
2218 case STATUS_ACCOUNT_DISABLED:
2219 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2220 break;
2221
2222 case STATUS_LOGON_FAILURE:
2223 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2224 break;
2225
2226 case STATUS_WRONG_PASSWORD:
2227 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2228 break;
2229
2230 case STATUS_ACCESS_DENIED:
2231 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2232 break;
2233
2234 case STATUS_ACCOUNT_RESTRICTION:
2235 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2236 break;
2237
2238 case STATUS_ACCOUNT_LOCKED_OUT:
2239 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2240 break;
2241
2242 case STATUS_ACCOUNT_EXPIRED:
2243 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2244 break;
2245
2246 case STATUS_LOGON_TYPE_NOT_GRANTED:
2247 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2248 break;
2249
2250 default:
2251 WLog_ERR(TAG, "SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32 "]",
2252 NtStatus2Tag(nla->errorCode),
2253 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2254 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2255 break;
2256 }
2257
2258 freerdp_set_last_error_log(nla->rdpcontext, code);
2259 return -1;
2260 }
2261 }
2262
2263 return nla_client_recv(nla);
2264}
2265
2266int nla_server_recv(rdpNla* nla)
2267{
2268 int status = -1;
2269
2270 WINPR_ASSERT(nla);
2271
2272 wStream* s = nla_server_recv_stream(nla);
2273 if (!s)
2274 goto fail;
2275 status = nla_decode_ts_request(nla, s);
2276
2277fail:
2278 Stream_Free(s, TRUE);
2279 return status;
2280}
2281
2291rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2292{
2293 WINPR_ASSERT(transport);
2294 WINPR_ASSERT(context);
2295
2296 rdpSettings* settings = context->settings;
2297 WINPR_ASSERT(settings);
2298
2299 rdpNla* nla = (rdpNla*)calloc(1, sizeof(rdpNla));
2300
2301 if (!nla)
2302 return nullptr;
2303
2304 nla->rdpcontext = context;
2305 nla->server = settings->ServerMode;
2306 nla->transport = transport;
2307 nla->sendSeqNum = 0;
2308 nla->recvSeqNum = 0;
2309 nla->version = 6;
2310 nla->earlyUserAuth = FALSE;
2311
2312 nla->identity = calloc(1, sizeof(SEC_WINNT_AUTH_IDENTITY));
2313 if (!nla->identity)
2314 goto cleanup;
2315
2316 nla->auth = credssp_auth_new(context);
2317 if (!nla->auth)
2318 goto cleanup;
2319
2320 /* init to 0 or we end up freeing a bad pointer if the alloc fails */
2321 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2322 goto cleanup;
2323
2324 /* generate random 32-byte nonce */
2325 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2326 goto cleanup;
2327
2328 return nla;
2329cleanup:
2330 WINPR_PRAGMA_DIAG_PUSH
2331 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2332 nla_free(nla);
2333 WINPR_PRAGMA_DIAG_POP
2334 return nullptr;
2335}
2336
2342void nla_free(rdpNla* nla)
2343{
2344 if (!nla)
2345 return;
2346
2347 smartcardCertInfo_Free(nla->smartcardCert);
2348 nla_buffer_free(nla);
2349 sspi_SecBufferFree(&nla->tsCredentials);
2350 credssp_auth_free(nla->auth);
2351
2352 sspi_FreeAuthIdentity(nla->identity);
2353 free(nla->pkinitArgs);
2354 free(nla->identity);
2355 free(nla);
2356}
2357
2358SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2359{
2360 if (!nla)
2361 return nullptr;
2362
2363 return nla->identity;
2364}
2365
2366NLA_STATE nla_get_state(const rdpNla* nla)
2367{
2368 if (!nla)
2369 return NLA_STATE_FINAL;
2370
2371 return nla->state;
2372}
2373
2374BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2375{
2376 if (!nla)
2377 return FALSE;
2378
2379 WLog_DBG(TAG, "-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2380 nla->state = state;
2381 return TRUE;
2382}
2383
2384BOOL nla_set_service_principal(rdpNla* nla, const char* service, const char* hostname)
2385{
2386 return (credssp_auth_set_spn(nla->auth, service, hostname));
2387}
2388
2389BOOL nla_impersonate(rdpNla* nla)
2390{
2391 return credssp_auth_impersonate(nla->auth);
2392}
2393
2394BOOL nla_revert_to_self(rdpNla* nla)
2395{
2396 return credssp_auth_revert_to_self(nla->auth);
2397}
2398
2399const char* nla_get_state_str(NLA_STATE state)
2400{
2401 switch (state)
2402 {
2403 case NLA_STATE_INITIAL:
2404 return "NLA_STATE_INITIAL";
2405 case NLA_STATE_NEGO_TOKEN:
2406 return "NLA_STATE_NEGO_TOKEN";
2407 case NLA_STATE_PUB_KEY_AUTH:
2408 return "NLA_STATE_PUB_KEY_AUTH";
2409 case NLA_STATE_AUTH_INFO:
2410 return "NLA_STATE_AUTH_INFO";
2411 case NLA_STATE_POST_NEGO:
2412 return "NLA_STATE_POST_NEGO";
2413 case NLA_STATE_EARLY_USER_AUTH:
2414 return "NLA_STATE_EARLY_USER_AUTH";
2415 case NLA_STATE_FINAL:
2416 return "NLA_STATE_FINAL";
2417 default:
2418 return "UNKNOWN";
2419 }
2420}
2421
2422DWORD nla_get_error(const rdpNla* nla)
2423{
2424 if (!nla)
2425 return ERROR_INTERNAL_ERROR;
2426 return (UINT32)nla->errorCode;
2427}
2428
2429INT32 nla_get_sspi_error(const rdpNla* nla)
2430{
2431 WINPR_ASSERT(nla);
2432 return credssp_auth_sspi_error(nla->auth);
2433}
2434
2435BOOL nla_encrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2436{
2437 WINPR_ASSERT(nla);
2438 WINPR_ASSERT(inBuffer);
2439 WINPR_ASSERT(outBuffer);
2440 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer, nullptr, nla->sendSeqNum++);
2441}
2442
2443BOOL nla_decrypt(rdpNla* nla, const SecBuffer* inBuffer, SecBuffer* outBuffer)
2444{
2445 WINPR_ASSERT(nla);
2446 WINPR_ASSERT(inBuffer);
2447 WINPR_ASSERT(outBuffer);
2448 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2449}
2450
2451SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2452{
2453 WINPR_ASSERT(nla);
2454
2455 SecurityFunctionTable* table = nullptr;
2456 CtxtHandle context = WINPR_C_ARRAY_INIT;
2457 credssp_auth_tableAndContext(nla->auth, &table, &context);
2458
2459 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2460}
2461
2462SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2463{
2464 WINPR_ASSERT(nla);
2465
2466 SecurityFunctionTable* table = nullptr;
2467 CtxtHandle context = WINPR_C_ARRAY_INIT;
2468 credssp_auth_tableAndContext(nla->auth, &table, &context);
2469
2470 return table->FreeContextBuffer(pBuffer);
2471}
WINPR_ATTR_NODISCARD 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 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.
WINPR_ATTR_NODISCARD 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.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
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.
WINPR_ATTR_NODISCARD 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.