25#include <freerdp/config.h>
32#include <freerdp/log.h>
33#include <freerdp/build-config.h>
36#include <winpr/assert.h>
38#include <winpr/sspi.h>
39#include <winpr/print.h>
40#include <winpr/tchar.h>
41#include <winpr/ncrypt.h>
42#include <winpr/cred.h>
43#include <winpr/debug.h>
44#include <winpr/asn1.h>
45#include <winpr/secapi.h>
47#include "../crypto/tls.h"
52#include "credssp_auth.h"
53#include <freerdp/utils/smartcardlogon.h>
55#define TAG FREERDP_TAG("core.nla")
57#define NLA_AUTH_PKG NEGO_SSP_NAME
61 AUTHZ_SUCCESS = 0x00000000,
62 AUTHZ_ACCESS_DENIED = 0x00000005,
114 rdpContext* rdpcontext;
115 rdpTransport* transport;
130 SEC_WINNT_AUTH_IDENTITY* identity;
132 rdpCredsspAuth* auth;
139static BOOL nla_send(rdpNla* nla);
140static int nla_server_recv(rdpNla* nla);
141static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
142static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
143static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
144static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
145static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
146static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
148void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
151 WLog_DBG(TAG,
"Early User Auth active: %s", earlyUserAuth ?
"true" :
"false");
152 nla->earlyUserAuth = earlyUserAuth;
155static void nla_buffer_free(rdpNla* nla)
158 sspi_SecBufferFree(&nla->pubKeyAuth);
159 sspi_SecBufferFree(&nla->authInfo);
160 sspi_SecBufferFree(&nla->negoToken);
161 sspi_SecBufferFree(&nla->ClientNonce);
162 sspi_SecBufferFree(&nla->PublicKey);
165static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx,
const SecBuffer* buffer)
169 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
172static BOOL nla_sec_buffer_alloc(
SecBuffer* buffer,
size_t size)
174 WINPR_ASSERT(buffer);
175 sspi_SecBufferFree(buffer);
176 if (size > UINT32_MAX)
178 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
181 WINPR_ASSERT(buffer);
182 buffer->BufferType = SECBUFFER_TOKEN;
186static BOOL nla_sec_buffer_alloc_from_data(
SecBuffer* buffer,
const BYTE* data,
size_t offset,
189 if (!nla_sec_buffer_alloc(buffer, offset + size))
192 WINPR_ASSERT(buffer);
193 BYTE* pb = buffer->pvBuffer;
194 memcpy(&pb[offset], data, size);
199static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
200 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
201 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
202 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
203 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
206static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
207 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
208 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
209 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
210 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
212static const UINT32 NonceLength = 32;
214static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
219 WINPR_ASSERT(nla->rdpcontext);
221 rdpSettings* settings = nla->rdpcontext->settings;
222 WINPR_ASSERT(settings);
224 if (!settings->SmartcardLogon)
227 smartcardCertInfo_Free(nla->smartcardCert);
229 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
231 WLog_ERR(TAG,
"unable to get smartcard certificate for logon");
235 if (!settings->CspName)
240 MS_SMART_CARD_KEY_STORAGE_PROVIDER))
242 WLog_ERR(TAG,
"unable to set CSP name");
247 if (!settings->ReaderName && nla->smartcardCert->reader)
250 nla->smartcardCert->reader))
252 WLog_ERR(TAG,
"unable to copy reader name");
257 if (!settings->ContainerName && nla->smartcardCert->containerName)
260 nla->smartcardCert->containerName))
262 WLog_ERR(TAG,
"unable to copy container name");
270 WLog_ERR(TAG,
"unable to set KeySpec");
274 WLog_DBG(TAG,
"Smartcard logon: Provider='%s' Reader='%s' Container='%s' KeySpec=%" PRIu32,
280 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
282 if (nla->smartcardCert->pkinitArgs)
284 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
285 if (!nla->pkinitArgs)
287 WLog_ERR(TAG,
"unable to copy pkinitArgs");
297static BOOL nla_client_setup_identity(rdpNla* nla)
299 BOOL PromptPassword = FALSE;
302 WINPR_ASSERT(nla->rdpcontext);
304 rdpSettings* settings = nla->rdpcontext->settings;
305 WINPR_ASSERT(settings);
307 freerdp* instance = nla->rdpcontext->instance;
308 WINPR_ASSERT(instance);
311 if ((utils_str_is_empty(settings->Username) ||
312 (utils_str_is_empty(settings->Password) &&
313 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
315 PromptPassword = TRUE;
318 if (PromptPassword && !utils_str_is_empty(settings->Username))
320 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
323 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
324 WINPR_SAM_ENTRY* entry =
325 SamLookupUserA(sam, settings->Username,
326 userLength + 1 ,
nullptr, 0);
333 PromptPassword = FALSE;
334 SamFreeEntry(sam, entry);
343 if (settings->RestrictedAdminModeRequired)
345 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
346 PromptPassword = FALSE;
349 if (settings->RemoteCredentialGuard)
350 PromptPassword = FALSE;
353 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
356 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
362 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
364 case AUTH_NO_CREDENTIALS:
365 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
372 if (!settings->Username)
374 sspi_FreeAuthIdentity(nla->identity);
376 nla->identity =
nullptr;
378 else if (settings->SmartcardLogon)
380 if (smartCardLogonWasDisabled)
382 if (!nla_adjust_settings_from_smartcard(nla))
386 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
387 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
388 sizeof(nla->certSha1)))
393 BOOL usePassword = TRUE;
395 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
397 const WCHAR* wstr = (
const WCHAR*)settings->RedirectionPassword;
398 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
400 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
401 FreeRDP_Domain, wstr, len))
407 if (settings->RestrictedAdminModeRequired)
409 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
411 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
412 FreeRDP_Domain, FreeRDP_PasswordHash))
415 nla->identity->Flags |= SEC_WINPR_AUTH_IDENTITY_PASSWORD_HASH;
422 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
423 FreeRDP_Domain, FreeRDP_Password))
431static int nla_client_init(rdpNla* nla)
434 WINPR_ASSERT(nla->rdpcontext);
436 rdpSettings* settings = nla->rdpcontext->settings;
437 WINPR_ASSERT(settings);
439 nla_set_state(nla, NLA_STATE_INITIAL);
441 if (!nla_adjust_settings_from_smartcard(nla))
444 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
447 if (!nla_client_setup_identity(nla))
452 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
455 const BYTE* data =
nullptr;
457 if (!transport_get_public_key(nla->transport, &data, &length))
459 WLog_ERR(TAG,
"Failed to get public key");
463 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
465 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
472int nla_client_begin(rdpNla* nla)
476 if (nla_client_init(nla) < 1)
479 if (nla_get_state(nla) != NLA_STATE_INITIAL)
489 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
491 const int rc = credssp_auth_authenticate(nla->auth);
498 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
501 if (credssp_auth_have_output_token(nla->auth))
506 nla_set_state(nla, NLA_STATE_FINAL);
509 switch (credssp_auth_sspi_error(nla->auth))
511 case SEC_E_LOGON_DENIED:
512 case SEC_E_NO_CREDENTIALS:
513 freerdp_set_last_error_log(nla->rdpcontext,
514 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
525static int nla_client_recv_nego_token(rdpNla* nla)
527 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
528 const int rc = credssp_auth_authenticate(nla->auth);
539 if (nla->peerVersion < 5)
540 res = nla_encrypt_public_key_echo(nla);
542 res = nla_encrypt_public_key_hash(nla);
550 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
561static int nla_client_recv_pub_key_auth(rdpNla* nla)
568 if (nla->peerVersion < 5)
569 rc = nla_decrypt_public_key_echo(nla);
571 rc = nla_decrypt_public_key_hash(nla);
573 sspi_SecBufferFree(&nla->pubKeyAuth);
579 rc = nla_encrypt_ts_credentials(nla);
586 if (nla->earlyUserAuth)
588 transport_set_early_user_auth_mode(nla->transport, TRUE);
589 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
592 nla_set_state(nla, NLA_STATE_AUTH_INFO);
596static int nla_client_recv_early_user_auth(rdpNla* nla)
600 transport_set_early_user_auth_mode(nla->transport, FALSE);
601 nla_set_state(nla, NLA_STATE_AUTH_INFO);
605static int nla_client_recv(rdpNla* nla)
609 switch (nla_get_state(nla))
611 case NLA_STATE_NEGO_TOKEN:
612 return nla_client_recv_nego_token(nla);
614 case NLA_STATE_PUB_KEY_AUTH:
615 return nla_client_recv_pub_key_auth(nla);
617 case NLA_STATE_EARLY_USER_AUTH:
618 return nla_client_recv_early_user_auth(nla);
620 case NLA_STATE_FINAL:
622 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
623 nla_get_state_str(nla_get_state(nla)));
628static int nla_client_authenticate(rdpNla* nla)
634 wStream* s = Stream_New(
nullptr, 4096);
638 WLog_ERR(TAG,
"Stream_New failed!");
642 if (nla_client_begin(nla) < 1)
645 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
647 Stream_ResetPosition(s);
648 const int status = transport_read_pdu(nla->transport, s);
652 WLog_ERR(TAG,
"nla_client_authenticate failure");
656 const int status2 = nla_recv_pdu(nla, s);
664 Stream_Free(s, TRUE);
672static int nla_server_init(rdpNla* nla)
676 const BYTE* data =
nullptr;
678 if (!transport_get_public_key(nla->transport, &data, &length))
680 WLog_ERR(TAG,
"Failed to get public key");
684 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
686 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
690 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
693 if (!credssp_auth_setup_server(nla->auth))
696 nla_set_state(nla, NLA_STATE_INITIAL);
700static wStream* nla_server_recv_stream(rdpNla* nla)
707 s = Stream_New(
nullptr, 4096);
712 status = transport_read_pdu(nla->transport, s);
717 WLog_ERR(TAG,
"nla_recv() error: %d", status);
718 Stream_Free(s, TRUE);
725static BOOL nla_server_recv_credentials(rdpNla* nla)
729 if (nla_server_recv(nla) < 0)
732 if (!nla_decrypt_ts_credentials(nla))
735 if (!nla_impersonate(nla))
738 if (!nla_revert_to_self(nla))
751static int nla_server_authenticate(rdpNla* nla)
757 if (nla_server_init(nla) < 1)
766 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
767 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
768 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
800 if (nla_server_recv(nla) < 0)
803 WLog_DBG(TAG,
"Receiving Authentication Token");
804 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
806 res = credssp_auth_authenticate(nla->auth);
813 switch (GetLastError())
815 case ERROR_PASSWORD_MUST_CHANGE:
816 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
819 case ERROR_PASSWORD_EXPIRED:
820 nla->errorCode = STATUS_PASSWORD_EXPIRED;
823 case ERROR_ACCOUNT_DISABLED:
824 nla->errorCode = STATUS_ACCOUNT_DISABLED;
829 nla->errorCode = STATUS_LOGON_FAILURE;
830 const INT32 sspi = credssp_auth_sspi_error(nla->auth);
831 if (sspi != SEC_E_OK)
832 WLog_DBG(TAG,
"[sspi][%s] failed with %s", credssp_auth_pkg_name(nla->auth),
833 GetSecurityStatusString(sspi));
846 if (credssp_auth_have_output_token(nla->auth))
851 if (nla_server_recv(nla) < 0)
854 WLog_DBG(TAG,
"Receiving pubkey Token");
857 if (nla->peerVersion < 5)
858 res = nla_decrypt_public_key_echo(nla);
860 res = nla_decrypt_public_key_hash(nla);
866 sspi_SecBufferFree(&nla->negoToken);
868 if (nla->peerVersion < 5)
869 res = nla_encrypt_public_key_echo(nla);
871 res = nla_encrypt_public_key_hash(nla);
878 WLog_DBG(TAG,
"Sending Authentication Token");
891 if (!nla_server_recv_credentials(nla))
895 nla_buffer_free(nla);
906int nla_authenticate(rdpNla* nla)
911 return nla_server_authenticate(nla);
913 return nla_client_authenticate(nla);
916static void ap_integer_increment_le(BYTE* number,
size_t size)
918 WINPR_ASSERT(number || (size == 0));
920 for (
size_t index = 0; index < size; index++)
922 if (number[index] < 0xFF)
935static void ap_integer_decrement_le(BYTE* number,
size_t size)
937 WINPR_ASSERT(number || (size == 0));
939 for (
size_t index = 0; index < size; index++)
941 if (number[index] > 0)
948 number[index] = 0xFF;
954BOOL nla_encrypt_public_key_echo(rdpNla* nla)
960 sspi_SecBufferFree(&nla->pubKeyAuth);
964 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
966 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
968 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
969 sspi_SecBufferFree(&buf);
973 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
980BOOL nla_encrypt_public_key_hash(rdpNla* nla)
983 WINPR_DIGEST_CTX* sha256 =
nullptr;
988 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
989 const size_t hashSize =
990 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
992 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
996 if (!(sha256 = winpr_Digest_New()))
999 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1003 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1006 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1010 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1013 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1016 sspi_SecBufferFree(&nla->pubKeyAuth);
1017 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1023 winpr_Digest_Free(sha256);
1024 sspi_SecBufferFree(&buf);
1028BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1030 BOOL status = FALSE;
1031 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1036 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1042 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1045 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1046 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1048 WLog_ERR(TAG,
"Could not verify server's public key echo");
1049#if defined(WITH_DEBUG_NLA)
1050 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1051 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1052 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1053 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1061 sspi_SecBufferFree(&public_key);
1065BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1067 WINPR_DIGEST_CTX* sha256 =
nullptr;
1068 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1069 BOOL status = FALSE;
1073 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1074 const size_t hashSize =
1075 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1078 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1082 if (!(sha256 = winpr_Digest_New()))
1085 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1089 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1092 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1096 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1099 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1103 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1104 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1106 WLog_ERR(TAG,
"Could not verify server's hash");
1113 winpr_Digest_Free(sha256);
1114 sspi_SecBufferFree(&hash);
1118static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1119 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1120 rdpSettings* settings)
1124 WinPrAsn1_tagId itemTag = 0;
1125 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1134 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1138 value.len /
sizeof(WCHAR));
1141static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1146 WinPrAsn1_INTEGER keyspec = 0;
1147 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1149 settings->KeySpec = (UINT32)keyspec;
1152 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1156 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1160 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1164 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1167static BOOL nla_messageTypeValid(UINT32 type)
1171 case KerbInvalidValue:
1172 case KerbInteractiveLogon:
1173 case KerbSmartCardLogon:
1174 case KerbWorkstationUnlockLogon:
1175 case KerbSmartCardUnlockLogon:
1176 case KerbProxyLogon:
1177 case KerbTicketLogon:
1178 case KerbTicketUnlockLogon:
1179#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1182#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1183 case KerbCertificateLogon:
1184 case KerbCertificateS4ULogon:
1185 case KerbCertificateUnlockLogon:
1187#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1188 case KerbNoElevationLogon:
1193 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1198static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1207 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1211 const UINT32 type = Stream_Get_UINT32(s);
1212 if (!nla_messageTypeValid(type))
1215 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1217 Stream_Read_UINT32(s, ticket->Flags);
1218 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1219 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1221 if (ticket->MessageType != KerbTicketLogon)
1223 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1227 if (!Stream_CheckAndLogRequiredLength(
1228 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1236 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1237 Stream_Seek(s, ticket->ServiceTicketLength);
1242 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1246static BOOL nla_credentialTypeValid(UINT32 type)
1250 case InvalidCredKey:
1251 case DeprecatedIUMCredKey:
1252 case DomainUserCredKey:
1253 case LocalUserCredKey:
1254 case ExternallySuppliedCredKey:
1257 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1262WINPR_ATTR_MALLOC(free, 1)
1270 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1273 size_t pos = Stream_GetPosition(s);
1276 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1277 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1280 if (!Stream_SetPosition(s, pos))
1288 ret->Version = Stream_Get_UINT32(s);
1289 ret->Flags = Stream_Get_UINT32(s);
1290 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1292 const UINT32 val = Stream_Get_UINT32(s);
1293 if (!nla_credentialTypeValid(val))
1298 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1300 ret->EncryptedCredsSize = EncryptedCredsSize;
1301 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1312} RemoteGuardPackageCredType;
1314static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1315 RemoteGuardPackageCredType* credsType,
1321 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1325 WINPR_ASSERT(credsType);
1326 WINPR_ASSERT(payload);
1328 *credsType = RCG_TYPE_NONE;
1331 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1334 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len /
sizeof(WCHAR),
1335 packageNameStr,
sizeof(packageNameStr));
1336 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1339 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1342 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1344 *credsType = RCG_TYPE_KERB;
1346 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1348 *credsType = RCG_TYPE_NTLM;
1352 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1356 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1363 TSCREDS_INVALID = 0,
1364 TSCREDS_USER_PASSWD = 1,
1365 TSCREDS_SMARTCARD = 2,
1366 TSCREDS_REMOTEGUARD = 6
1369static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1375 WinPrAsn1_INTEGER credType = -1;
1381 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1384 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1389 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1393 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1396 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1398 rdpSettings* settings = nla->rdpcontext->settings;
1399 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1400 credType != TSCREDS_REMOTEGUARD)
1402 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1408 case TSCREDS_USER_PASSWD:
1411 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1416 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1420 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1424 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1426 case TSCREDS_SMARTCARD:
1429 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1434 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1436 settings->PasswordIsSmartcardPin = TRUE;
1440 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1442 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1446 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1450 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1452 case TSCREDS_REMOTEGUARD:
1455 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1461 .ServiceTicketLength = 0,
1462 .TicketGrantingTicketLength = 0,
1463 .ServiceTicket =
nullptr,
1464 .TicketGrantingTicket =
nullptr };
1468 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1471 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1472 wStream logonPayload = WINPR_C_ARRAY_INIT;
1473 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1476 if (logonCredsType != RCG_TYPE_KERB)
1478 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1482 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1484 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1492 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1493 Stream_GetRemainingLength(&suppCredsSeq.source))
1496 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1499 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1500 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1501 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1505 if (suppCredsType != RCG_TYPE_NTLM)
1507 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1511 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1514 WLog_ERR(TAG,
"invalid supplementalCreds");
1520 WLog_ERR(TAG,
"invalid supplementalCreds");
1524 freerdp_peer* peer = nla->rdpcontext->peer;
1525 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1530 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1540 WINPR_ASSERT(ticket);
1542 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1543 ticket->TicketGrantingTicketLength))
1546 Stream_Write_UINT32(s, KerbTicketLogon);
1547 Stream_Write_UINT32(s, ticket->Flags);
1548 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1549 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1551 Stream_Write_UINT64(s, 0x20);
1552 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1554 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1555 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1559static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1562 WINPR_ASSERT(logonTicket);
1564 SecurityFunctionTable* table =
nullptr;
1566 credssp_auth_tableAndContext(nla->auth, &table, &context);
1567 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1571static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1575 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1576 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1581 logonTicket.ServiceTicket =
nullptr;
1582 logonTicket.TicketGrantingTicket =
nullptr;
1585 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1589 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1592 s = Stream_New(
nullptr, 2000);
1596 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1599 credBuffer.len = Stream_GetPosition(s);
1600 credBuffer.data = Stream_Buffer(s);
1601 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1604 free(logonTicket.ServiceTicket);
1605 free(logonTicket.TicketGrantingTicket);
1606 Stream_Free(s, TRUE);
1610static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1615 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1619 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1623 wStream* s = Stream_New(
nullptr, 300);
1627 Stream_Write_UINT32(s, pntlm->Version);
1628 Stream_Write_UINT32(s, pntlm->Flags);
1630 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1631 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1632 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1633 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1634 Stream_Zero(s, 6 + 16 * 4 + 14);
1638 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1642 Stream_Free(s, TRUE);
1646static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1650 WinPrAsn1_tagId tag;
1651 FreeRDP_Settings_Keys_String setting_id;
1652 } cspData_fields[] = { { 1, FreeRDP_CardName },
1653 { 2, FreeRDP_ReaderName },
1654 { 3, FreeRDP_ContainerName },
1655 { 4, FreeRDP_CspName } };
1660 WINPR_ASSERT(nla->rdpcontext);
1662 const rdpSettings* settings = nla->rdpcontext->settings;
1663 WINPR_ASSERT(settings);
1666 if (!WinPrAsn1EncSeqContainer(enc))
1673 octet_string.len = ss *
sizeof(WCHAR);
1674 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1675 WinPrAsn1FreeOctetString(&octet_string);
1680 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1684 if (!WinPrAsn1EncContextualInteger(
1686 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1690 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1695 settings, cspData_fields[i].setting_id, &len);
1696 octet_string.len = len *
sizeof(WCHAR);
1697 if (octet_string.len)
1700 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1701 WinPrAsn1FreeOctetString(&octet_string);
1708 if (!WinPrAsn1EncEndContainer(enc))
1716 octet_string.len = ss *
sizeof(WCHAR);
1717 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1718 WinPrAsn1FreeOctetString(&octet_string);
1728 octet_string.len = ss *
sizeof(WCHAR);
1729 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1730 WinPrAsn1FreeOctetString(&octet_string);
1736 return WinPrAsn1EncEndContainer(enc) != 0;
1739static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1747 WINPR_ASSERT(nla->rdpcontext);
1749 const rdpSettings* settings = nla->rdpcontext->settings;
1750 WINPR_ASSERT(settings);
1753 if (!WinPrAsn1EncSeqContainer(enc))
1756 if (!settings->DisableCredentialsDelegation && nla->identity)
1758 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1759 username.data = (BYTE*)nla->identity->User;
1761 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1762 domain.data = (BYTE*)nla->identity->Domain;
1764 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1765 password.data = (BYTE*)nla->identity->Password;
1768 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1770 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1772 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1776 return WinPrAsn1EncEndContainer(enc) != 0;
1779static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1785 if (!WinPrAsn1EncSeqContainer(enc))
1789 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1792 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1800 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1803 if (!WinPrAsn1EncSeqContainer(enc))
1806 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1809 if (!WinPrAsn1EncEndContainer(enc))
1812 if (!WinPrAsn1EncEndContainer(enc))
1817 return WinPrAsn1EncEndContainer(enc) != 0;
1827static BOOL nla_encode_ts_credentials(rdpNla* nla)
1830 WinPrAsn1Encoder* enc =
nullptr;
1832 wStream s = WINPR_C_ARRAY_INIT;
1833 TsCredentialsType credType = TSCREDS_INVALID;
1836 WINPR_ASSERT(nla->rdpcontext);
1838 rdpSettings* settings = nla->rdpcontext->settings;
1839 WINPR_ASSERT(settings);
1841 if (settings->RemoteCredentialGuard)
1842 credType = TSCREDS_REMOTEGUARD;
1843 else if (settings->SmartcardLogon)
1844 credType = TSCREDS_SMARTCARD;
1846 credType = TSCREDS_USER_PASSWD;
1848 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1853 if (!WinPrAsn1EncSeqContainer(enc))
1857 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1861 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1866 case TSCREDS_SMARTCARD:
1867 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1871 case TSCREDS_USER_PASSWD:
1872 if (!nla_encode_ts_password_credentials(nla, enc))
1876 case TSCREDS_REMOTEGUARD:
1877 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1885 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1888 if (!WinPrAsn1EncStreamSize(enc, &length))
1891 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1893 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1897 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1899 ret = WinPrAsn1EncToStream(enc, &s);
1902 WinPrAsn1Encoder_Free(&enc);
1906static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1910 if (!nla_encode_ts_credentials(nla))
1913 sspi_SecBufferFree(&nla->authInfo);
1914 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
1915 nla->sendSeqNum++));
1918static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1922 if (nla->authInfo.cbBuffer < 1)
1924 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
1928 sspi_SecBufferFree(&nla->tsCredentials);
1929 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1932 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1938static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
1939 WinPrAsn1_tagId tagId,
const char* msg)
1944 WINPR_ASSERT(buffer);
1947 if (buffer->cbBuffer > 0)
1952 WLog_DBG(TAG,
" ----->> %s", msg);
1953 octet_string.data = buffer->pvBuffer;
1954 octet_string.len = buffer->cbBuffer;
1955 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1963static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
1964 WinPrAsn1_tagId tagId,
const char* msg)
1966 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1967 sspi_SecBufferFree(buffer);
1979BOOL nla_send(rdpNla* nla)
1984 WinPrAsn1Encoder* enc =
nullptr;
1988 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1993 WLog_DBG(TAG,
"----->> sending...");
1994 if (!WinPrAsn1EncSeqContainer(enc))
1998 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
1999 if (!WinPrAsn1EncContextualInteger(enc, 0,
2000 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
2004 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
2006 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
2008 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2012 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2016 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2021 if (nla->authInfo.cbBuffer > 0)
2023 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2028 if (nla->pubKeyAuth.cbBuffer > 0)
2030 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2035 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2037 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2038 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2039 if (!WinPrAsn1EncContextualInteger(
2040 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2045 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2047 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2052 if (!WinPrAsn1EncEndContainer(enc))
2055 if (!WinPrAsn1EncStreamSize(enc, &length))
2058 s = Stream_New(
nullptr, length);
2062 if (!WinPrAsn1EncToStream(enc, s))
2065 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2066 if (transport_write(nla->transport, s) < 0)
2071 Stream_Free(s, TRUE);
2072 WinPrAsn1Encoder_Free(&enc);
2076static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2081 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2082 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2088 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2090 WLog_DBG(TAG,
"<<----- receiving...");
2093 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2099 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2102 if (!Stream_SafeSeek(s, offset))
2105 version = (UINT)val;
2106 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2108 if (nla->peerVersion == 0)
2109 nla->peerVersion = version;
2112 if (nla->peerVersion != version)
2114 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2115 nla->peerVersion, version);
2119 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2127 WLog_DBG(TAG,
" <<----- nego token");
2129 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2130 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2133 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2137 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2142 WLog_DBG(TAG,
" <<----- auth info");
2144 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2146 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2151 WLog_DBG(TAG,
" <<----- public key auth");
2153 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2155 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2161 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2163 nla->errorCode = val;
2164 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2165 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2168 WLog_DBG(TAG,
" <<----- client nonce");
2170 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2172 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2184int nla_recv_pdu(rdpNla* nla,
wStream* s)
2189 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2192 Stream_Read_UINT32(s, code);
2193 if (code != AUTHZ_SUCCESS)
2195 WLog_DBG(TAG,
"Early User Auth active: FAILURE code 0x%08" PRIX32
"", code);
2196 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2197 freerdp_set_last_error_log(nla->rdpcontext, code);
2201 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2205 if (nla_decode_ts_request(nla, s) < 1)
2212 switch (nla->errorCode)
2214 case STATUS_PASSWORD_MUST_CHANGE:
2215 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2218 case STATUS_PASSWORD_EXPIRED:
2219 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2222 case STATUS_ACCOUNT_DISABLED:
2223 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2226 case STATUS_LOGON_FAILURE:
2227 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2230 case STATUS_WRONG_PASSWORD:
2231 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2234 case STATUS_ACCESS_DENIED:
2235 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2238 case STATUS_ACCOUNT_RESTRICTION:
2239 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2242 case STATUS_ACCOUNT_LOCKED_OUT:
2243 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2246 case STATUS_ACCOUNT_EXPIRED:
2247 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2250 case STATUS_LOGON_TYPE_NOT_GRANTED:
2251 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2255 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2256 NtStatus2Tag(nla->errorCode),
2257 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2258 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2262 freerdp_set_last_error_log(nla->rdpcontext, code);
2267 return nla_client_recv(nla);
2270int nla_server_recv(rdpNla* nla)
2276 wStream* s = nla_server_recv_stream(nla);
2279 status = nla_decode_ts_request(nla, s);
2282 Stream_Free(s, TRUE);
2295rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2297 WINPR_ASSERT(transport);
2298 WINPR_ASSERT(context);
2300 rdpSettings* settings = context->settings;
2301 WINPR_ASSERT(settings);
2303 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2308 nla->rdpcontext = context;
2309 nla->server = settings->ServerMode;
2310 nla->transport = transport;
2311 nla->sendSeqNum = 0;
2312 nla->recvSeqNum = 0;
2314 nla->earlyUserAuth = FALSE;
2316 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2320 nla->auth = credssp_auth_new(context);
2325 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2329 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2334 WINPR_PRAGMA_DIAG_PUSH
2335 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2337 WINPR_PRAGMA_DIAG_POP
2346void nla_free(rdpNla* nla)
2351 smartcardCertInfo_Free(nla->smartcardCert);
2352 nla_buffer_free(nla);
2353 sspi_SecBufferFree(&nla->tsCredentials);
2354 credssp_auth_free(nla->auth);
2356 sspi_FreeAuthIdentity(nla->identity);
2357 free(nla->pkinitArgs);
2358 free(nla->identity);
2362SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2367 return nla->identity;
2370NLA_STATE nla_get_state(
const rdpNla* nla)
2373 return NLA_STATE_FINAL;
2378BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2383 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2388BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2390 return (credssp_auth_set_spn(nla->auth, service, hostname));
2393BOOL nla_impersonate(rdpNla* nla)
2395 return credssp_auth_impersonate(nla->auth);
2398BOOL nla_revert_to_self(rdpNla* nla)
2400 return credssp_auth_revert_to_self(nla->auth);
2403const char* nla_get_state_str(NLA_STATE state)
2407 case NLA_STATE_INITIAL:
2408 return "NLA_STATE_INITIAL";
2409 case NLA_STATE_NEGO_TOKEN:
2410 return "NLA_STATE_NEGO_TOKEN";
2411 case NLA_STATE_PUB_KEY_AUTH:
2412 return "NLA_STATE_PUB_KEY_AUTH";
2413 case NLA_STATE_AUTH_INFO:
2414 return "NLA_STATE_AUTH_INFO";
2415 case NLA_STATE_POST_NEGO:
2416 return "NLA_STATE_POST_NEGO";
2417 case NLA_STATE_EARLY_USER_AUTH:
2418 return "NLA_STATE_EARLY_USER_AUTH";
2419 case NLA_STATE_FINAL:
2420 return "NLA_STATE_FINAL";
2426DWORD nla_get_error(
const rdpNla* nla)
2429 return ERROR_INTERNAL_ERROR;
2430 return (UINT32)nla->errorCode;
2433INT32 nla_get_sspi_error(
const rdpNla* nla)
2436 return credssp_auth_sspi_error(nla->auth);
2442 WINPR_ASSERT(inBuffer);
2443 WINPR_ASSERT(outBuffer);
2444 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2450 WINPR_ASSERT(inBuffer);
2451 WINPR_ASSERT(outBuffer);
2452 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2455SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2459 SecurityFunctionTable* table =
nullptr;
2461 credssp_auth_tableAndContext(nla->auth, &table, &context);
2463 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2466SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2470 SecurityFunctionTable* table =
nullptr;
2472 credssp_auth_tableAndContext(nla->auth, &table, &context);
2474 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.