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>
48#include "../crypto/tls.h"
53#include "credssp_auth.h"
54#include <freerdp/utils/smartcardlogon.h>
56#define TAG FREERDP_TAG("core.nla")
58#define NLA_AUTH_PKG NEGO_SSP_NAME
62 AUTHZ_SUCCESS = 0x00000000,
63 AUTHZ_ACCESS_DENIED = 0x00000005,
115 rdpContext* rdpcontext;
116 rdpTransport* transport;
131 SEC_WINNT_AUTH_IDENTITY* identity;
133 rdpCredsspAuth* auth;
141static BOOL nla_send(rdpNla* nla);
144static int nla_server_recv(rdpNla* nla);
147static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
150static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
153static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
156static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
159static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
162static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
164void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
167 WLog_DBG(TAG,
"Early User Auth active: %s", earlyUserAuth ?
"true" :
"false");
168 nla->earlyUserAuth = earlyUserAuth;
171static void nla_buffer_free(rdpNla* nla)
174 sspi_SecBufferFree(&nla->pubKeyAuth);
175 sspi_SecBufferFree(&nla->authInfo);
176 sspi_SecBufferFree(&nla->negoToken);
177 sspi_SecBufferFree(&nla->ClientNonce);
178 sspi_SecBufferFree(&nla->PublicKey);
182static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx,
const SecBuffer* buffer)
186 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
190static BOOL nla_sec_buffer_alloc(
SecBuffer* buffer,
size_t size)
192 WINPR_ASSERT(buffer);
193 sspi_SecBufferFree(buffer);
194 if (size > UINT32_MAX)
196 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
199 WINPR_ASSERT(buffer);
200 buffer->BufferType = SECBUFFER_TOKEN;
205static BOOL nla_sec_buffer_alloc_from_data(
SecBuffer* buffer,
const BYTE* data,
size_t offset,
208 if (!nla_sec_buffer_alloc(buffer, offset + size))
211 WINPR_ASSERT(buffer);
212 BYTE* pb = buffer->pvBuffer;
213 memcpy(&pb[offset], data, size);
218static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
219 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
220 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
221 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
222 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
225static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
226 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
227 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
228 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
229 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
231static const UINT32 NonceLength = 32;
234static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
239 WINPR_ASSERT(nla->rdpcontext);
241 rdpSettings* settings = nla->rdpcontext->settings;
242 WINPR_ASSERT(settings);
244 if (!settings->SmartcardLogon)
247 smartcardCertInfo_Free(nla->smartcardCert);
249 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
251 WLog_ERR(TAG,
"unable to get smartcard certificate for logon");
255 if (!settings->CspName)
260 MS_SMART_CARD_KEY_STORAGE_PROVIDER))
262 WLog_ERR(TAG,
"unable to set CSP name");
267 if (!settings->ReaderName && nla->smartcardCert->reader)
270 nla->smartcardCert->reader))
272 WLog_ERR(TAG,
"unable to copy reader name");
277 if (!settings->ContainerName && nla->smartcardCert->containerName)
280 nla->smartcardCert->containerName))
282 WLog_ERR(TAG,
"unable to copy container name");
290 WLog_ERR(TAG,
"unable to set KeySpec");
294 WLog_DBG(TAG,
"Smartcard logon: Provider='%s' Reader='%s' Container='%s' KeySpec=%" PRIu32,
300 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
302 if (nla->smartcardCert->pkinitArgs)
304 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
305 if (!nla->pkinitArgs)
307 WLog_ERR(TAG,
"unable to copy pkinitArgs");
318static BOOL nla_client_setup_identity(rdpNla* nla)
320 BOOL PromptPassword = FALSE;
323 WINPR_ASSERT(nla->rdpcontext);
325 rdpSettings* settings = nla->rdpcontext->settings;
326 WINPR_ASSERT(settings);
328 freerdp* instance = nla->rdpcontext->instance;
329 WINPR_ASSERT(instance);
332 if ((utils_str_is_empty(settings->Username) ||
333 (utils_str_is_empty(settings->Password) &&
334 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
336 PromptPassword = TRUE;
339 if (PromptPassword && !utils_str_is_empty(settings->Username))
341 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
344 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
345 WINPR_SAM_ENTRY* entry =
346 SamLookupUserA(sam, settings->Username,
347 userLength + 1 ,
nullptr, 0);
354 PromptPassword = FALSE;
355 SamFreeEntry(sam, entry);
364 if (settings->RestrictedAdminModeRequired)
366 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
367 PromptPassword = FALSE;
370 if (settings->RemoteCredentialGuard)
371 PromptPassword = FALSE;
374 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
377 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
383 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
385 case AUTH_NO_CREDENTIALS:
386 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
393 if (!settings->Username)
395 sspi_FreeAuthIdentity(nla->identity);
397 nla->identity =
nullptr;
399 else if (settings->SmartcardLogon)
401 if (smartCardLogonWasDisabled)
403 if (!nla_adjust_settings_from_smartcard(nla))
407 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
408 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
409 sizeof(nla->certSha1)))
414 BOOL usePassword = TRUE;
416 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
419 WINPR_PACKED_ALIGN_CAST(
const WCHAR*, settings->RedirectionPassword);
420 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
422 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
423 FreeRDP_Domain, wstr, len))
429 if (settings->RestrictedAdminModeRequired)
431 if (settings->PasswordHash && strnlen(settings->PasswordHash, 33) == 32)
433 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
434 FreeRDP_Domain, FreeRDP_PasswordHash))
437 nla->identity->Flags |= SEC_WINPR_AUTH_IDENTITY_PASSWORD_HASH;
444 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
445 FreeRDP_Domain, FreeRDP_Password))
454static int nla_client_init(rdpNla* nla)
457 WINPR_ASSERT(nla->rdpcontext);
459 rdpSettings* settings = nla->rdpcontext->settings;
460 WINPR_ASSERT(settings);
462 nla_set_state(nla, NLA_STATE_INITIAL);
464 if (!nla_adjust_settings_from_smartcard(nla))
467 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
470 if (!nla_client_setup_identity(nla))
475 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
478 const BYTE* data =
nullptr;
480 if (!transport_get_public_key(nla->transport, &data, &length))
482 WLog_ERR(TAG,
"Failed to get public key");
486 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
488 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
495int nla_client_begin(rdpNla* nla)
499 if (nla_client_init(nla) < 1)
502 if (nla_get_state(nla) != NLA_STATE_INITIAL)
512 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
514 const int rc = credssp_auth_authenticate(nla->auth);
521 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
524 if (credssp_auth_have_output_token(nla->auth))
529 nla_set_state(nla, NLA_STATE_FINAL);
532 switch (credssp_auth_sspi_error(nla->auth))
534 case SEC_E_LOGON_DENIED:
535 case SEC_E_NO_CREDENTIALS:
536 freerdp_set_last_error_log(nla->rdpcontext,
537 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
549static int nla_client_recv_nego_token(rdpNla* nla)
551 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
552 const int rc = credssp_auth_authenticate(nla->auth);
563 if (nla->peerVersion < 5)
564 res = nla_encrypt_public_key_echo(nla);
566 res = nla_encrypt_public_key_hash(nla);
574 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
586static int nla_client_recv_pub_key_auth(rdpNla* nla)
593 if (nla->peerVersion < 5)
594 rc = nla_decrypt_public_key_echo(nla);
596 rc = nla_decrypt_public_key_hash(nla);
598 sspi_SecBufferFree(&nla->pubKeyAuth);
604 rc = nla_encrypt_ts_credentials(nla);
611 if (nla->earlyUserAuth)
613 transport_set_early_user_auth_mode(nla->transport, TRUE);
614 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
617 nla_set_state(nla, NLA_STATE_AUTH_INFO);
622static int nla_client_recv_early_user_auth(rdpNla* nla)
626 transport_set_early_user_auth_mode(nla->transport, FALSE);
627 nla_set_state(nla, NLA_STATE_AUTH_INFO);
632static BOOL nla_send_early_user_auth(rdpNla* nla, BOOL success)
640 WLog_DBG(TAG,
"----->> sending %s", success ?
"AUTHZ_SUCCESS" :
"AUTHZ_ACCESS_DENIED");
641 wStream* s = Stream_New(
nullptr, 32);
645 Stream_Write_UINT32(s, AUTHZ_SUCCESS);
647 Stream_Write_UINT32(s, AUTHZ_ACCESS_DENIED);
648 Stream_SealLength(s);
649 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", Stream_Length(s));
650 if (transport_write(nla->transport, s) < 0)
655 Stream_Free(s, TRUE);
660static int nla_client_recv(rdpNla* nla)
664 switch (nla_get_state(nla))
666 case NLA_STATE_NEGO_TOKEN:
667 return nla_client_recv_nego_token(nla);
669 case NLA_STATE_PUB_KEY_AUTH:
670 return nla_client_recv_pub_key_auth(nla);
672 case NLA_STATE_EARLY_USER_AUTH:
673 return nla_client_recv_early_user_auth(nla);
675 case NLA_STATE_FINAL:
677 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
678 nla_get_state_str(nla_get_state(nla)));
684static int nla_client_authenticate(rdpNla* nla)
690 wStream* s = Stream_New(
nullptr, 4096);
694 WLog_ERR(TAG,
"Stream_New failed!");
698 if (nla_client_begin(nla) < 1)
701 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
703 Stream_ResetPosition(s);
704 const int status = transport_read_pdu(nla->transport, s);
708 WLog_ERR(TAG,
"nla_client_authenticate failure");
712 const int status2 = nla_recv_pdu(nla, s);
720 Stream_Free(s, TRUE);
728static int nla_server_init(rdpNla* nla)
732 const BYTE* data =
nullptr;
734 if (!transport_get_public_key(nla->transport, &data, &length))
736 WLog_ERR(TAG,
"Failed to get public key");
740 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
742 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
746 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
749 if (!credssp_auth_setup_server(nla->auth))
752 nla_set_state(nla, NLA_STATE_INITIAL);
756WINPR_ATTR_MALLOC(Stream_Free, 1)
757static
wStream* nla_server_recv_stream(rdpNla* nla)
763 wStream* s = Stream_New(
nullptr, 4096);
768 status = transport_read_pdu(nla->transport, s);
773 WLog_ERR(TAG,
"nla_recv() error: %d", status);
774 Stream_Free(s, TRUE);
782static BOOL nla_server_recv_credentials(rdpNla* nla)
786 if (nla_server_recv(nla) < 0)
789 if (!nla_decrypt_ts_credentials(nla))
792 if (!nla_impersonate(nla))
795 if (!nla_revert_to_self(nla))
808static int nla_server_authenticate(rdpNla* nla)
814 if (nla_server_init(nla) < 1)
823 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
824 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
825 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
857 if (nla_server_recv(nla) < 0)
860 WLog_DBG(TAG,
"Receiving Authentication Token");
861 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
863 res = credssp_auth_authenticate(nla->auth);
870 switch (GetLastError())
872 case ERROR_PASSWORD_MUST_CHANGE:
873 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
876 case ERROR_PASSWORD_EXPIRED:
877 nla->errorCode = STATUS_PASSWORD_EXPIRED;
880 case ERROR_ACCOUNT_DISABLED:
881 nla->errorCode = STATUS_ACCOUNT_DISABLED;
886 nla->errorCode = STATUS_LOGON_FAILURE;
887 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
888 if (sspi != SEC_E_OK)
889 WLog_DBG(TAG,
"[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
890 GetSecurityStatusString(sspi));
903 if (credssp_auth_have_output_token(nla->auth))
908 if (nla_server_recv(nla) < 0)
911 WLog_DBG(TAG,
"Receiving pubkey Token");
914 if (nla->peerVersion < 5)
915 res = nla_decrypt_public_key_echo(nla);
917 res = nla_decrypt_public_key_hash(nla);
923 sspi_SecBufferFree(&nla->negoToken);
925 if (nla->peerVersion < 5)
926 res = nla_encrypt_public_key_echo(nla);
928 res = nla_encrypt_public_key_hash(nla);
935 WLog_DBG(TAG,
"Sending Authentication Token");
948 if (!nla_server_recv_credentials(nla))
950 else if (nla->earlyUserAuth)
952 if (!nla_send_early_user_auth(nla, ret == 1))
957 nla_buffer_free(nla);
968int nla_authenticate(rdpNla* nla)
973 return nla_server_authenticate(nla);
975 return nla_client_authenticate(nla);
978static void ap_integer_increment_le(BYTE* number,
size_t size)
980 WINPR_ASSERT(number || (size == 0));
982 for (
size_t index = 0; index < size; index++)
984 if (number[index] < 0xFF)
997static void ap_integer_decrement_le(BYTE* number,
size_t size)
999 WINPR_ASSERT(number || (size == 0));
1001 for (
size_t index = 0; index < size; index++)
1003 if (number[index] > 0)
1010 number[index] = 0xFF;
1016BOOL nla_encrypt_public_key_echo(rdpNla* nla)
1018 BOOL status = FALSE;
1022 sspi_SecBufferFree(&nla->pubKeyAuth);
1026 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
1028 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
1030 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
1031 sspi_SecBufferFree(&buf);
1035 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
1042BOOL nla_encrypt_public_key_hash(rdpNla* nla)
1044 BOOL status = FALSE;
1045 WINPR_DIGEST_CTX* sha256 =
nullptr;
1050 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
1051 const size_t hashSize =
1052 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
1054 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
1058 if (!(sha256 = winpr_Digest_New()))
1061 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1065 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1068 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1072 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1075 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1078 sspi_SecBufferFree(&nla->pubKeyAuth);
1079 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1085 winpr_Digest_Free(sha256);
1086 sspi_SecBufferFree(&buf);
1090BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1092 BOOL status = FALSE;
1093 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1098 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1104 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1107 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1108 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1110 WLog_ERR(TAG,
"Could not verify server's public key echo");
1111#if defined(WITH_DEBUG_NLA)
1112 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1113 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1114 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1115 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1123 sspi_SecBufferFree(&public_key);
1127BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1129 WINPR_DIGEST_CTX* sha256 =
nullptr;
1130 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1131 BOOL status = FALSE;
1135 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1136 const size_t hashSize =
1137 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1140 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1144 if (!(sha256 = winpr_Digest_New()))
1147 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1151 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1154 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1158 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1161 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1165 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1166 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1168 WLog_ERR(TAG,
"Could not verify server's hash");
1175 winpr_Digest_Free(sha256);
1176 sspi_SecBufferFree(&hash);
1181static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1182 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1183 rdpSettings* settings)
1187 WinPrAsn1_tagId itemTag = 0;
1188 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1197 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, TRUE))
1201 settings, settingId, WINPR_PACKED_ALIGN_CAST(
const WCHAR*, value.data),
1202 value.len /
sizeof(WCHAR));
1208static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1213 WinPrAsn1_INTEGER keyspec = 0;
1214 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1216 settings->KeySpec = (UINT32)keyspec;
1219 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1223 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1227 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1231 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1235static BOOL nla_messageTypeValid(UINT32 type)
1239 case KerbInvalidValue:
1240 case KerbInteractiveLogon:
1241 case KerbSmartCardLogon:
1242 case KerbWorkstationUnlockLogon:
1243 case KerbSmartCardUnlockLogon:
1244 case KerbProxyLogon:
1245 case KerbTicketLogon:
1246 case KerbTicketUnlockLogon:
1247#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1250#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1251 case KerbCertificateLogon:
1252 case KerbCertificateS4ULogon:
1253 case KerbCertificateUnlockLogon:
1255#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1256 case KerbNoElevationLogon:
1261 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1267static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1276 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1280 const UINT32 type = Stream_Get_UINT32(s);
1281 if (!nla_messageTypeValid(type))
1284 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1286 Stream_Read_UINT32(s, ticket->Flags);
1287 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1288 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1290 if (ticket->MessageType != KerbTicketLogon)
1292 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1296 if (!Stream_CheckAndLogRequiredLength(
1297 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1305 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1306 Stream_Seek(s, ticket->ServiceTicketLength);
1311 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1316static BOOL nla_credentialTypeValid(UINT32 type)
1320 case InvalidCredKey:
1321 case DeprecatedIUMCredKey:
1322 case DomainUserCredKey:
1323 case LocalUserCredKey:
1324 case ExternallySuppliedCredKey:
1327 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1332WINPR_ATTR_MALLOC(free, 1)
1339 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1342 size_t pos = Stream_GetPosition(s);
1345 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1346 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1349 if (!Stream_SetPosition(s, pos))
1357 ret->Version = Stream_Get_UINT32(s);
1358 ret->Flags = Stream_Get_UINT32(s);
1359 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1361 const UINT32 val = Stream_Get_UINT32(s);
1362 if (!nla_credentialTypeValid(val))
1367 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1369 ret->EncryptedCredsSize = EncryptedCredsSize;
1370 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1381} RemoteGuardPackageCredType;
1384static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1385 RemoteGuardPackageCredType* credsType,
1390 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1394 WINPR_ASSERT(credsType);
1395 WINPR_ASSERT(payload);
1397 *credsType = RCG_TYPE_NONE;
1402 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, TRUE) || error)
1405 ConvertMszWCharNToUtf8(WINPR_PACKED_ALIGN_CAST(WCHAR*, packageName.data),
1406 packageName.len /
sizeof(WCHAR), packageNameStr,
1407 sizeof(packageNameStr));
1408 free(packageName.data);
1410 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1413 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1416 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1418 *credsType = RCG_TYPE_KERB;
1420 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1422 *credsType = RCG_TYPE_NTLM;
1426 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1430 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1437 TSCREDS_INVALID = 0,
1438 TSCREDS_USER_PASSWD = 1,
1439 TSCREDS_SMARTCARD = 2,
1440 TSCREDS_REMOTEGUARD = 6
1444static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1450 WinPrAsn1_INTEGER credType = -1;
1456 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1459 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1464 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1468 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1471 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1473 rdpSettings* settings = nla->rdpcontext->settings;
1474 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1475 credType != TSCREDS_REMOTEGUARD)
1477 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1483 case TSCREDS_USER_PASSWD:
1486 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1491 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1495 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1499 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1501 case TSCREDS_SMARTCARD:
1504 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1509 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1511 settings->PasswordIsSmartcardPin = TRUE;
1515 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1517 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1521 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1525 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1527 case TSCREDS_REMOTEGUARD:
1530 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1536 .ServiceTicketLength = 0,
1537 .TicketGrantingTicketLength = 0,
1538 .ServiceTicket =
nullptr,
1539 .TicketGrantingTicket =
nullptr };
1543 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1546 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1547 wStream logonPayload = WINPR_C_ARRAY_INIT;
1548 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1551 if (logonCredsType != RCG_TYPE_KERB)
1553 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1557 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1559 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1567 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1568 Stream_GetRemainingLength(&suppCredsSeq.source))
1571 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1574 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1575 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1576 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1580 if (suppCredsType != RCG_TYPE_NTLM)
1582 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1586 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1589 WLog_ERR(TAG,
"invalid supplementalCreds");
1595 WLog_ERR(TAG,
"invalid supplementalCreds");
1599 freerdp_peer* peer = nla->rdpcontext->peer;
1600 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1605 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1616 WINPR_ASSERT(ticket);
1618 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4ull) + 16ULL + ticket->ServiceTicketLength +
1619 ticket->TicketGrantingTicketLength))
1622 Stream_Write_UINT32(s, KerbTicketLogon);
1623 Stream_Write_UINT32(s, ticket->Flags);
1624 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1625 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1627 Stream_Write_UINT64(s, 0x20);
1628 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1630 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1631 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1636static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1639 WINPR_ASSERT(logonTicket);
1641 SecurityFunctionTable* table =
nullptr;
1643 credssp_auth_tableAndContext(nla->auth, &table, &context);
1644 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1649static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1653 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1654 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1659 logonTicket.ServiceTicket =
nullptr;
1660 logonTicket.TicketGrantingTicket =
nullptr;
1663 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1667 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1670 s = Stream_New(
nullptr, 2000);
1674 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1677 credBuffer.len = Stream_GetPosition(s);
1678 credBuffer.data = Stream_Buffer(s);
1679 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1682 free(logonTicket.ServiceTicket);
1683 free(logonTicket.TicketGrantingTicket);
1684 Stream_Free(s, TRUE);
1689static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1694 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1698 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1702 wStream* s = Stream_New(
nullptr, 300);
1706 Stream_Write_UINT32(s, pntlm->Version);
1707 Stream_Write_UINT32(s, pntlm->Flags);
1709 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1710 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1711 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1712 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1713 Stream_Zero(s, 6 + 16 * 4 + 14);
1717 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1721 Stream_Free(s, TRUE);
1726static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1730 WinPrAsn1_tagId tag;
1731 FreeRDP_Settings_Keys_String setting_id;
1732 } cspData_fields[] = { { 1, FreeRDP_CardName },
1733 { 2, FreeRDP_ReaderName },
1734 { 3, FreeRDP_ContainerName },
1735 { 4, FreeRDP_CspName } };
1740 WINPR_ASSERT(nla->rdpcontext);
1742 const rdpSettings* settings = nla->rdpcontext->settings;
1743 WINPR_ASSERT(settings);
1746 if (!WinPrAsn1EncSeqContainer(enc))
1753 octet_string.len = ss *
sizeof(WCHAR);
1754 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1755 WinPrAsn1FreeOctetString(&octet_string);
1760 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1764 if (!WinPrAsn1EncContextualInteger(
1766 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1770 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1775 settings, cspData_fields[i].setting_id, &len);
1776 octet_string.len = len *
sizeof(WCHAR);
1777 if (octet_string.len)
1780 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1781 WinPrAsn1FreeOctetString(&octet_string);
1788 if (!WinPrAsn1EncEndContainer(enc))
1796 octet_string.len = ss *
sizeof(WCHAR);
1797 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1798 WinPrAsn1FreeOctetString(&octet_string);
1808 octet_string.len = ss *
sizeof(WCHAR);
1809 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1810 WinPrAsn1FreeOctetString(&octet_string);
1816 return WinPrAsn1EncEndContainer(enc) != 0;
1820static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1828 WINPR_ASSERT(nla->rdpcontext);
1830 const rdpSettings* settings = nla->rdpcontext->settings;
1831 WINPR_ASSERT(settings);
1834 if (!WinPrAsn1EncSeqContainer(enc))
1837 const BOOL enabled =
1840 if (enabled && nla->identity)
1842 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1843 username.data = (BYTE*)nla->identity->User;
1845 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1846 domain.data = (BYTE*)nla->identity->Domain;
1848 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1849 password.data = (BYTE*)nla->identity->Password;
1852 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1854 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1856 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1860 return WinPrAsn1EncEndContainer(enc) != 0;
1864static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1870 if (!WinPrAsn1EncSeqContainer(enc))
1874 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1877 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1885 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1888 if (!WinPrAsn1EncSeqContainer(enc))
1891 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1894 if (!WinPrAsn1EncEndContainer(enc))
1897 if (!WinPrAsn1EncEndContainer(enc))
1902 return WinPrAsn1EncEndContainer(enc) != 0;
1912static BOOL nla_encode_ts_credentials(rdpNla* nla)
1915 WinPrAsn1Encoder* enc =
nullptr;
1917 wStream s = WINPR_C_ARRAY_INIT;
1918 TsCredentialsType credType = TSCREDS_INVALID;
1921 WINPR_ASSERT(nla->rdpcontext);
1923 rdpSettings* settings = nla->rdpcontext->settings;
1924 WINPR_ASSERT(settings);
1926 if (settings->RemoteCredentialGuard)
1927 credType = TSCREDS_REMOTEGUARD;
1928 else if (settings->SmartcardLogon)
1929 credType = TSCREDS_SMARTCARD;
1931 credType = TSCREDS_USER_PASSWD;
1933 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1938 if (!WinPrAsn1EncSeqContainer(enc))
1942 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1946 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1951 case TSCREDS_SMARTCARD:
1952 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1956 case TSCREDS_USER_PASSWD:
1957 if (!nla_encode_ts_password_credentials(nla, enc))
1961 case TSCREDS_REMOTEGUARD:
1962 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1970 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1973 if (!WinPrAsn1EncStreamSize(enc, &length))
1976 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1978 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1982 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1984 ret = WinPrAsn1EncToStream(enc, &s);
1987 WinPrAsn1Encoder_Free(&enc);
1992static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1996 if (!nla_encode_ts_credentials(nla))
1999 sspi_SecBufferFree(&nla->authInfo);
2000 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
2001 nla->sendSeqNum++));
2005static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
2009 if (nla->authInfo.cbBuffer < 1)
2011 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
2015 sspi_SecBufferFree(&nla->tsCredentials);
2016 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
2019 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
2026static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
2027 WinPrAsn1_tagId tagId,
const char* msg)
2032 WINPR_ASSERT(buffer);
2035 if (buffer->cbBuffer > 0)
2040 WLog_DBG(TAG,
" ----->> %s", msg);
2041 octet_string.data = buffer->pvBuffer;
2042 octet_string.len = buffer->cbBuffer;
2043 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
2052static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
2053 WinPrAsn1_tagId tagId,
const char* msg)
2055 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
2056 sspi_SecBufferFree(buffer);
2068BOOL nla_send(rdpNla* nla)
2073 WinPrAsn1Encoder* enc =
nullptr;
2077 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
2082 WLog_DBG(TAG,
"----->> sending...");
2083 if (!WinPrAsn1EncSeqContainer(enc))
2087 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
2088 if (!WinPrAsn1EncContextualInteger(enc, 0,
2089 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2093 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2095 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2097 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2101 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2105 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2110 if (nla->authInfo.cbBuffer > 0)
2112 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2117 if (nla->pubKeyAuth.cbBuffer > 0)
2119 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2124 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2126 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2127 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2128 if (!WinPrAsn1EncContextualInteger(
2129 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2134 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2136 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2141 if (!WinPrAsn1EncEndContainer(enc))
2144 if (!WinPrAsn1EncStreamSize(enc, &length))
2147 s = Stream_New(
nullptr, length);
2151 if (!WinPrAsn1EncToStream(enc, s))
2154 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2155 if (transport_write(nla->transport, s) < 0)
2160 Stream_Free(s, TRUE);
2161 WinPrAsn1Encoder_Free(&enc);
2166static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2171 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2172 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2178 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2180 WLog_DBG(TAG,
"<<----- receiving...");
2183 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2189 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2192 if (!Stream_SafeSeek(s, offset))
2195 version = (UINT)val;
2196 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2198 if (nla->peerVersion == 0)
2199 nla->peerVersion = version;
2202 if (nla->peerVersion != version)
2204 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2205 nla->peerVersion, version);
2209 size_t tagcount = 0;
2210 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2219 WLog_DBG(TAG,
" <<----- nego token");
2221 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2222 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2225 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2229 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2234 WLog_DBG(TAG,
" <<----- auth info");
2236 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2238 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2243 WLog_DBG(TAG,
" <<----- public key auth");
2245 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2247 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2253 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2255 nla->errorCode = val;
2256 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2257 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2260 WLog_DBG(TAG,
" <<----- client nonce");
2262 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2264 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2273 return tagcount > 0 ? 1 : -1;
2276int nla_recv_pdu(rdpNla* nla,
wStream* s)
2281 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2283 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
2286 const UINT32 authzResult = Stream_Get_UINT32(s);
2287 if (authzResult != AUTHZ_SUCCESS)
2289 UINT32 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2291 switch (authzResult)
2293 case AUTHZ_ACCESS_DENIED:
2297 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2303 WLog_ERR(TAG,
"Early User Auth active: FAILURE authorization result 0x%08" PRIX32
"",
2305 freerdp_set_last_error_log(nla->rdpcontext, code);
2309 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2313 if (nla_decode_ts_request(nla, s) < 1)
2320 switch (nla->errorCode)
2322 case STATUS_PASSWORD_MUST_CHANGE:
2323 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2326 case STATUS_PASSWORD_EXPIRED:
2327 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2330 case STATUS_ACCOUNT_DISABLED:
2331 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2334 case STATUS_LOGON_FAILURE:
2335 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2338 case STATUS_WRONG_PASSWORD:
2339 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2342 case STATUS_ACCESS_DENIED:
2343 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2346 case STATUS_ACCOUNT_RESTRICTION:
2347 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2350 case STATUS_ACCOUNT_LOCKED_OUT:
2351 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2354 case STATUS_ACCOUNT_EXPIRED:
2355 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2358 case STATUS_LOGON_TYPE_NOT_GRANTED:
2359 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2362 case STATUS_NTLM_BLOCKED:
2365 case SEC_E_UNSUPPORTED_FUNCTION:
2366 code = FREERDP_ERROR_CONNECT_NTLM_BLOCKED;
2370 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2371 NtStatus2Tag(nla->errorCode),
2372 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2373 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2377 freerdp_set_last_error_log(nla->rdpcontext, code);
2382 return nla_client_recv(nla);
2385int nla_server_recv(rdpNla* nla)
2391 wStream* s = nla_server_recv_stream(nla);
2394 status = nla_decode_ts_request(nla, s);
2397 Stream_Free(s, TRUE);
2410rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2412 WINPR_ASSERT(transport);
2413 WINPR_ASSERT(context);
2415 rdpSettings* settings = context->settings;
2416 WINPR_ASSERT(settings);
2418 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2423 nla->rdpcontext = context;
2424 nla->server = settings->ServerMode;
2425 nla->transport = transport;
2426 nla->sendSeqNum = 0;
2427 nla->recvSeqNum = 0;
2429 nla->earlyUserAuth = FALSE;
2431 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2435 nla->auth = credssp_auth_new(context);
2440 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2444 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2449 WINPR_PRAGMA_DIAG_PUSH
2450 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2452 WINPR_PRAGMA_DIAG_POP
2461void nla_free(rdpNla* nla)
2466 smartcardCertInfo_Free(nla->smartcardCert);
2467 nla_buffer_free(nla);
2468 sspi_SecBufferFree(&nla->tsCredentials);
2469 credssp_auth_free(nla->auth);
2471 sspi_FreeAuthIdentity(nla->identity);
2472 free(nla->pkinitArgs);
2473 free(nla->identity);
2477SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2482 return nla->identity;
2485NLA_STATE nla_get_state(
const rdpNla* nla)
2488 return NLA_STATE_FINAL;
2493BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2498 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2503BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2505 return (credssp_auth_set_spn(nla->auth, service, hostname));
2508BOOL nla_impersonate(rdpNla* nla)
2510 return credssp_auth_impersonate(nla->auth);
2513BOOL nla_revert_to_self(rdpNla* nla)
2515 return credssp_auth_revert_to_self(nla->auth);
2518const char* nla_get_state_str(NLA_STATE state)
2522 case NLA_STATE_INITIAL:
2523 return "NLA_STATE_INITIAL";
2524 case NLA_STATE_NEGO_TOKEN:
2525 return "NLA_STATE_NEGO_TOKEN";
2526 case NLA_STATE_PUB_KEY_AUTH:
2527 return "NLA_STATE_PUB_KEY_AUTH";
2528 case NLA_STATE_AUTH_INFO:
2529 return "NLA_STATE_AUTH_INFO";
2530 case NLA_STATE_POST_NEGO:
2531 return "NLA_STATE_POST_NEGO";
2532 case NLA_STATE_EARLY_USER_AUTH:
2533 return "NLA_STATE_EARLY_USER_AUTH";
2534 case NLA_STATE_FINAL:
2535 return "NLA_STATE_FINAL";
2541DWORD nla_get_error(
const rdpNla* nla)
2544 return ERROR_INTERNAL_ERROR;
2545 return (UINT32)nla->errorCode;
2548INT32 nla_get_sspi_error(
const rdpNla* nla)
2551 return credssp_auth_sspi_error(nla->auth);
2557 WINPR_ASSERT(inBuffer);
2558 WINPR_ASSERT(outBuffer);
2559 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2565 WINPR_ASSERT(inBuffer);
2566 WINPR_ASSERT(outBuffer);
2567 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2570SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2574 SecurityFunctionTable* table =
nullptr;
2576 credssp_auth_tableAndContext(nla->auth, &table, &context);
2578 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2581SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2585 SecurityFunctionTable* table =
nullptr;
2587 credssp_auth_tableAndContext(nla->auth, &table, &context);
2589 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.