25#include <freerdp/config.h>
32#include <freerdp/log.h>
33#include <freerdp/build-config.h>
36#include <winpr/assert.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>
47#include "../crypto/tls.h"
52#include "credssp_auth.h"
53#include <freerdp/utils/smartcardlogon.h>
55#define TAG FREERDP_TAG("core.nla")
57#define NLA_AUTH_PKG NEGO_SSP_NAME
61 AUTHZ_SUCCESS = 0x00000000,
62 AUTHZ_ACCESS_DENIED = 0x00000005,
114 rdpContext* rdpcontext;
115 rdpTransport* transport;
130 SEC_WINNT_AUTH_IDENTITY* identity;
132 rdpCredsspAuth* auth;
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);
148void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
151 WLog_DBG(TAG,
"Early User Auth active: %s", earlyUserAuth ?
"true" :
"false");
152 nla->earlyUserAuth = earlyUserAuth;
155static void nla_buffer_free(rdpNla* 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);
165static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx,
const SecBuffer* buffer)
169 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
172static BOOL nla_sec_buffer_alloc(
SecBuffer* buffer,
size_t size)
174 WINPR_ASSERT(buffer);
175 sspi_SecBufferFree(buffer);
176 if (size > UINT32_MAX)
178 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
181 WINPR_ASSERT(buffer);
182 buffer->BufferType = SECBUFFER_TOKEN;
186static BOOL nla_sec_buffer_alloc_from_data(
SecBuffer* buffer,
const BYTE* data,
size_t offset,
189 if (!nla_sec_buffer_alloc(buffer, offset + size))
192 WINPR_ASSERT(buffer);
193 BYTE* pb = buffer->pvBuffer;
194 memcpy(&pb[offset], data, size);
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 };
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 };
212static const UINT32 NonceLength = 32;
214static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
219 WINPR_ASSERT(nla->rdpcontext);
221 rdpSettings* settings = nla->rdpcontext->settings;
222 WINPR_ASSERT(settings);
224 if (!settings->SmartcardLogon)
227 smartcardCertInfo_Free(nla->smartcardCert);
229 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
231 WLog_ERR(TAG,
"unable to get smartcard certificate for logon");
235 if (!settings->CspName)
240 MS_SMART_CARD_KEY_STORAGE_PROVIDER))
242 WLog_ERR(TAG,
"unable to set CSP name");
247 if (!settings->ReaderName && nla->smartcardCert->reader)
250 nla->smartcardCert->reader))
252 WLog_ERR(TAG,
"unable to copy reader name");
257 if (!settings->ContainerName && nla->smartcardCert->containerName)
260 nla->smartcardCert->containerName))
262 WLog_ERR(TAG,
"unable to copy container name");
270 WLog_ERR(TAG,
"unable to set KeySpec");
274 WLog_DBG(TAG,
"Smartcard logon: Provider='%s' Reader='%s' Container='%s' KeySpec=%" PRIu32,
280 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
282 if (nla->smartcardCert->pkinitArgs)
284 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
285 if (!nla->pkinitArgs)
287 WLog_ERR(TAG,
"unable to copy pkinitArgs");
297static BOOL nla_client_setup_identity(rdpNla* nla)
299 BOOL PromptPassword = FALSE;
302 WINPR_ASSERT(nla->rdpcontext);
304 rdpSettings* settings = nla->rdpcontext->settings;
305 WINPR_ASSERT(settings);
307 freerdp* instance = nla->rdpcontext->instance;
308 WINPR_ASSERT(instance);
311 if ((utils_str_is_empty(settings->Username) ||
312 (utils_str_is_empty(settings->Password) &&
313 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
315 PromptPassword = TRUE;
318 if (PromptPassword && !utils_str_is_empty(settings->Username))
320 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
323 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
324 WINPR_SAM_ENTRY* entry =
325 SamLookupUserA(sam, settings->Username,
326 userLength + 1 ,
nullptr, 0);
333 PromptPassword = FALSE;
334 SamFreeEntry(sam, entry);
343 if (settings->RestrictedAdminModeRequired)
345 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
346 PromptPassword = FALSE;
349 if (settings->RemoteCredentialGuard)
350 PromptPassword = FALSE;
353 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
356 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
362 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
364 case AUTH_NO_CREDENTIALS:
365 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
372 if (!settings->Username)
374 sspi_FreeAuthIdentity(nla->identity);
376 nla->identity =
nullptr;
378 else if (settings->SmartcardLogon)
380 if (smartCardLogonWasDisabled)
382 if (!nla_adjust_settings_from_smartcard(nla))
386 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
387 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
388 sizeof(nla->certSha1)))
393 BOOL usePassword = TRUE;
395 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
398 WINPR_PACKED_ALIGN_CAST(
const WCHAR*, settings->RedirectionPassword);
399 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
401 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
402 FreeRDP_Domain, wstr, len))
408 if (settings->RestrictedAdminModeRequired)
410 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
412 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
413 FreeRDP_Domain, FreeRDP_PasswordHash))
416 nla->identity->Flags |= SEC_WINPR_AUTH_IDENTITY_PASSWORD_HASH;
423 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
424 FreeRDP_Domain, FreeRDP_Password))
432static int nla_client_init(rdpNla* nla)
435 WINPR_ASSERT(nla->rdpcontext);
437 rdpSettings* settings = nla->rdpcontext->settings;
438 WINPR_ASSERT(settings);
440 nla_set_state(nla, NLA_STATE_INITIAL);
442 if (!nla_adjust_settings_from_smartcard(nla))
445 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
448 if (!nla_client_setup_identity(nla))
453 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
456 const BYTE* data =
nullptr;
458 if (!transport_get_public_key(nla->transport, &data, &length))
460 WLog_ERR(TAG,
"Failed to get public key");
464 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
466 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
473int nla_client_begin(rdpNla* nla)
477 if (nla_client_init(nla) < 1)
480 if (nla_get_state(nla) != NLA_STATE_INITIAL)
490 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
492 const int rc = credssp_auth_authenticate(nla->auth);
499 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
502 if (credssp_auth_have_output_token(nla->auth))
507 nla_set_state(nla, NLA_STATE_FINAL);
510 switch (credssp_auth_sspi_error(nla->auth))
512 case SEC_E_LOGON_DENIED:
513 case SEC_E_NO_CREDENTIALS:
514 freerdp_set_last_error_log(nla->rdpcontext,
515 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
526static int nla_client_recv_nego_token(rdpNla* nla)
528 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
529 const int rc = credssp_auth_authenticate(nla->auth);
540 if (nla->peerVersion < 5)
541 res = nla_encrypt_public_key_echo(nla);
543 res = nla_encrypt_public_key_hash(nla);
551 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
562static int nla_client_recv_pub_key_auth(rdpNla* nla)
569 if (nla->peerVersion < 5)
570 rc = nla_decrypt_public_key_echo(nla);
572 rc = nla_decrypt_public_key_hash(nla);
574 sspi_SecBufferFree(&nla->pubKeyAuth);
580 rc = nla_encrypt_ts_credentials(nla);
587 if (nla->earlyUserAuth)
589 transport_set_early_user_auth_mode(nla->transport, TRUE);
590 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
593 nla_set_state(nla, NLA_STATE_AUTH_INFO);
597static int nla_client_recv_early_user_auth(rdpNla* nla)
601 transport_set_early_user_auth_mode(nla->transport, FALSE);
602 nla_set_state(nla, NLA_STATE_AUTH_INFO);
606static int nla_client_recv(rdpNla* nla)
610 switch (nla_get_state(nla))
612 case NLA_STATE_NEGO_TOKEN:
613 return nla_client_recv_nego_token(nla);
615 case NLA_STATE_PUB_KEY_AUTH:
616 return nla_client_recv_pub_key_auth(nla);
618 case NLA_STATE_EARLY_USER_AUTH:
619 return nla_client_recv_early_user_auth(nla);
621 case NLA_STATE_FINAL:
623 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
624 nla_get_state_str(nla_get_state(nla)));
629static int nla_client_authenticate(rdpNla* nla)
635 wStream* s = Stream_New(
nullptr, 4096);
639 WLog_ERR(TAG,
"Stream_New failed!");
643 if (nla_client_begin(nla) < 1)
646 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
648 Stream_ResetPosition(s);
649 const int status = transport_read_pdu(nla->transport, s);
653 WLog_ERR(TAG,
"nla_client_authenticate failure");
657 const int status2 = nla_recv_pdu(nla, s);
665 Stream_Free(s, TRUE);
673static int nla_server_init(rdpNla* nla)
677 const BYTE* data =
nullptr;
679 if (!transport_get_public_key(nla->transport, &data, &length))
681 WLog_ERR(TAG,
"Failed to get public key");
685 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
687 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
691 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
694 if (!credssp_auth_setup_server(nla->auth))
697 nla_set_state(nla, NLA_STATE_INITIAL);
701static wStream* nla_server_recv_stream(rdpNla* nla)
708 s = Stream_New(
nullptr, 4096);
713 status = transport_read_pdu(nla->transport, s);
718 WLog_ERR(TAG,
"nla_recv() error: %d", status);
719 Stream_Free(s, TRUE);
726static BOOL nla_server_recv_credentials(rdpNla* nla)
730 if (nla_server_recv(nla) < 0)
733 if (!nla_decrypt_ts_credentials(nla))
736 if (!nla_impersonate(nla))
739 if (!nla_revert_to_self(nla))
752static int nla_server_authenticate(rdpNla* nla)
758 if (nla_server_init(nla) < 1)
767 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
768 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
769 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
801 if (nla_server_recv(nla) < 0)
804 WLog_DBG(TAG,
"Receiving Authentication Token");
805 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
807 res = credssp_auth_authenticate(nla->auth);
814 switch (GetLastError())
816 case ERROR_PASSWORD_MUST_CHANGE:
817 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
820 case ERROR_PASSWORD_EXPIRED:
821 nla->errorCode = STATUS_PASSWORD_EXPIRED;
824 case ERROR_ACCOUNT_DISABLED:
825 nla->errorCode = STATUS_ACCOUNT_DISABLED;
830 nla->errorCode = STATUS_LOGON_FAILURE;
831 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
832 if (sspi != SEC_E_OK)
833 WLog_DBG(TAG,
"[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
834 GetSecurityStatusString(sspi));
847 if (credssp_auth_have_output_token(nla->auth))
852 if (nla_server_recv(nla) < 0)
855 WLog_DBG(TAG,
"Receiving pubkey Token");
858 if (nla->peerVersion < 5)
859 res = nla_decrypt_public_key_echo(nla);
861 res = nla_decrypt_public_key_hash(nla);
867 sspi_SecBufferFree(&nla->negoToken);
869 if (nla->peerVersion < 5)
870 res = nla_encrypt_public_key_echo(nla);
872 res = nla_encrypt_public_key_hash(nla);
879 WLog_DBG(TAG,
"Sending Authentication Token");
892 if (!nla_server_recv_credentials(nla))
896 nla_buffer_free(nla);
907int nla_authenticate(rdpNla* nla)
912 return nla_server_authenticate(nla);
914 return nla_client_authenticate(nla);
917static void ap_integer_increment_le(BYTE* number,
size_t size)
919 WINPR_ASSERT(number || (size == 0));
921 for (
size_t index = 0; index < size; index++)
923 if (number[index] < 0xFF)
936static void ap_integer_decrement_le(BYTE* number,
size_t size)
938 WINPR_ASSERT(number || (size == 0));
940 for (
size_t index = 0; index < size; index++)
942 if (number[index] > 0)
949 number[index] = 0xFF;
955BOOL nla_encrypt_public_key_echo(rdpNla* nla)
961 sspi_SecBufferFree(&nla->pubKeyAuth);
965 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
967 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
969 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
970 sspi_SecBufferFree(&buf);
974 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
981BOOL nla_encrypt_public_key_hash(rdpNla* nla)
984 WINPR_DIGEST_CTX* sha256 =
nullptr;
989 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
990 const size_t hashSize =
991 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
993 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
997 if (!(sha256 = winpr_Digest_New()))
1000 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1004 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1007 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1011 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1014 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1017 sspi_SecBufferFree(&nla->pubKeyAuth);
1018 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1024 winpr_Digest_Free(sha256);
1025 sspi_SecBufferFree(&buf);
1029BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1031 BOOL status = FALSE;
1032 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1037 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1043 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1046 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1047 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1049 WLog_ERR(TAG,
"Could not verify server's public key echo");
1050#if defined(WITH_DEBUG_NLA)
1051 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1052 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1053 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1054 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1062 sspi_SecBufferFree(&public_key);
1066BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1068 WINPR_DIGEST_CTX* sha256 =
nullptr;
1069 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1070 BOOL status = FALSE;
1074 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1075 const size_t hashSize =
1076 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1079 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1083 if (!(sha256 = winpr_Digest_New()))
1086 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1090 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1093 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1097 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1100 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1104 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1105 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1107 WLog_ERR(TAG,
"Could not verify server's hash");
1114 winpr_Digest_Free(sha256);
1115 sspi_SecBufferFree(&hash);
1119static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1120 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1121 rdpSettings* settings)
1125 WinPrAsn1_tagId itemTag = 0;
1126 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1135 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1139 settings, settingId, WINPR_PACKED_ALIGN_CAST(
const WCHAR*, value.data),
1140 value.len /
sizeof(WCHAR));
1143static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1148 WinPrAsn1_INTEGER keyspec = 0;
1149 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1151 settings->KeySpec = (UINT32)keyspec;
1154 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1158 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1162 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1166 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1169static BOOL nla_messageTypeValid(UINT32 type)
1173 case KerbInvalidValue:
1174 case KerbInteractiveLogon:
1175 case KerbSmartCardLogon:
1176 case KerbWorkstationUnlockLogon:
1177 case KerbSmartCardUnlockLogon:
1178 case KerbProxyLogon:
1179 case KerbTicketLogon:
1180 case KerbTicketUnlockLogon:
1181#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1184#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1185 case KerbCertificateLogon:
1186 case KerbCertificateS4ULogon:
1187 case KerbCertificateUnlockLogon:
1189#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1190 case KerbNoElevationLogon:
1195 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1200static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1209 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1213 const UINT32 type = Stream_Get_UINT32(s);
1214 if (!nla_messageTypeValid(type))
1217 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1219 Stream_Read_UINT32(s, ticket->Flags);
1220 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1221 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1223 if (ticket->MessageType != KerbTicketLogon)
1225 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1229 if (!Stream_CheckAndLogRequiredLength(
1230 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1238 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1239 Stream_Seek(s, ticket->ServiceTicketLength);
1244 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1248static BOOL nla_credentialTypeValid(UINT32 type)
1252 case InvalidCredKey:
1253 case DeprecatedIUMCredKey:
1254 case DomainUserCredKey:
1255 case LocalUserCredKey:
1256 case ExternallySuppliedCredKey:
1259 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1264WINPR_ATTR_MALLOC(free, 1)
1272 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1275 size_t pos = Stream_GetPosition(s);
1278 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1279 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1282 if (!Stream_SetPosition(s, pos))
1290 ret->Version = Stream_Get_UINT32(s);
1291 ret->Flags = Stream_Get_UINT32(s);
1292 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1294 const UINT32 val = Stream_Get_UINT32(s);
1295 if (!nla_credentialTypeValid(val))
1300 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1302 ret->EncryptedCredsSize = EncryptedCredsSize;
1303 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1314} RemoteGuardPackageCredType;
1316static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1317 RemoteGuardPackageCredType* credsType,
1323 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1327 WINPR_ASSERT(credsType);
1328 WINPR_ASSERT(payload);
1330 *credsType = RCG_TYPE_NONE;
1333 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1336 ConvertMszWCharNToUtf8(WINPR_PACKED_ALIGN_CAST(WCHAR*, packageName.data),
1337 packageName.len /
sizeof(WCHAR), packageNameStr,
sizeof(packageNameStr));
1338 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1341 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1344 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1346 *credsType = RCG_TYPE_KERB;
1348 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1350 *credsType = RCG_TYPE_NTLM;
1354 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1358 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1365 TSCREDS_INVALID = 0,
1366 TSCREDS_USER_PASSWD = 1,
1367 TSCREDS_SMARTCARD = 2,
1368 TSCREDS_REMOTEGUARD = 6
1371static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1377 WinPrAsn1_INTEGER credType = -1;
1383 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1386 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1391 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1395 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1398 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1400 rdpSettings* settings = nla->rdpcontext->settings;
1401 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1402 credType != TSCREDS_REMOTEGUARD)
1404 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1410 case TSCREDS_USER_PASSWD:
1413 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1418 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1422 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1426 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1428 case TSCREDS_SMARTCARD:
1431 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1436 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1438 settings->PasswordIsSmartcardPin = TRUE;
1442 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1444 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1448 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1452 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1454 case TSCREDS_REMOTEGUARD:
1457 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1463 .ServiceTicketLength = 0,
1464 .TicketGrantingTicketLength = 0,
1465 .ServiceTicket =
nullptr,
1466 .TicketGrantingTicket =
nullptr };
1470 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1473 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1474 wStream logonPayload = WINPR_C_ARRAY_INIT;
1475 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1478 if (logonCredsType != RCG_TYPE_KERB)
1480 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1484 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1486 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1494 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1495 Stream_GetRemainingLength(&suppCredsSeq.source))
1498 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1501 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1502 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1503 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1507 if (suppCredsType != RCG_TYPE_NTLM)
1509 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1513 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1516 WLog_ERR(TAG,
"invalid supplementalCreds");
1522 WLog_ERR(TAG,
"invalid supplementalCreds");
1526 freerdp_peer* peer = nla->rdpcontext->peer;
1527 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1532 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1542 WINPR_ASSERT(ticket);
1544 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1545 ticket->TicketGrantingTicketLength))
1548 Stream_Write_UINT32(s, KerbTicketLogon);
1549 Stream_Write_UINT32(s, ticket->Flags);
1550 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1551 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1553 Stream_Write_UINT64(s, 0x20);
1554 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1556 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1557 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1561static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1564 WINPR_ASSERT(logonTicket);
1566 SecurityFunctionTable* table =
nullptr;
1568 credssp_auth_tableAndContext(nla->auth, &table, &context);
1569 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1573static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1577 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1578 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1583 logonTicket.ServiceTicket =
nullptr;
1584 logonTicket.TicketGrantingTicket =
nullptr;
1587 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1591 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1594 s = Stream_New(
nullptr, 2000);
1598 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1601 credBuffer.len = Stream_GetPosition(s);
1602 credBuffer.data = Stream_Buffer(s);
1603 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1606 free(logonTicket.ServiceTicket);
1607 free(logonTicket.TicketGrantingTicket);
1608 Stream_Free(s, TRUE);
1612static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1617 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1621 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1625 wStream* s = Stream_New(
nullptr, 300);
1629 Stream_Write_UINT32(s, pntlm->Version);
1630 Stream_Write_UINT32(s, pntlm->Flags);
1632 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1633 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1634 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1635 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1636 Stream_Zero(s, 6 + 16 * 4 + 14);
1640 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1644 Stream_Free(s, TRUE);
1648static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1652 WinPrAsn1_tagId tag;
1653 FreeRDP_Settings_Keys_String setting_id;
1654 } cspData_fields[] = { { 1, FreeRDP_CardName },
1655 { 2, FreeRDP_ReaderName },
1656 { 3, FreeRDP_ContainerName },
1657 { 4, FreeRDP_CspName } };
1662 WINPR_ASSERT(nla->rdpcontext);
1664 const rdpSettings* settings = nla->rdpcontext->settings;
1665 WINPR_ASSERT(settings);
1668 if (!WinPrAsn1EncSeqContainer(enc))
1675 octet_string.len = ss *
sizeof(WCHAR);
1676 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1677 WinPrAsn1FreeOctetString(&octet_string);
1682 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1686 if (!WinPrAsn1EncContextualInteger(
1688 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1692 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1697 settings, cspData_fields[i].setting_id, &len);
1698 octet_string.len = len *
sizeof(WCHAR);
1699 if (octet_string.len)
1702 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1703 WinPrAsn1FreeOctetString(&octet_string);
1710 if (!WinPrAsn1EncEndContainer(enc))
1718 octet_string.len = ss *
sizeof(WCHAR);
1719 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1720 WinPrAsn1FreeOctetString(&octet_string);
1730 octet_string.len = ss *
sizeof(WCHAR);
1731 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1732 WinPrAsn1FreeOctetString(&octet_string);
1738 return WinPrAsn1EncEndContainer(enc) != 0;
1741static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1749 WINPR_ASSERT(nla->rdpcontext);
1751 const rdpSettings* settings = nla->rdpcontext->settings;
1752 WINPR_ASSERT(settings);
1755 if (!WinPrAsn1EncSeqContainer(enc))
1758 if (!settings->DisableCredentialsDelegation && nla->identity)
1760 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1761 username.data = (BYTE*)nla->identity->User;
1763 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1764 domain.data = (BYTE*)nla->identity->Domain;
1766 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1767 password.data = (BYTE*)nla->identity->Password;
1770 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1772 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1774 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1778 return WinPrAsn1EncEndContainer(enc) != 0;
1781static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1787 if (!WinPrAsn1EncSeqContainer(enc))
1791 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1794 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1802 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1805 if (!WinPrAsn1EncSeqContainer(enc))
1808 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1811 if (!WinPrAsn1EncEndContainer(enc))
1814 if (!WinPrAsn1EncEndContainer(enc))
1819 return WinPrAsn1EncEndContainer(enc) != 0;
1829static BOOL nla_encode_ts_credentials(rdpNla* nla)
1832 WinPrAsn1Encoder* enc =
nullptr;
1834 wStream s = WINPR_C_ARRAY_INIT;
1835 TsCredentialsType credType = TSCREDS_INVALID;
1838 WINPR_ASSERT(nla->rdpcontext);
1840 rdpSettings* settings = nla->rdpcontext->settings;
1841 WINPR_ASSERT(settings);
1843 if (settings->RemoteCredentialGuard)
1844 credType = TSCREDS_REMOTEGUARD;
1845 else if (settings->SmartcardLogon)
1846 credType = TSCREDS_SMARTCARD;
1848 credType = TSCREDS_USER_PASSWD;
1850 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1855 if (!WinPrAsn1EncSeqContainer(enc))
1859 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1863 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1868 case TSCREDS_SMARTCARD:
1869 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1873 case TSCREDS_USER_PASSWD:
1874 if (!nla_encode_ts_password_credentials(nla, enc))
1878 case TSCREDS_REMOTEGUARD:
1879 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1887 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1890 if (!WinPrAsn1EncStreamSize(enc, &length))
1893 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1895 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1899 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1901 ret = WinPrAsn1EncToStream(enc, &s);
1904 WinPrAsn1Encoder_Free(&enc);
1908static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1912 if (!nla_encode_ts_credentials(nla))
1915 sspi_SecBufferFree(&nla->authInfo);
1916 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
1917 nla->sendSeqNum++));
1920static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1924 if (nla->authInfo.cbBuffer < 1)
1926 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
1930 sspi_SecBufferFree(&nla->tsCredentials);
1931 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1934 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1940static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
1941 WinPrAsn1_tagId tagId,
const char* msg)
1946 WINPR_ASSERT(buffer);
1949 if (buffer->cbBuffer > 0)
1954 WLog_DBG(TAG,
" ----->> %s", msg);
1955 octet_string.data = buffer->pvBuffer;
1956 octet_string.len = buffer->cbBuffer;
1957 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1965static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
1966 WinPrAsn1_tagId tagId,
const char* msg)
1968 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1969 sspi_SecBufferFree(buffer);
1981BOOL nla_send(rdpNla* nla)
1986 WinPrAsn1Encoder* enc =
nullptr;
1990 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1995 WLog_DBG(TAG,
"----->> sending...");
1996 if (!WinPrAsn1EncSeqContainer(enc))
2000 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
2001 if (!WinPrAsn1EncContextualInteger(enc, 0,
2002 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2006 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2008 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2010 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2014 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2018 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2023 if (nla->authInfo.cbBuffer > 0)
2025 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2030 if (nla->pubKeyAuth.cbBuffer > 0)
2032 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2037 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2039 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2040 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2041 if (!WinPrAsn1EncContextualInteger(
2042 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2047 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2049 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2054 if (!WinPrAsn1EncEndContainer(enc))
2057 if (!WinPrAsn1EncStreamSize(enc, &length))
2060 s = Stream_New(
nullptr, length);
2064 if (!WinPrAsn1EncToStream(enc, s))
2067 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2068 if (transport_write(nla->transport, s) < 0)
2073 Stream_Free(s, TRUE);
2074 WinPrAsn1Encoder_Free(&enc);
2078static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2083 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2084 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2090 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2092 WLog_DBG(TAG,
"<<----- receiving...");
2095 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2101 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2104 if (!Stream_SafeSeek(s, offset))
2107 version = (UINT)val;
2108 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2110 if (nla->peerVersion == 0)
2111 nla->peerVersion = version;
2114 if (nla->peerVersion != version)
2116 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2117 nla->peerVersion, version);
2121 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2129 WLog_DBG(TAG,
" <<----- nego token");
2131 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2132 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2135 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2139 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2144 WLog_DBG(TAG,
" <<----- auth info");
2146 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2148 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2153 WLog_DBG(TAG,
" <<----- public key auth");
2155 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2157 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2163 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2165 nla->errorCode = val;
2166 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2167 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2170 WLog_DBG(TAG,
" <<----- client nonce");
2172 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2174 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2186int nla_recv_pdu(rdpNla* nla,
wStream* s)
2191 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2193 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2196 const UINT32 authzResult = Stream_Get_UINT32(s);
2197 if (authzResult != AUTHZ_SUCCESS)
2199 UINT32 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2201 switch (authzResult)
2203 case AUTHZ_ACCESS_DENIED:
2207 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2213 WLog_ERR(TAG,
"Early User Auth active: FAILURE authorization result 0x%08" PRIX32
"",
2215 freerdp_set_last_error_log(nla->rdpcontext, code);
2219 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2223 if (nla_decode_ts_request(nla, s) < 1)
2230 switch (nla->errorCode)
2232 case STATUS_PASSWORD_MUST_CHANGE:
2233 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2236 case STATUS_PASSWORD_EXPIRED:
2237 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2240 case STATUS_ACCOUNT_DISABLED:
2241 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2244 case STATUS_LOGON_FAILURE:
2245 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2248 case STATUS_WRONG_PASSWORD:
2249 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2252 case STATUS_ACCESS_DENIED:
2253 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2256 case STATUS_ACCOUNT_RESTRICTION:
2257 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2260 case STATUS_ACCOUNT_LOCKED_OUT:
2261 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2264 case STATUS_ACCOUNT_EXPIRED:
2265 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2268 case STATUS_LOGON_TYPE_NOT_GRANTED:
2269 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2273 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2274 NtStatus2Tag(nla->errorCode),
2275 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2276 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2280 freerdp_set_last_error_log(nla->rdpcontext, code);
2285 return nla_client_recv(nla);
2288int nla_server_recv(rdpNla* nla)
2294 wStream* s = nla_server_recv_stream(nla);
2297 status = nla_decode_ts_request(nla, s);
2300 Stream_Free(s, TRUE);
2313rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2315 WINPR_ASSERT(transport);
2316 WINPR_ASSERT(context);
2318 rdpSettings* settings = context->settings;
2319 WINPR_ASSERT(settings);
2321 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2326 nla->rdpcontext = context;
2327 nla->server = settings->ServerMode;
2328 nla->transport = transport;
2329 nla->sendSeqNum = 0;
2330 nla->recvSeqNum = 0;
2332 nla->earlyUserAuth = FALSE;
2334 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2338 nla->auth = credssp_auth_new(context);
2343 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2347 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2352 WINPR_PRAGMA_DIAG_PUSH
2353 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2355 WINPR_PRAGMA_DIAG_POP
2364void nla_free(rdpNla* nla)
2369 smartcardCertInfo_Free(nla->smartcardCert);
2370 nla_buffer_free(nla);
2371 sspi_SecBufferFree(&nla->tsCredentials);
2372 credssp_auth_free(nla->auth);
2374 sspi_FreeAuthIdentity(nla->identity);
2375 free(nla->pkinitArgs);
2376 free(nla->identity);
2380SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2385 return nla->identity;
2388NLA_STATE nla_get_state(
const rdpNla* nla)
2391 return NLA_STATE_FINAL;
2396BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2401 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2406BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2408 return (credssp_auth_set_spn(nla->auth, service, hostname));
2411BOOL nla_impersonate(rdpNla* nla)
2413 return credssp_auth_impersonate(nla->auth);
2416BOOL nla_revert_to_self(rdpNla* nla)
2418 return credssp_auth_revert_to_self(nla->auth);
2421const char* nla_get_state_str(NLA_STATE state)
2425 case NLA_STATE_INITIAL:
2426 return "NLA_STATE_INITIAL";
2427 case NLA_STATE_NEGO_TOKEN:
2428 return "NLA_STATE_NEGO_TOKEN";
2429 case NLA_STATE_PUB_KEY_AUTH:
2430 return "NLA_STATE_PUB_KEY_AUTH";
2431 case NLA_STATE_AUTH_INFO:
2432 return "NLA_STATE_AUTH_INFO";
2433 case NLA_STATE_POST_NEGO:
2434 return "NLA_STATE_POST_NEGO";
2435 case NLA_STATE_EARLY_USER_AUTH:
2436 return "NLA_STATE_EARLY_USER_AUTH";
2437 case NLA_STATE_FINAL:
2438 return "NLA_STATE_FINAL";
2444DWORD nla_get_error(
const rdpNla* nla)
2447 return ERROR_INTERNAL_ERROR;
2448 return (UINT32)nla->errorCode;
2451INT32 nla_get_sspi_error(
const rdpNla* nla)
2454 return credssp_auth_sspi_error(nla->auth);
2460 WINPR_ASSERT(inBuffer);
2461 WINPR_ASSERT(outBuffer);
2462 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2468 WINPR_ASSERT(inBuffer);
2469 WINPR_ASSERT(outBuffer);
2470 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2473SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2477 SecurityFunctionTable* table =
nullptr;
2479 credssp_auth_tableAndContext(nla->auth, &table, &context);
2481 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2484SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2488 SecurityFunctionTable* table =
nullptr;
2490 credssp_auth_tableAndContext(nla->auth, &table, &context);
2492 return table->FreeContextBuffer(pBuffer);
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 BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
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.