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;
140static BOOL nla_send(rdpNla* nla);
143static int nla_server_recv(rdpNla* nla);
146static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
149static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
152static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
155static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
158static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
161static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
163void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
166 WLog_DBG(TAG,
"Early User Auth active: %s", earlyUserAuth ?
"true" :
"false");
167 nla->earlyUserAuth = earlyUserAuth;
170static void nla_buffer_free(rdpNla* nla)
173 sspi_SecBufferFree(&nla->pubKeyAuth);
174 sspi_SecBufferFree(&nla->authInfo);
175 sspi_SecBufferFree(&nla->negoToken);
176 sspi_SecBufferFree(&nla->ClientNonce);
177 sspi_SecBufferFree(&nla->PublicKey);
181static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx,
const SecBuffer* buffer)
185 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
189static BOOL nla_sec_buffer_alloc(
SecBuffer* buffer,
size_t size)
191 WINPR_ASSERT(buffer);
192 sspi_SecBufferFree(buffer);
193 if (size > UINT32_MAX)
195 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
198 WINPR_ASSERT(buffer);
199 buffer->BufferType = SECBUFFER_TOKEN;
204static BOOL nla_sec_buffer_alloc_from_data(
SecBuffer* buffer,
const BYTE* data,
size_t offset,
207 if (!nla_sec_buffer_alloc(buffer, offset + size))
210 WINPR_ASSERT(buffer);
211 BYTE* pb = buffer->pvBuffer;
212 memcpy(&pb[offset], data, size);
217static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
218 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
219 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
220 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
221 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
224static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
225 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
226 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
227 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
228 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
230static const UINT32 NonceLength = 32;
233static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
238 WINPR_ASSERT(nla->rdpcontext);
240 rdpSettings* settings = nla->rdpcontext->settings;
241 WINPR_ASSERT(settings);
243 if (!settings->SmartcardLogon)
246 smartcardCertInfo_Free(nla->smartcardCert);
248 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
250 WLog_ERR(TAG,
"unable to get smartcard certificate for logon");
254 if (!settings->CspName)
259 MS_SMART_CARD_KEY_STORAGE_PROVIDER))
261 WLog_ERR(TAG,
"unable to set CSP name");
266 if (!settings->ReaderName && nla->smartcardCert->reader)
269 nla->smartcardCert->reader))
271 WLog_ERR(TAG,
"unable to copy reader name");
276 if (!settings->ContainerName && nla->smartcardCert->containerName)
279 nla->smartcardCert->containerName))
281 WLog_ERR(TAG,
"unable to copy container name");
289 WLog_ERR(TAG,
"unable to set KeySpec");
293 WLog_DBG(TAG,
"Smartcard logon: Provider='%s' Reader='%s' Container='%s' KeySpec=%" PRIu32,
299 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
301 if (nla->smartcardCert->pkinitArgs)
303 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
304 if (!nla->pkinitArgs)
306 WLog_ERR(TAG,
"unable to copy pkinitArgs");
317static BOOL nla_client_setup_identity(rdpNla* nla)
319 BOOL PromptPassword = FALSE;
322 WINPR_ASSERT(nla->rdpcontext);
324 rdpSettings* settings = nla->rdpcontext->settings;
325 WINPR_ASSERT(settings);
327 freerdp* instance = nla->rdpcontext->instance;
328 WINPR_ASSERT(instance);
331 if ((utils_str_is_empty(settings->Username) ||
332 (utils_str_is_empty(settings->Password) &&
333 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
335 PromptPassword = TRUE;
338 if (PromptPassword && !utils_str_is_empty(settings->Username))
340 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
343 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
344 WINPR_SAM_ENTRY* entry =
345 SamLookupUserA(sam, settings->Username,
346 userLength + 1 ,
nullptr, 0);
353 PromptPassword = FALSE;
354 SamFreeEntry(sam, entry);
363 if (settings->RestrictedAdminModeRequired)
365 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
366 PromptPassword = FALSE;
369 if (settings->RemoteCredentialGuard)
370 PromptPassword = FALSE;
373 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
376 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
382 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
384 case AUTH_NO_CREDENTIALS:
385 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
392 if (!settings->Username)
394 sspi_FreeAuthIdentity(nla->identity);
396 nla->identity =
nullptr;
398 else if (settings->SmartcardLogon)
400 if (smartCardLogonWasDisabled)
402 if (!nla_adjust_settings_from_smartcard(nla))
406 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
407 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
408 sizeof(nla->certSha1)))
413 BOOL usePassword = TRUE;
415 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
418 WINPR_PACKED_ALIGN_CAST(
const WCHAR*, settings->RedirectionPassword);
419 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
421 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
422 FreeRDP_Domain, wstr, len))
428 if (settings->RestrictedAdminModeRequired)
430 if (settings->PasswordHash && strnlen(settings->PasswordHash, 33) == 32)
432 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
433 FreeRDP_Domain, FreeRDP_PasswordHash))
436 nla->identity->Flags |= SEC_WINPR_AUTH_IDENTITY_PASSWORD_HASH;
443 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
444 FreeRDP_Domain, FreeRDP_Password))
453static int nla_client_init(rdpNla* nla)
456 WINPR_ASSERT(nla->rdpcontext);
458 rdpSettings* settings = nla->rdpcontext->settings;
459 WINPR_ASSERT(settings);
461 nla_set_state(nla, NLA_STATE_INITIAL);
463 if (!nla_adjust_settings_from_smartcard(nla))
466 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
469 if (!nla_client_setup_identity(nla))
474 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
477 const BYTE* data =
nullptr;
479 if (!transport_get_public_key(nla->transport, &data, &length))
481 WLog_ERR(TAG,
"Failed to get public key");
485 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
487 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
494int nla_client_begin(rdpNla* nla)
498 if (nla_client_init(nla) < 1)
501 if (nla_get_state(nla) != NLA_STATE_INITIAL)
511 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
513 const int rc = credssp_auth_authenticate(nla->auth);
520 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
523 if (credssp_auth_have_output_token(nla->auth))
528 nla_set_state(nla, NLA_STATE_FINAL);
531 switch (credssp_auth_sspi_error(nla->auth))
533 case SEC_E_LOGON_DENIED:
534 case SEC_E_NO_CREDENTIALS:
535 freerdp_set_last_error_log(nla->rdpcontext,
536 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
548static int nla_client_recv_nego_token(rdpNla* nla)
550 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
551 const int rc = credssp_auth_authenticate(nla->auth);
562 if (nla->peerVersion < 5)
563 res = nla_encrypt_public_key_echo(nla);
565 res = nla_encrypt_public_key_hash(nla);
573 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
585static int nla_client_recv_pub_key_auth(rdpNla* nla)
592 if (nla->peerVersion < 5)
593 rc = nla_decrypt_public_key_echo(nla);
595 rc = nla_decrypt_public_key_hash(nla);
597 sspi_SecBufferFree(&nla->pubKeyAuth);
603 rc = nla_encrypt_ts_credentials(nla);
610 if (nla->earlyUserAuth)
612 transport_set_early_user_auth_mode(nla->transport, TRUE);
613 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
616 nla_set_state(nla, NLA_STATE_AUTH_INFO);
621static int nla_client_recv_early_user_auth(rdpNla* nla)
625 transport_set_early_user_auth_mode(nla->transport, FALSE);
626 nla_set_state(nla, NLA_STATE_AUTH_INFO);
631static BOOL nla_send_early_user_auth(rdpNla* nla, BOOL success)
639 WLog_DBG(TAG,
"----->> sending %s", success ?
"AUTHZ_SUCCESS" :
"AUTHZ_ACCESS_DENIED");
640 wStream* s = Stream_New(
nullptr, 32);
644 Stream_Write_UINT32(s, AUTHZ_SUCCESS);
646 Stream_Write_UINT32(s, AUTHZ_ACCESS_DENIED);
647 Stream_SealLength(s);
648 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", Stream_Length(s));
649 if (transport_write(nla->transport, s) < 0)
654 Stream_Free(s, TRUE);
659static int nla_client_recv(rdpNla* nla)
663 switch (nla_get_state(nla))
665 case NLA_STATE_NEGO_TOKEN:
666 return nla_client_recv_nego_token(nla);
668 case NLA_STATE_PUB_KEY_AUTH:
669 return nla_client_recv_pub_key_auth(nla);
671 case NLA_STATE_EARLY_USER_AUTH:
672 return nla_client_recv_early_user_auth(nla);
674 case NLA_STATE_FINAL:
676 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
677 nla_get_state_str(nla_get_state(nla)));
683static int nla_client_authenticate(rdpNla* nla)
689 wStream* s = Stream_New(
nullptr, 4096);
693 WLog_ERR(TAG,
"Stream_New failed!");
697 if (nla_client_begin(nla) < 1)
700 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
702 Stream_ResetPosition(s);
703 const int status = transport_read_pdu(nla->transport, s);
707 WLog_ERR(TAG,
"nla_client_authenticate failure");
711 const int status2 = nla_recv_pdu(nla, s);
719 Stream_Free(s, TRUE);
727static int nla_server_init(rdpNla* nla)
731 const BYTE* data =
nullptr;
733 if (!transport_get_public_key(nla->transport, &data, &length))
735 WLog_ERR(TAG,
"Failed to get public key");
739 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
741 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
745 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
748 if (!credssp_auth_setup_server(nla->auth))
751 nla_set_state(nla, NLA_STATE_INITIAL);
755WINPR_ATTR_MALLOC(Stream_Free, 1)
756static
wStream* nla_server_recv_stream(rdpNla* nla)
762 wStream* s = Stream_New(
nullptr, 4096);
767 status = transport_read_pdu(nla->transport, s);
772 WLog_ERR(TAG,
"nla_recv() error: %d", status);
773 Stream_Free(s, TRUE);
781static BOOL nla_server_recv_credentials(rdpNla* nla)
785 if (nla_server_recv(nla) < 0)
788 if (!nla_decrypt_ts_credentials(nla))
791 if (!nla_impersonate(nla))
794 if (!nla_revert_to_self(nla))
807static int nla_server_authenticate(rdpNla* nla)
813 if (nla_server_init(nla) < 1)
822 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
823 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
824 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
856 if (nla_server_recv(nla) < 0)
859 WLog_DBG(TAG,
"Receiving Authentication Token");
860 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
862 res = credssp_auth_authenticate(nla->auth);
869 switch (GetLastError())
871 case ERROR_PASSWORD_MUST_CHANGE:
872 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
875 case ERROR_PASSWORD_EXPIRED:
876 nla->errorCode = STATUS_PASSWORD_EXPIRED;
879 case ERROR_ACCOUNT_DISABLED:
880 nla->errorCode = STATUS_ACCOUNT_DISABLED;
885 nla->errorCode = STATUS_LOGON_FAILURE;
886 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
887 if (sspi != SEC_E_OK)
888 WLog_DBG(TAG,
"[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
889 GetSecurityStatusString(sspi));
902 if (credssp_auth_have_output_token(nla->auth))
907 if (nla_server_recv(nla) < 0)
910 WLog_DBG(TAG,
"Receiving pubkey Token");
913 if (nla->peerVersion < 5)
914 res = nla_decrypt_public_key_echo(nla);
916 res = nla_decrypt_public_key_hash(nla);
922 sspi_SecBufferFree(&nla->negoToken);
924 if (nla->peerVersion < 5)
925 res = nla_encrypt_public_key_echo(nla);
927 res = nla_encrypt_public_key_hash(nla);
934 WLog_DBG(TAG,
"Sending Authentication Token");
941 if (nla->earlyUserAuth)
943 if (!nla_send_early_user_auth(nla, TRUE))
952 if (!nla_server_recv_credentials(nla))
956 nla_buffer_free(nla);
967int nla_authenticate(rdpNla* nla)
972 return nla_server_authenticate(nla);
974 return nla_client_authenticate(nla);
977static void ap_integer_increment_le(BYTE* number,
size_t size)
979 WINPR_ASSERT(number || (size == 0));
981 for (
size_t index = 0; index < size; index++)
983 if (number[index] < 0xFF)
996static void ap_integer_decrement_le(BYTE* number,
size_t size)
998 WINPR_ASSERT(number || (size == 0));
1000 for (
size_t index = 0; index < size; index++)
1002 if (number[index] > 0)
1009 number[index] = 0xFF;
1015BOOL nla_encrypt_public_key_echo(rdpNla* nla)
1017 BOOL status = FALSE;
1021 sspi_SecBufferFree(&nla->pubKeyAuth);
1025 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
1027 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
1029 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
1030 sspi_SecBufferFree(&buf);
1034 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
1041BOOL nla_encrypt_public_key_hash(rdpNla* nla)
1043 BOOL status = FALSE;
1044 WINPR_DIGEST_CTX* sha256 =
nullptr;
1049 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
1050 const size_t hashSize =
1051 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
1053 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
1057 if (!(sha256 = winpr_Digest_New()))
1060 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1064 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1067 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1071 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1074 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1077 sspi_SecBufferFree(&nla->pubKeyAuth);
1078 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1084 winpr_Digest_Free(sha256);
1085 sspi_SecBufferFree(&buf);
1089BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1091 BOOL status = FALSE;
1092 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1097 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1103 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1106 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1107 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1109 WLog_ERR(TAG,
"Could not verify server's public key echo");
1110#if defined(WITH_DEBUG_NLA)
1111 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1112 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1113 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1114 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1122 sspi_SecBufferFree(&public_key);
1126BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1128 WINPR_DIGEST_CTX* sha256 =
nullptr;
1129 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1130 BOOL status = FALSE;
1134 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1135 const size_t hashSize =
1136 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1139 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1143 if (!(sha256 = winpr_Digest_New()))
1146 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1150 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1153 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1157 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1160 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1164 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1165 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1167 WLog_ERR(TAG,
"Could not verify server's hash");
1174 winpr_Digest_Free(sha256);
1175 sspi_SecBufferFree(&hash);
1180static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1181 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1182 rdpSettings* settings)
1186 WinPrAsn1_tagId itemTag = 0;
1187 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1196 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, TRUE))
1200 settings, settingId, WINPR_PACKED_ALIGN_CAST(
const WCHAR*, value.data),
1201 value.len /
sizeof(WCHAR));
1207static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1212 WinPrAsn1_INTEGER keyspec = 0;
1213 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1215 settings->KeySpec = (UINT32)keyspec;
1218 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1222 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1226 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1230 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1234static BOOL nla_messageTypeValid(UINT32 type)
1238 case KerbInvalidValue:
1239 case KerbInteractiveLogon:
1240 case KerbSmartCardLogon:
1241 case KerbWorkstationUnlockLogon:
1242 case KerbSmartCardUnlockLogon:
1243 case KerbProxyLogon:
1244 case KerbTicketLogon:
1245 case KerbTicketUnlockLogon:
1246#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1249#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1250 case KerbCertificateLogon:
1251 case KerbCertificateS4ULogon:
1252 case KerbCertificateUnlockLogon:
1254#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1255 case KerbNoElevationLogon:
1260 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1266static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1275 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1279 const UINT32 type = Stream_Get_UINT32(s);
1280 if (!nla_messageTypeValid(type))
1283 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1285 Stream_Read_UINT32(s, ticket->Flags);
1286 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1287 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1289 if (ticket->MessageType != KerbTicketLogon)
1291 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1295 if (!Stream_CheckAndLogRequiredLength(
1296 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1304 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1305 Stream_Seek(s, ticket->ServiceTicketLength);
1310 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1315static BOOL nla_credentialTypeValid(UINT32 type)
1319 case InvalidCredKey:
1320 case DeprecatedIUMCredKey:
1321 case DomainUserCredKey:
1322 case LocalUserCredKey:
1323 case ExternallySuppliedCredKey:
1326 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1331WINPR_ATTR_MALLOC(free, 1)
1338 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1341 size_t pos = Stream_GetPosition(s);
1344 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1345 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1348 if (!Stream_SetPosition(s, pos))
1356 ret->Version = Stream_Get_UINT32(s);
1357 ret->Flags = Stream_Get_UINT32(s);
1358 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1360 const UINT32 val = Stream_Get_UINT32(s);
1361 if (!nla_credentialTypeValid(val))
1366 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1368 ret->EncryptedCredsSize = EncryptedCredsSize;
1369 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1380} RemoteGuardPackageCredType;
1383static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1384 RemoteGuardPackageCredType* credsType,
1389 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1393 WINPR_ASSERT(credsType);
1394 WINPR_ASSERT(payload);
1396 *credsType = RCG_TYPE_NONE;
1401 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, TRUE) || error)
1404 ConvertMszWCharNToUtf8(WINPR_PACKED_ALIGN_CAST(WCHAR*, packageName.data),
1405 packageName.len /
sizeof(WCHAR), packageNameStr,
1406 sizeof(packageNameStr));
1407 free(packageName.data);
1409 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1412 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1415 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1417 *credsType = RCG_TYPE_KERB;
1419 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1421 *credsType = RCG_TYPE_NTLM;
1425 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1429 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1436 TSCREDS_INVALID = 0,
1437 TSCREDS_USER_PASSWD = 1,
1438 TSCREDS_SMARTCARD = 2,
1439 TSCREDS_REMOTEGUARD = 6
1443static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1449 WinPrAsn1_INTEGER credType = -1;
1455 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1458 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1463 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1467 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1470 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1472 rdpSettings* settings = nla->rdpcontext->settings;
1473 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1474 credType != TSCREDS_REMOTEGUARD)
1476 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1482 case TSCREDS_USER_PASSWD:
1485 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1490 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1494 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1498 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1500 case TSCREDS_SMARTCARD:
1503 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1508 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1510 settings->PasswordIsSmartcardPin = TRUE;
1514 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1516 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1520 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1524 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1526 case TSCREDS_REMOTEGUARD:
1529 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1535 .ServiceTicketLength = 0,
1536 .TicketGrantingTicketLength = 0,
1537 .ServiceTicket =
nullptr,
1538 .TicketGrantingTicket =
nullptr };
1542 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1545 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1546 wStream logonPayload = WINPR_C_ARRAY_INIT;
1547 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1550 if (logonCredsType != RCG_TYPE_KERB)
1552 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1556 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1558 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1566 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1567 Stream_GetRemainingLength(&suppCredsSeq.source))
1570 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1573 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1574 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1575 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1579 if (suppCredsType != RCG_TYPE_NTLM)
1581 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1585 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1588 WLog_ERR(TAG,
"invalid supplementalCreds");
1594 WLog_ERR(TAG,
"invalid supplementalCreds");
1598 freerdp_peer* peer = nla->rdpcontext->peer;
1599 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1604 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1615 WINPR_ASSERT(ticket);
1617 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1618 ticket->TicketGrantingTicketLength))
1621 Stream_Write_UINT32(s, KerbTicketLogon);
1622 Stream_Write_UINT32(s, ticket->Flags);
1623 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1624 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1626 Stream_Write_UINT64(s, 0x20);
1627 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1629 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1630 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1635static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1638 WINPR_ASSERT(logonTicket);
1640 SecurityFunctionTable* table =
nullptr;
1642 credssp_auth_tableAndContext(nla->auth, &table, &context);
1643 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1648static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1652 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1653 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1658 logonTicket.ServiceTicket =
nullptr;
1659 logonTicket.TicketGrantingTicket =
nullptr;
1662 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1666 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1669 s = Stream_New(
nullptr, 2000);
1673 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1676 credBuffer.len = Stream_GetPosition(s);
1677 credBuffer.data = Stream_Buffer(s);
1678 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1681 free(logonTicket.ServiceTicket);
1682 free(logonTicket.TicketGrantingTicket);
1683 Stream_Free(s, TRUE);
1688static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1693 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1697 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1701 wStream* s = Stream_New(
nullptr, 300);
1705 Stream_Write_UINT32(s, pntlm->Version);
1706 Stream_Write_UINT32(s, pntlm->Flags);
1708 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1709 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1710 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1711 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1712 Stream_Zero(s, 6 + 16 * 4 + 14);
1716 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1720 Stream_Free(s, TRUE);
1725static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1729 WinPrAsn1_tagId tag;
1730 FreeRDP_Settings_Keys_String setting_id;
1731 } cspData_fields[] = { { 1, FreeRDP_CardName },
1732 { 2, FreeRDP_ReaderName },
1733 { 3, FreeRDP_ContainerName },
1734 { 4, FreeRDP_CspName } };
1739 WINPR_ASSERT(nla->rdpcontext);
1741 const rdpSettings* settings = nla->rdpcontext->settings;
1742 WINPR_ASSERT(settings);
1745 if (!WinPrAsn1EncSeqContainer(enc))
1752 octet_string.len = ss *
sizeof(WCHAR);
1753 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1754 WinPrAsn1FreeOctetString(&octet_string);
1759 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1763 if (!WinPrAsn1EncContextualInteger(
1765 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1769 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1774 settings, cspData_fields[i].setting_id, &len);
1775 octet_string.len = len *
sizeof(WCHAR);
1776 if (octet_string.len)
1779 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1780 WinPrAsn1FreeOctetString(&octet_string);
1787 if (!WinPrAsn1EncEndContainer(enc))
1795 octet_string.len = ss *
sizeof(WCHAR);
1796 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1797 WinPrAsn1FreeOctetString(&octet_string);
1807 octet_string.len = ss *
sizeof(WCHAR);
1808 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1809 WinPrAsn1FreeOctetString(&octet_string);
1815 return WinPrAsn1EncEndContainer(enc) != 0;
1819static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1827 WINPR_ASSERT(nla->rdpcontext);
1829 const rdpSettings* settings = nla->rdpcontext->settings;
1830 WINPR_ASSERT(settings);
1833 if (!WinPrAsn1EncSeqContainer(enc))
1836 const BOOL enabled =
1839 if (enabled && nla->identity)
1841 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1842 username.data = (BYTE*)nla->identity->User;
1844 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1845 domain.data = (BYTE*)nla->identity->Domain;
1847 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1848 password.data = (BYTE*)nla->identity->Password;
1851 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1853 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1855 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1859 return WinPrAsn1EncEndContainer(enc) != 0;
1863static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1869 if (!WinPrAsn1EncSeqContainer(enc))
1873 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1876 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1884 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1887 if (!WinPrAsn1EncSeqContainer(enc))
1890 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1893 if (!WinPrAsn1EncEndContainer(enc))
1896 if (!WinPrAsn1EncEndContainer(enc))
1901 return WinPrAsn1EncEndContainer(enc) != 0;
1911static BOOL nla_encode_ts_credentials(rdpNla* nla)
1914 WinPrAsn1Encoder* enc =
nullptr;
1916 wStream s = WINPR_C_ARRAY_INIT;
1917 TsCredentialsType credType = TSCREDS_INVALID;
1920 WINPR_ASSERT(nla->rdpcontext);
1922 rdpSettings* settings = nla->rdpcontext->settings;
1923 WINPR_ASSERT(settings);
1925 if (settings->RemoteCredentialGuard)
1926 credType = TSCREDS_REMOTEGUARD;
1927 else if (settings->SmartcardLogon)
1928 credType = TSCREDS_SMARTCARD;
1930 credType = TSCREDS_USER_PASSWD;
1932 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1937 if (!WinPrAsn1EncSeqContainer(enc))
1941 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1945 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1950 case TSCREDS_SMARTCARD:
1951 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1955 case TSCREDS_USER_PASSWD:
1956 if (!nla_encode_ts_password_credentials(nla, enc))
1960 case TSCREDS_REMOTEGUARD:
1961 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1969 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1972 if (!WinPrAsn1EncStreamSize(enc, &length))
1975 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1977 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1981 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1983 ret = WinPrAsn1EncToStream(enc, &s);
1986 WinPrAsn1Encoder_Free(&enc);
1991static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1995 if (!nla_encode_ts_credentials(nla))
1998 sspi_SecBufferFree(&nla->authInfo);
1999 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
2000 nla->sendSeqNum++));
2004static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
2008 if (nla->authInfo.cbBuffer < 1)
2010 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
2014 sspi_SecBufferFree(&nla->tsCredentials);
2015 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
2018 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
2025static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
2026 WinPrAsn1_tagId tagId,
const char* msg)
2031 WINPR_ASSERT(buffer);
2034 if (buffer->cbBuffer > 0)
2039 WLog_DBG(TAG,
" ----->> %s", msg);
2040 octet_string.data = buffer->pvBuffer;
2041 octet_string.len = buffer->cbBuffer;
2042 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
2051static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
2052 WinPrAsn1_tagId tagId,
const char* msg)
2054 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
2055 sspi_SecBufferFree(buffer);
2067BOOL nla_send(rdpNla* nla)
2072 WinPrAsn1Encoder* enc =
nullptr;
2076 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
2081 WLog_DBG(TAG,
"----->> sending...");
2082 if (!WinPrAsn1EncSeqContainer(enc))
2086 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
2087 if (!WinPrAsn1EncContextualInteger(enc, 0,
2088 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2092 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2094 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2096 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2100 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2104 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2109 if (nla->authInfo.cbBuffer > 0)
2111 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2116 if (nla->pubKeyAuth.cbBuffer > 0)
2118 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2123 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2125 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2126 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2127 if (!WinPrAsn1EncContextualInteger(
2128 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2133 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2135 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2140 if (!WinPrAsn1EncEndContainer(enc))
2143 if (!WinPrAsn1EncStreamSize(enc, &length))
2146 s = Stream_New(
nullptr, length);
2150 if (!WinPrAsn1EncToStream(enc, s))
2153 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2154 if (transport_write(nla->transport, s) < 0)
2159 Stream_Free(s, TRUE);
2160 WinPrAsn1Encoder_Free(&enc);
2165static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2170 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2171 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2177 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2179 WLog_DBG(TAG,
"<<----- receiving...");
2182 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2188 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2191 if (!Stream_SafeSeek(s, offset))
2194 version = (UINT)val;
2195 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2197 if (nla->peerVersion == 0)
2198 nla->peerVersion = version;
2201 if (nla->peerVersion != version)
2203 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2204 nla->peerVersion, version);
2208 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2216 WLog_DBG(TAG,
" <<----- nego token");
2218 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2219 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2222 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2226 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2231 WLog_DBG(TAG,
" <<----- auth info");
2233 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2235 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2240 WLog_DBG(TAG,
" <<----- public key auth");
2242 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2244 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2250 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2252 nla->errorCode = val;
2253 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2254 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2257 WLog_DBG(TAG,
" <<----- client nonce");
2259 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2261 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2273int nla_recv_pdu(rdpNla* nla,
wStream* s)
2278 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2280 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2283 const UINT32 authzResult = Stream_Get_UINT32(s);
2284 if (authzResult != AUTHZ_SUCCESS)
2286 UINT32 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2288 switch (authzResult)
2290 case AUTHZ_ACCESS_DENIED:
2294 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2300 WLog_ERR(TAG,
"Early User Auth active: FAILURE authorization result 0x%08" PRIX32
"",
2302 freerdp_set_last_error_log(nla->rdpcontext, code);
2306 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2310 if (nla_decode_ts_request(nla, s) < 1)
2317 switch (nla->errorCode)
2319 case STATUS_PASSWORD_MUST_CHANGE:
2320 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2323 case STATUS_PASSWORD_EXPIRED:
2324 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2327 case STATUS_ACCOUNT_DISABLED:
2328 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2331 case STATUS_LOGON_FAILURE:
2332 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2335 case STATUS_WRONG_PASSWORD:
2336 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2339 case STATUS_ACCESS_DENIED:
2340 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2343 case STATUS_ACCOUNT_RESTRICTION:
2344 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2347 case STATUS_ACCOUNT_LOCKED_OUT:
2348 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2351 case STATUS_ACCOUNT_EXPIRED:
2352 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2355 case STATUS_LOGON_TYPE_NOT_GRANTED:
2356 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2360 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2361 NtStatus2Tag(nla->errorCode),
2362 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2363 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2367 freerdp_set_last_error_log(nla->rdpcontext, code);
2372 return nla_client_recv(nla);
2375int nla_server_recv(rdpNla* nla)
2381 wStream* s = nla_server_recv_stream(nla);
2384 status = nla_decode_ts_request(nla, s);
2387 Stream_Free(s, TRUE);
2400rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2402 WINPR_ASSERT(transport);
2403 WINPR_ASSERT(context);
2405 rdpSettings* settings = context->settings;
2406 WINPR_ASSERT(settings);
2408 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2413 nla->rdpcontext = context;
2414 nla->server = settings->ServerMode;
2415 nla->transport = transport;
2416 nla->sendSeqNum = 0;
2417 nla->recvSeqNum = 0;
2419 nla->earlyUserAuth = FALSE;
2421 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2425 nla->auth = credssp_auth_new(context);
2430 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2434 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2439 WINPR_PRAGMA_DIAG_PUSH
2440 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2442 WINPR_PRAGMA_DIAG_POP
2451void nla_free(rdpNla* nla)
2456 smartcardCertInfo_Free(nla->smartcardCert);
2457 nla_buffer_free(nla);
2458 sspi_SecBufferFree(&nla->tsCredentials);
2459 credssp_auth_free(nla->auth);
2461 sspi_FreeAuthIdentity(nla->identity);
2462 free(nla->pkinitArgs);
2463 free(nla->identity);
2467SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2472 return nla->identity;
2475NLA_STATE nla_get_state(
const rdpNla* nla)
2478 return NLA_STATE_FINAL;
2483BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2488 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2493BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2495 return (credssp_auth_set_spn(nla->auth, service, hostname));
2498BOOL nla_impersonate(rdpNla* nla)
2500 return credssp_auth_impersonate(nla->auth);
2503BOOL nla_revert_to_self(rdpNla* nla)
2505 return credssp_auth_revert_to_self(nla->auth);
2508const char* nla_get_state_str(NLA_STATE state)
2512 case NLA_STATE_INITIAL:
2513 return "NLA_STATE_INITIAL";
2514 case NLA_STATE_NEGO_TOKEN:
2515 return "NLA_STATE_NEGO_TOKEN";
2516 case NLA_STATE_PUB_KEY_AUTH:
2517 return "NLA_STATE_PUB_KEY_AUTH";
2518 case NLA_STATE_AUTH_INFO:
2519 return "NLA_STATE_AUTH_INFO";
2520 case NLA_STATE_POST_NEGO:
2521 return "NLA_STATE_POST_NEGO";
2522 case NLA_STATE_EARLY_USER_AUTH:
2523 return "NLA_STATE_EARLY_USER_AUTH";
2524 case NLA_STATE_FINAL:
2525 return "NLA_STATE_FINAL";
2531DWORD nla_get_error(
const rdpNla* nla)
2534 return ERROR_INTERNAL_ERROR;
2535 return (UINT32)nla->errorCode;
2538INT32 nla_get_sspi_error(
const rdpNla* nla)
2541 return credssp_auth_sspi_error(nla->auth);
2547 WINPR_ASSERT(inBuffer);
2548 WINPR_ASSERT(outBuffer);
2549 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2555 WINPR_ASSERT(inBuffer);
2556 WINPR_ASSERT(outBuffer);
2557 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2560SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2564 SecurityFunctionTable* table =
nullptr;
2566 credssp_auth_tableAndContext(nla->auth, &table, &context);
2568 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2571SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2575 SecurityFunctionTable* table =
nullptr;
2577 credssp_auth_tableAndContext(nla->auth, &table, &context);
2579 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.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.