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