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)
238 settings, FreeRDP_CspName, nla->smartcardCert->csp))
240 WLog_ERR(TAG,
"unable to set CSP name");
243 if (!settings->CspName &&
246 WLog_ERR(TAG,
"unable to set CSP name");
251 if (!settings->ReaderName && nla->smartcardCert->reader)
254 nla->smartcardCert->reader))
256 WLog_ERR(TAG,
"unable to copy reader name");
261 if (!settings->ContainerName && nla->smartcardCert->containerName)
264 nla->smartcardCert->containerName))
266 WLog_ERR(TAG,
"unable to copy container name");
271 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
273 if (nla->smartcardCert->pkinitArgs)
275 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
276 if (!nla->pkinitArgs)
278 WLog_ERR(TAG,
"unable to copy pkinitArgs");
288static BOOL nla_client_setup_identity(rdpNla* nla)
290 BOOL PromptPassword = FALSE;
293 WINPR_ASSERT(nla->rdpcontext);
295 rdpSettings* settings = nla->rdpcontext->settings;
296 WINPR_ASSERT(settings);
298 freerdp* instance = nla->rdpcontext->instance;
299 WINPR_ASSERT(instance);
302 if ((utils_str_is_empty(settings->Username) ||
303 (utils_str_is_empty(settings->Password) &&
304 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
306 PromptPassword = TRUE;
309 if (PromptPassword && !utils_str_is_empty(settings->Username))
311 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
314 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
315 WINPR_SAM_ENTRY* entry =
316 SamLookupUserA(sam, settings->Username,
317 userLength + 1 ,
nullptr, 0);
324 PromptPassword = FALSE;
325 SamFreeEntry(sam, entry);
334 if (settings->RestrictedAdminModeRequired)
336 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
337 PromptPassword = FALSE;
340 if (settings->RemoteCredentialGuard)
341 PromptPassword = FALSE;
344 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
347 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
353 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
355 case AUTH_NO_CREDENTIALS:
356 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
363 if (!settings->Username)
365 sspi_FreeAuthIdentity(nla->identity);
367 nla->identity =
nullptr;
369 else if (settings->SmartcardLogon)
371 if (smartCardLogonWasDisabled)
373 if (!nla_adjust_settings_from_smartcard(nla))
377 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
378 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
379 sizeof(nla->certSha1)))
384 BOOL usePassword = TRUE;
386 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
388 const WCHAR* wstr = (
const WCHAR*)settings->RedirectionPassword;
389 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
391 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
392 FreeRDP_Domain, wstr, len))
398 if (settings->RestrictedAdminModeRequired)
400 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
402 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
403 FreeRDP_Domain, FreeRDP_PasswordHash))
411 nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
418 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
419 FreeRDP_Domain, FreeRDP_Password))
427static int nla_client_init(rdpNla* nla)
430 WINPR_ASSERT(nla->rdpcontext);
432 rdpSettings* settings = nla->rdpcontext->settings;
433 WINPR_ASSERT(settings);
435 nla_set_state(nla, NLA_STATE_INITIAL);
437 if (!nla_adjust_settings_from_smartcard(nla))
440 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
443 if (!nla_client_setup_identity(nla))
448 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
451 const BYTE* data =
nullptr;
453 if (!transport_get_public_key(nla->transport, &data, &length))
455 WLog_ERR(TAG,
"Failed to get public key");
459 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
461 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
468int nla_client_begin(rdpNla* nla)
472 if (nla_client_init(nla) < 1)
475 if (nla_get_state(nla) != NLA_STATE_INITIAL)
485 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
487 const int rc = credssp_auth_authenticate(nla->auth);
494 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
497 if (credssp_auth_have_output_token(nla->auth))
502 nla_set_state(nla, NLA_STATE_FINAL);
505 switch (credssp_auth_sspi_error(nla->auth))
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);
521static int nla_client_recv_nego_token(rdpNla* nla)
523 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
524 const int rc = credssp_auth_authenticate(nla->auth);
535 if (nla->peerVersion < 5)
536 res = nla_encrypt_public_key_echo(nla);
538 res = nla_encrypt_public_key_hash(nla);
546 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
557static int nla_client_recv_pub_key_auth(rdpNla* nla)
564 if (nla->peerVersion < 5)
565 rc = nla_decrypt_public_key_echo(nla);
567 rc = nla_decrypt_public_key_hash(nla);
569 sspi_SecBufferFree(&nla->pubKeyAuth);
575 rc = nla_encrypt_ts_credentials(nla);
582 if (nla->earlyUserAuth)
584 transport_set_early_user_auth_mode(nla->transport, TRUE);
585 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
588 nla_set_state(nla, NLA_STATE_AUTH_INFO);
592static int nla_client_recv_early_user_auth(rdpNla* nla)
596 transport_set_early_user_auth_mode(nla->transport, FALSE);
597 nla_set_state(nla, NLA_STATE_AUTH_INFO);
601static int nla_client_recv(rdpNla* nla)
605 switch (nla_get_state(nla))
607 case NLA_STATE_NEGO_TOKEN:
608 return nla_client_recv_nego_token(nla);
610 case NLA_STATE_PUB_KEY_AUTH:
611 return nla_client_recv_pub_key_auth(nla);
613 case NLA_STATE_EARLY_USER_AUTH:
614 return nla_client_recv_early_user_auth(nla);
616 case NLA_STATE_FINAL:
618 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
619 nla_get_state_str(nla_get_state(nla)));
624static int nla_client_authenticate(rdpNla* nla)
630 wStream* s = Stream_New(
nullptr, 4096);
634 WLog_ERR(TAG,
"Stream_New failed!");
638 if (nla_client_begin(nla) < 1)
641 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
643 Stream_ResetPosition(s);
644 const int status = transport_read_pdu(nla->transport, s);
648 WLog_ERR(TAG,
"nla_client_authenticate failure");
652 const int status2 = nla_recv_pdu(nla, s);
660 Stream_Free(s, TRUE);
668static int nla_server_init(rdpNla* nla)
672 const BYTE* data =
nullptr;
674 if (!transport_get_public_key(nla->transport, &data, &length))
676 WLog_ERR(TAG,
"Failed to get public key");
680 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
682 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
686 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
689 if (!credssp_auth_setup_server(nla->auth))
692 nla_set_state(nla, NLA_STATE_INITIAL);
696static wStream* nla_server_recv_stream(rdpNla* nla)
703 s = Stream_New(
nullptr, 4096);
708 status = transport_read_pdu(nla->transport, s);
713 WLog_ERR(TAG,
"nla_recv() error: %d", status);
714 Stream_Free(s, TRUE);
721static BOOL nla_server_recv_credentials(rdpNla* nla)
725 if (nla_server_recv(nla) < 0)
728 if (!nla_decrypt_ts_credentials(nla))
731 if (!nla_impersonate(nla))
734 if (!nla_revert_to_self(nla))
747static int nla_server_authenticate(rdpNla* nla)
753 if (nla_server_init(nla) < 1)
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);
796 if (nla_server_recv(nla) < 0)
799 WLog_DBG(TAG,
"Receiving Authentication Token");
800 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
802 res = credssp_auth_authenticate(nla->auth);
809 switch (GetLastError())
811 case ERROR_PASSWORD_MUST_CHANGE:
812 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
815 case ERROR_PASSWORD_EXPIRED:
816 nla->errorCode = STATUS_PASSWORD_EXPIRED;
819 case ERROR_ACCOUNT_DISABLED:
820 nla->errorCode = STATUS_ACCOUNT_DISABLED;
825 nla->errorCode = STATUS_LOGON_FAILURE;
826 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
827 if (sspi != SEC_E_OK)
828 WLog_DBG(TAG,
"[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
829 GetSecurityStatusString(sspi));
842 if (credssp_auth_have_output_token(nla->auth))
847 if (nla_server_recv(nla) < 0)
850 WLog_DBG(TAG,
"Receiving pubkey Token");
853 if (nla->peerVersion < 5)
854 res = nla_decrypt_public_key_echo(nla);
856 res = nla_decrypt_public_key_hash(nla);
862 sspi_SecBufferFree(&nla->negoToken);
864 if (nla->peerVersion < 5)
865 res = nla_encrypt_public_key_echo(nla);
867 res = nla_encrypt_public_key_hash(nla);
874 WLog_DBG(TAG,
"Sending Authentication Token");
887 if (!nla_server_recv_credentials(nla))
891 nla_buffer_free(nla);
902int nla_authenticate(rdpNla* nla)
907 return nla_server_authenticate(nla);
909 return nla_client_authenticate(nla);
912static void ap_integer_increment_le(BYTE* number,
size_t size)
914 WINPR_ASSERT(number || (size == 0));
916 for (
size_t index = 0; index < size; index++)
918 if (number[index] < 0xFF)
931static void ap_integer_decrement_le(BYTE* number,
size_t size)
933 WINPR_ASSERT(number || (size == 0));
935 for (
size_t index = 0; index < size; index++)
937 if (number[index] > 0)
944 number[index] = 0xFF;
950BOOL nla_encrypt_public_key_echo(rdpNla* nla)
956 sspi_SecBufferFree(&nla->pubKeyAuth);
960 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
962 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
964 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
965 sspi_SecBufferFree(&buf);
969 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
976BOOL nla_encrypt_public_key_hash(rdpNla* nla)
979 WINPR_DIGEST_CTX* sha256 =
nullptr;
984 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
985 const size_t hashSize =
986 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
988 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
992 if (!(sha256 = winpr_Digest_New()))
995 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
999 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1002 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1006 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1009 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1012 sspi_SecBufferFree(&nla->pubKeyAuth);
1013 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1019 winpr_Digest_Free(sha256);
1020 sspi_SecBufferFree(&buf);
1024BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1026 BOOL status = FALSE;
1027 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1032 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1038 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1041 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1042 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1044 WLog_ERR(TAG,
"Could not verify server's public key echo");
1045#if defined(WITH_DEBUG_NLA)
1046 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1047 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1048 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1049 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1057 sspi_SecBufferFree(&public_key);
1061BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1063 WINPR_DIGEST_CTX* sha256 =
nullptr;
1064 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1065 BOOL status = FALSE;
1069 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1070 const size_t hashSize =
1071 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1074 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1078 if (!(sha256 = winpr_Digest_New()))
1081 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1085 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1088 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1092 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1095 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1099 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1100 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1102 WLog_ERR(TAG,
"Could not verify server's hash");
1109 winpr_Digest_Free(sha256);
1110 sspi_SecBufferFree(&hash);
1114static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1115 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1116 rdpSettings* settings)
1120 WinPrAsn1_tagId itemTag = 0;
1121 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1130 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1134 value.len /
sizeof(WCHAR));
1137static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1142 WinPrAsn1_INTEGER keyspec = 0;
1143 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1145 settings->KeySpec = (UINT32)keyspec;
1148 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1152 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1156 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1160 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1163static BOOL nla_messageTypeValid(UINT32 type)
1167 case KerbInvalidValue:
1168 case KerbInteractiveLogon:
1169 case KerbSmartCardLogon:
1170 case KerbWorkstationUnlockLogon:
1171 case KerbSmartCardUnlockLogon:
1172 case KerbProxyLogon:
1173 case KerbTicketLogon:
1174 case KerbTicketUnlockLogon:
1175#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1178#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1179 case KerbCertificateLogon:
1180 case KerbCertificateS4ULogon:
1181 case KerbCertificateUnlockLogon:
1183#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1184 case KerbNoElevationLogon:
1189 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1194static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1203 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1207 const UINT32 type = Stream_Get_UINT32(s);
1208 if (!nla_messageTypeValid(type))
1211 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1213 Stream_Read_UINT32(s, ticket->Flags);
1214 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1215 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1217 if (ticket->MessageType != KerbTicketLogon)
1219 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1223 if (!Stream_CheckAndLogRequiredLength(
1224 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1232 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1233 Stream_Seek(s, ticket->ServiceTicketLength);
1238 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1242static BOOL nla_credentialTypeValid(UINT32 type)
1246 case InvalidCredKey:
1247 case DeprecatedIUMCredKey:
1248 case DomainUserCredKey:
1249 case LocalUserCredKey:
1250 case ExternallySuppliedCredKey:
1253 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1258WINPR_ATTR_MALLOC(free, 1)
1266 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1269 size_t pos = Stream_GetPosition(s);
1272 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1273 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1276 if (!Stream_SetPosition(s, pos))
1284 ret->Version = Stream_Get_UINT32(s);
1285 ret->Flags = Stream_Get_UINT32(s);
1286 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1288 const UINT32 val = Stream_Get_UINT32(s);
1289 if (!nla_credentialTypeValid(val))
1294 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1296 ret->EncryptedCredsSize = EncryptedCredsSize;
1297 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1308} RemoteGuardPackageCredType;
1310static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1311 RemoteGuardPackageCredType* credsType,
1317 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1321 WINPR_ASSERT(credsType);
1322 WINPR_ASSERT(payload);
1324 *credsType = RCG_TYPE_NONE;
1327 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1330 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len /
sizeof(WCHAR),
1331 packageNameStr,
sizeof(packageNameStr));
1332 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1335 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1338 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1340 *credsType = RCG_TYPE_KERB;
1342 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1344 *credsType = RCG_TYPE_NTLM;
1348 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1352 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1359 TSCREDS_INVALID = 0,
1360 TSCREDS_USER_PASSWD = 1,
1361 TSCREDS_SMARTCARD = 2,
1362 TSCREDS_REMOTEGUARD = 6
1365static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1371 WinPrAsn1_INTEGER credType = -1;
1377 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1380 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1385 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1389 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1392 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1394 rdpSettings* settings = nla->rdpcontext->settings;
1395 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1396 credType != TSCREDS_REMOTEGUARD)
1398 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1404 case TSCREDS_USER_PASSWD:
1407 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1412 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1416 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1420 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1422 case TSCREDS_SMARTCARD:
1425 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1430 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1432 settings->PasswordIsSmartcardPin = TRUE;
1436 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1438 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1442 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1446 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1448 case TSCREDS_REMOTEGUARD:
1451 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1457 .ServiceTicketLength = 0,
1458 .TicketGrantingTicketLength = 0,
1459 .ServiceTicket =
nullptr,
1460 .TicketGrantingTicket =
nullptr };
1464 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1467 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1468 wStream logonPayload = WINPR_C_ARRAY_INIT;
1469 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1472 if (logonCredsType != RCG_TYPE_KERB)
1474 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1478 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1480 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1488 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1489 Stream_GetRemainingLength(&suppCredsSeq.source))
1492 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1495 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1496 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1497 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1501 if (suppCredsType != RCG_TYPE_NTLM)
1503 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1507 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1510 WLog_ERR(TAG,
"invalid supplementalCreds");
1516 WLog_ERR(TAG,
"invalid supplementalCreds");
1520 freerdp_peer* peer = nla->rdpcontext->peer;
1521 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1526 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1536 WINPR_ASSERT(ticket);
1538 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1539 ticket->TicketGrantingTicketLength))
1542 Stream_Write_UINT32(s, KerbTicketLogon);
1543 Stream_Write_UINT32(s, ticket->Flags);
1544 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1545 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1547 Stream_Write_UINT64(s, 0x20);
1548 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1550 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1551 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1555static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1558 WINPR_ASSERT(logonTicket);
1560 SecurityFunctionTable* table =
nullptr;
1562 credssp_auth_tableAndContext(nla->auth, &table, &context);
1563 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1567static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1571 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1572 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1577 logonTicket.ServiceTicket =
nullptr;
1578 logonTicket.TicketGrantingTicket =
nullptr;
1581 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1585 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1588 s = Stream_New(
nullptr, 2000);
1592 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1595 credBuffer.len = Stream_GetPosition(s);
1596 credBuffer.data = Stream_Buffer(s);
1597 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1600 free(logonTicket.ServiceTicket);
1601 free(logonTicket.TicketGrantingTicket);
1602 Stream_Free(s, TRUE);
1606static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1611 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1615 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1619 wStream* s = Stream_New(
nullptr, 300);
1623 Stream_Write_UINT32(s, pntlm->Version);
1624 Stream_Write_UINT32(s, pntlm->Flags);
1626 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1627 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1628 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1629 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1630 Stream_Zero(s, 6 + 16 * 4 + 14);
1634 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1638 Stream_Free(s, TRUE);
1642static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1646 WinPrAsn1_tagId tag;
1647 FreeRDP_Settings_Keys_String setting_id;
1648 } cspData_fields[] = { { 1, FreeRDP_CardName },
1649 { 2, FreeRDP_ReaderName },
1650 { 3, FreeRDP_ContainerName },
1651 { 4, FreeRDP_CspName } };
1656 WINPR_ASSERT(nla->rdpcontext);
1658 const rdpSettings* settings = nla->rdpcontext->settings;
1659 WINPR_ASSERT(settings);
1662 if (!WinPrAsn1EncSeqContainer(enc))
1669 octet_string.len = ss *
sizeof(WCHAR);
1670 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1671 WinPrAsn1FreeOctetString(&octet_string);
1676 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1680 if (!WinPrAsn1EncContextualInteger(
1682 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1686 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1691 settings, cspData_fields[i].setting_id, &len);
1692 octet_string.len = len *
sizeof(WCHAR);
1693 if (octet_string.len)
1696 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1697 WinPrAsn1FreeOctetString(&octet_string);
1704 if (!WinPrAsn1EncEndContainer(enc))
1712 octet_string.len = ss *
sizeof(WCHAR);
1713 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1714 WinPrAsn1FreeOctetString(&octet_string);
1724 octet_string.len = ss *
sizeof(WCHAR);
1725 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1726 WinPrAsn1FreeOctetString(&octet_string);
1732 return WinPrAsn1EncEndContainer(enc) != 0;
1735static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1743 WINPR_ASSERT(nla->rdpcontext);
1745 const rdpSettings* settings = nla->rdpcontext->settings;
1746 WINPR_ASSERT(settings);
1749 if (!WinPrAsn1EncSeqContainer(enc))
1752 if (!settings->DisableCredentialsDelegation && nla->identity)
1754 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1755 username.data = (BYTE*)nla->identity->User;
1757 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1758 domain.data = (BYTE*)nla->identity->Domain;
1760 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1761 password.data = (BYTE*)nla->identity->Password;
1764 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1766 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1768 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1772 return WinPrAsn1EncEndContainer(enc) != 0;
1775static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1781 if (!WinPrAsn1EncSeqContainer(enc))
1785 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1788 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1796 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1799 if (!WinPrAsn1EncSeqContainer(enc))
1802 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1805 if (!WinPrAsn1EncEndContainer(enc))
1808 if (!WinPrAsn1EncEndContainer(enc))
1813 return WinPrAsn1EncEndContainer(enc) != 0;
1823static BOOL nla_encode_ts_credentials(rdpNla* nla)
1826 WinPrAsn1Encoder* enc =
nullptr;
1828 wStream s = WINPR_C_ARRAY_INIT;
1829 TsCredentialsType credType = TSCREDS_INVALID;
1832 WINPR_ASSERT(nla->rdpcontext);
1834 rdpSettings* settings = nla->rdpcontext->settings;
1835 WINPR_ASSERT(settings);
1837 if (settings->RemoteCredentialGuard)
1838 credType = TSCREDS_REMOTEGUARD;
1839 else if (settings->SmartcardLogon)
1840 credType = TSCREDS_SMARTCARD;
1842 credType = TSCREDS_USER_PASSWD;
1844 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1849 if (!WinPrAsn1EncSeqContainer(enc))
1853 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1857 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1862 case TSCREDS_SMARTCARD:
1863 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1867 case TSCREDS_USER_PASSWD:
1868 if (!nla_encode_ts_password_credentials(nla, enc))
1872 case TSCREDS_REMOTEGUARD:
1873 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1881 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1884 if (!WinPrAsn1EncStreamSize(enc, &length))
1887 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1889 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1893 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1895 ret = WinPrAsn1EncToStream(enc, &s);
1898 WinPrAsn1Encoder_Free(&enc);
1902static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1906 if (!nla_encode_ts_credentials(nla))
1909 sspi_SecBufferFree(&nla->authInfo);
1910 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
1911 nla->sendSeqNum++));
1914static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1918 if (nla->authInfo.cbBuffer < 1)
1920 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
1924 sspi_SecBufferFree(&nla->tsCredentials);
1925 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1928 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1934static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
1935 WinPrAsn1_tagId tagId,
const char* msg)
1940 WINPR_ASSERT(buffer);
1943 if (buffer->cbBuffer > 0)
1948 WLog_DBG(TAG,
" ----->> %s", msg);
1949 octet_string.data = buffer->pvBuffer;
1950 octet_string.len = buffer->cbBuffer;
1951 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1959static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
1960 WinPrAsn1_tagId tagId,
const char* msg)
1962 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1963 sspi_SecBufferFree(buffer);
1975BOOL nla_send(rdpNla* nla)
1980 WinPrAsn1Encoder* enc =
nullptr;
1984 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1989 WLog_DBG(TAG,
"----->> sending...");
1990 if (!WinPrAsn1EncSeqContainer(enc))
1994 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
1995 if (!WinPrAsn1EncContextualInteger(enc, 0,
1996 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2000 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2002 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2004 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2008 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2012 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2017 if (nla->authInfo.cbBuffer > 0)
2019 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2024 if (nla->pubKeyAuth.cbBuffer > 0)
2026 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2031 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2033 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2034 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2035 if (!WinPrAsn1EncContextualInteger(
2036 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2041 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2043 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2048 if (!WinPrAsn1EncEndContainer(enc))
2051 if (!WinPrAsn1EncStreamSize(enc, &length))
2054 s = Stream_New(
nullptr, length);
2058 if (!WinPrAsn1EncToStream(enc, s))
2061 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2062 if (transport_write(nla->transport, s) < 0)
2067 Stream_Free(s, TRUE);
2068 WinPrAsn1Encoder_Free(&enc);
2072static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2077 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2078 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2084 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2086 WLog_DBG(TAG,
"<<----- receiving...");
2089 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2095 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2098 if (!Stream_SafeSeek(s, offset))
2101 version = (UINT)val;
2102 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2104 if (nla->peerVersion == 0)
2105 nla->peerVersion = version;
2108 if (nla->peerVersion != version)
2110 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2111 nla->peerVersion, version);
2115 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2123 WLog_DBG(TAG,
" <<----- nego token");
2125 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2126 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2129 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2133 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2138 WLog_DBG(TAG,
" <<----- auth info");
2140 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2142 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2147 WLog_DBG(TAG,
" <<----- public key auth");
2149 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2151 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2157 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2159 nla->errorCode = val;
2160 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2161 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2164 WLog_DBG(TAG,
" <<----- client nonce");
2166 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2168 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2180int nla_recv_pdu(rdpNla* nla,
wStream* s)
2185 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2188 Stream_Read_UINT32(s, code);
2189 if (code != AUTHZ_SUCCESS)
2191 WLog_DBG(TAG,
"Early User Auth active: FAILURE code 0x%08" PRIX32
"", code);
2192 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2193 freerdp_set_last_error_log(nla->rdpcontext, code);
2197 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2201 if (nla_decode_ts_request(nla, s) < 1)
2208 switch (nla->errorCode)
2210 case STATUS_PASSWORD_MUST_CHANGE:
2211 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2214 case STATUS_PASSWORD_EXPIRED:
2215 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2218 case STATUS_ACCOUNT_DISABLED:
2219 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2222 case STATUS_LOGON_FAILURE:
2223 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2226 case STATUS_WRONG_PASSWORD:
2227 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2230 case STATUS_ACCESS_DENIED:
2231 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2234 case STATUS_ACCOUNT_RESTRICTION:
2235 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2238 case STATUS_ACCOUNT_LOCKED_OUT:
2239 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2242 case STATUS_ACCOUNT_EXPIRED:
2243 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2246 case STATUS_LOGON_TYPE_NOT_GRANTED:
2247 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2251 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2252 NtStatus2Tag(nla->errorCode),
2253 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2254 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2258 freerdp_set_last_error_log(nla->rdpcontext, code);
2263 return nla_client_recv(nla);
2266int nla_server_recv(rdpNla* nla)
2272 wStream* s = nla_server_recv_stream(nla);
2275 status = nla_decode_ts_request(nla, s);
2278 Stream_Free(s, TRUE);
2291rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2293 WINPR_ASSERT(transport);
2294 WINPR_ASSERT(context);
2296 rdpSettings* settings = context->settings;
2297 WINPR_ASSERT(settings);
2299 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2304 nla->rdpcontext = context;
2305 nla->server = settings->ServerMode;
2306 nla->transport = transport;
2307 nla->sendSeqNum = 0;
2308 nla->recvSeqNum = 0;
2310 nla->earlyUserAuth = FALSE;
2312 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2316 nla->auth = credssp_auth_new(context);
2321 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2325 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2330 WINPR_PRAGMA_DIAG_PUSH
2331 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2333 WINPR_PRAGMA_DIAG_POP
2342void nla_free(rdpNla* nla)
2347 smartcardCertInfo_Free(nla->smartcardCert);
2348 nla_buffer_free(nla);
2349 sspi_SecBufferFree(&nla->tsCredentials);
2350 credssp_auth_free(nla->auth);
2352 sspi_FreeAuthIdentity(nla->identity);
2353 free(nla->pkinitArgs);
2354 free(nla->identity);
2358SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2363 return nla->identity;
2366NLA_STATE nla_get_state(
const rdpNla* nla)
2369 return NLA_STATE_FINAL;
2374BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2379 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2384BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2386 return (credssp_auth_set_spn(nla->auth, service, hostname));
2389BOOL nla_impersonate(rdpNla* nla)
2391 return credssp_auth_impersonate(nla->auth);
2394BOOL nla_revert_to_self(rdpNla* nla)
2396 return credssp_auth_revert_to_self(nla->auth);
2399const char* nla_get_state_str(NLA_STATE state)
2403 case NLA_STATE_INITIAL:
2404 return "NLA_STATE_INITIAL";
2405 case NLA_STATE_NEGO_TOKEN:
2406 return "NLA_STATE_NEGO_TOKEN";
2407 case NLA_STATE_PUB_KEY_AUTH:
2408 return "NLA_STATE_PUB_KEY_AUTH";
2409 case NLA_STATE_AUTH_INFO:
2410 return "NLA_STATE_AUTH_INFO";
2411 case NLA_STATE_POST_NEGO:
2412 return "NLA_STATE_POST_NEGO";
2413 case NLA_STATE_EARLY_USER_AUTH:
2414 return "NLA_STATE_EARLY_USER_AUTH";
2415 case NLA_STATE_FINAL:
2416 return "NLA_STATE_FINAL";
2422DWORD nla_get_error(
const rdpNla* nla)
2425 return ERROR_INTERNAL_ERROR;
2426 return (UINT32)nla->errorCode;
2429INT32 nla_get_sspi_error(
const rdpNla* nla)
2432 return credssp_auth_sspi_error(nla->auth);
2438 WINPR_ASSERT(inBuffer);
2439 WINPR_ASSERT(outBuffer);
2440 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2446 WINPR_ASSERT(inBuffer);
2447 WINPR_ASSERT(outBuffer);
2448 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2451SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2455 SecurityFunctionTable* table =
nullptr;
2457 credssp_auth_tableAndContext(nla->auth, &table, &context);
2459 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2462SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2466 SecurityFunctionTable* table =
nullptr;
2468 credssp_auth_tableAndContext(nla->auth, &table, &context);
2470 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 UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API WCHAR * freerdp_settings_get_string_as_utf16(const rdpSettings *settings, FreeRDP_Settings_Keys_String id, size_t *pCharLen)
Return an allocated UTF16 string.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.