25#include <freerdp/config.h>
32#include <freerdp/log.h>
33#include <freerdp/build-config.h>
36#include <winpr/assert.h>
38#include <winpr/sspi.h>
39#include <winpr/print.h>
40#include <winpr/tchar.h>
41#include <winpr/ncrypt.h>
42#include <winpr/cred.h>
43#include <winpr/debug.h>
44#include <winpr/asn1.h>
45#include <winpr/secapi.h>
47#include "../crypto/tls.h"
52#include "credssp_auth.h"
53#include <freerdp/utils/smartcardlogon.h>
55#define TAG FREERDP_TAG("core.nla")
57#define NLA_AUTH_PKG NEGO_SSP_NAME
61 AUTHZ_SUCCESS = 0x00000000,
62 AUTHZ_ACCESS_DENIED = 0x00000005,
114 rdpContext* rdpcontext;
115 rdpTransport* transport;
130 SEC_WINNT_AUTH_IDENTITY* identity;
132 rdpCredsspAuth* auth;
139static BOOL nla_send(rdpNla* nla);
140static int nla_server_recv(rdpNla* nla);
141static BOOL nla_encrypt_public_key_echo(rdpNla* nla);
142static BOOL nla_encrypt_public_key_hash(rdpNla* nla);
143static BOOL nla_decrypt_public_key_echo(rdpNla* nla);
144static BOOL nla_decrypt_public_key_hash(rdpNla* nla);
145static BOOL nla_encrypt_ts_credentials(rdpNla* nla);
146static BOOL nla_decrypt_ts_credentials(rdpNla* nla);
148void nla_set_early_user_auth(rdpNla* nla, BOOL earlyUserAuth)
151 WLog_DBG(TAG,
"Early User Auth active: %s", earlyUserAuth ?
"true" :
"false");
152 nla->earlyUserAuth = earlyUserAuth;
155static void nla_buffer_free(rdpNla* nla)
158 sspi_SecBufferFree(&nla->pubKeyAuth);
159 sspi_SecBufferFree(&nla->authInfo);
160 sspi_SecBufferFree(&nla->negoToken);
161 sspi_SecBufferFree(&nla->ClientNonce);
162 sspi_SecBufferFree(&nla->PublicKey);
165static BOOL nla_Digest_Update_From_SecBuffer(WINPR_DIGEST_CTX* ctx,
const SecBuffer* buffer)
169 return winpr_Digest_Update(ctx, buffer->pvBuffer, buffer->cbBuffer);
172static BOOL nla_sec_buffer_alloc(
SecBuffer* buffer,
size_t size)
174 WINPR_ASSERT(buffer);
175 sspi_SecBufferFree(buffer);
176 if (size > UINT32_MAX)
178 if (!sspi_SecBufferAlloc(buffer, (ULONG)size))
181 WINPR_ASSERT(buffer);
182 buffer->BufferType = SECBUFFER_TOKEN;
186static BOOL nla_sec_buffer_alloc_from_data(
SecBuffer* buffer,
const BYTE* data,
size_t offset,
189 if (!nla_sec_buffer_alloc(buffer, offset + size))
192 WINPR_ASSERT(buffer);
193 BYTE* pb = buffer->pvBuffer;
194 memcpy(&pb[offset], data, size);
199static const BYTE ClientServerHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
200 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x54,
201 0x6F, 0x2D, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
202 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
203 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
206static const BYTE ServerClientHashMagic[] = { 0x43, 0x72, 0x65, 0x64, 0x53, 0x53, 0x50, 0x20,
207 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x54,
208 0x6F, 0x2D, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74,
209 0x20, 0x42, 0x69, 0x6E, 0x64, 0x69, 0x6E, 0x67,
210 0x20, 0x48, 0x61, 0x73, 0x68, 0x00 };
212static const UINT32 NonceLength = 32;
214static BOOL nla_adjust_settings_from_smartcard(rdpNla* nla)
219 WINPR_ASSERT(nla->rdpcontext);
221 rdpSettings* settings = nla->rdpcontext->settings;
222 WINPR_ASSERT(settings);
224 if (!settings->SmartcardLogon)
227 smartcardCertInfo_Free(nla->smartcardCert);
229 if (!smartcard_getCert(nla->rdpcontext, &nla->smartcardCert, FALSE))
231 WLog_ERR(TAG,
"unable to get smartcard certificate for logon");
235 if (!settings->CspName)
238 settings, FreeRDP_CspName, nla->smartcardCert->csp))
240 WLog_ERR(TAG,
"unable to set CSP name");
243 if (!settings->CspName &&
246 WLog_ERR(TAG,
"unable to set CSP name");
251 if (!settings->ReaderName && nla->smartcardCert->reader)
254 nla->smartcardCert->reader))
256 WLog_ERR(TAG,
"unable to copy reader name");
261 if (!settings->ContainerName && nla->smartcardCert->containerName)
264 nla->smartcardCert->containerName))
266 WLog_ERR(TAG,
"unable to copy container name");
271 memcpy(nla->certSha1, nla->smartcardCert->sha1Hash,
sizeof(nla->certSha1));
273 if (nla->smartcardCert->pkinitArgs)
275 nla->pkinitArgs = _strdup(nla->smartcardCert->pkinitArgs);
276 if (!nla->pkinitArgs)
278 WLog_ERR(TAG,
"unable to copy pkinitArgs");
288static BOOL nla_client_setup_identity(rdpNla* nla)
290 BOOL PromptPassword = FALSE;
293 WINPR_ASSERT(nla->rdpcontext);
295 rdpSettings* settings = nla->rdpcontext->settings;
296 WINPR_ASSERT(settings);
298 freerdp* instance = nla->rdpcontext->instance;
299 WINPR_ASSERT(instance);
302 if ((utils_str_is_empty(settings->Username) ||
303 (utils_str_is_empty(settings->Password) &&
304 utils_str_is_empty((
const char*)settings->RedirectionPassword))))
306 PromptPassword = TRUE;
309 if (PromptPassword && !utils_str_is_empty(settings->Username))
311 WINPR_SAM* sam = SamOpen(
nullptr, TRUE);
314 const UINT32 userLength = (UINT32)strnlen(settings->Username, INT32_MAX);
315 WINPR_SAM_ENTRY* entry =
316 SamLookupUserA(sam, settings->Username,
317 userLength + 1 ,
nullptr, 0);
324 PromptPassword = FALSE;
325 SamFreeEntry(sam, entry);
334 if (settings->RestrictedAdminModeRequired)
336 if ((settings->PasswordHash) && (strlen(settings->PasswordHash) > 0))
337 PromptPassword = FALSE;
340 if (settings->RemoteCredentialGuard)
341 PromptPassword = FALSE;
344 BOOL smartCardLogonWasDisabled = !settings->SmartcardLogon;
347 switch (utils_authenticate(instance, AUTH_NLA, TRUE))
353 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_CONNECT_CANCELLED);
355 case AUTH_NO_CREDENTIALS:
356 WLog_INFO(TAG,
"No credentials provided - using nullptr identity");
363 if (!settings->Username)
365 sspi_FreeAuthIdentity(nla->identity);
367 nla->identity =
nullptr;
369 else if (settings->SmartcardLogon)
371 if (smartCardLogonWasDisabled)
373 if (!nla_adjust_settings_from_smartcard(nla))
377 if (!identity_set_from_smartcard_hash(nla->identity, settings, FreeRDP_Username,
378 FreeRDP_Domain, FreeRDP_Password, nla->certSha1,
379 sizeof(nla->certSha1)))
384 BOOL usePassword = TRUE;
386 if (settings->RedirectionPassword && (settings->RedirectionPasswordLength > 0))
388 const WCHAR* wstr = (
const WCHAR*)settings->RedirectionPassword;
389 const size_t len = _wcsnlen(wstr, settings->RedirectionPasswordLength /
sizeof(WCHAR));
391 if (!identity_set_from_settings_with_pwd(nla->identity, settings, FreeRDP_Username,
392 FreeRDP_Domain, wstr, len))
398 if (settings->RestrictedAdminModeRequired)
400 if (settings->PasswordHash && strlen(settings->PasswordHash) == 32)
402 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
403 FreeRDP_Domain, FreeRDP_PasswordHash))
411 nla->identity->PasswordLength += LB_PASSWORD_MAX_LENGTH;
418 if (!identity_set_from_settings(nla->identity, settings, FreeRDP_Username,
419 FreeRDP_Domain, FreeRDP_Password))
427static int nla_client_init(rdpNla* nla)
430 WINPR_ASSERT(nla->rdpcontext);
432 rdpSettings* settings = nla->rdpcontext->settings;
433 WINPR_ASSERT(settings);
435 nla_set_state(nla, NLA_STATE_INITIAL);
437 if (!nla_adjust_settings_from_smartcard(nla))
440 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
443 if (!nla_client_setup_identity(nla))
448 if (!credssp_auth_setup_client(nla->auth,
"TERMSRV", hostname, nla->identity, nla->pkinitArgs))
451 const BYTE* data =
nullptr;
453 if (!transport_get_public_key(nla->transport, &data, &length))
455 WLog_ERR(TAG,
"Failed to get public key");
459 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
461 WLog_ERR(TAG,
"Failed to allocate sspi secBuffer");
468int nla_client_begin(rdpNla* nla)
472 if (nla_client_init(nla) < 1)
475 if (nla_get_state(nla) != NLA_STATE_INITIAL)
485 credssp_auth_set_flags(nla->auth, ISC_REQ_MUTUAL_AUTH | ISC_REQ_CONFIDENTIALITY);
487 const int rc = credssp_auth_authenticate(nla->auth);
494 nla_set_state(nla, NLA_STATE_NEGO_TOKEN);
497 if (credssp_auth_have_output_token(nla->auth))
502 nla_set_state(nla, NLA_STATE_FINAL);
505 switch (credssp_auth_sspi_error(nla->auth))
507 case SEC_E_LOGON_DENIED:
508 case SEC_E_NO_CREDENTIALS:
509 freerdp_set_last_error_log(nla->rdpcontext,
510 FREERDP_ERROR_CONNECT_LOGON_FAILURE);
521static int nla_client_recv_nego_token(rdpNla* nla)
523 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
524 const int rc = credssp_auth_authenticate(nla->auth);
535 if (nla->peerVersion < 5)
536 res = nla_encrypt_public_key_echo(nla);
538 res = nla_encrypt_public_key_hash(nla);
546 nla_set_state(nla, NLA_STATE_PUB_KEY_AUTH);
557static int nla_client_recv_pub_key_auth(rdpNla* nla)
564 if (nla->peerVersion < 5)
565 rc = nla_decrypt_public_key_echo(nla);
567 rc = nla_decrypt_public_key_hash(nla);
569 sspi_SecBufferFree(&nla->pubKeyAuth);
575 rc = nla_encrypt_ts_credentials(nla);
582 if (nla->earlyUserAuth)
584 transport_set_early_user_auth_mode(nla->transport, TRUE);
585 nla_set_state(nla, NLA_STATE_EARLY_USER_AUTH);
588 nla_set_state(nla, NLA_STATE_AUTH_INFO);
592static int nla_client_recv_early_user_auth(rdpNla* nla)
596 transport_set_early_user_auth_mode(nla->transport, FALSE);
597 nla_set_state(nla, NLA_STATE_AUTH_INFO);
601static int nla_client_recv(rdpNla* nla)
605 switch (nla_get_state(nla))
607 case NLA_STATE_NEGO_TOKEN:
608 return nla_client_recv_nego_token(nla);
610 case NLA_STATE_PUB_KEY_AUTH:
611 return nla_client_recv_pub_key_auth(nla);
613 case NLA_STATE_EARLY_USER_AUTH:
614 return nla_client_recv_early_user_auth(nla);
616 case NLA_STATE_FINAL:
618 WLog_ERR(TAG,
"NLA in invalid client receive state %s",
619 nla_get_state_str(nla_get_state(nla)));
624static int nla_client_authenticate(rdpNla* nla)
630 wStream* s = Stream_New(
nullptr, 4096);
634 WLog_ERR(TAG,
"Stream_New failed!");
638 if (nla_client_begin(nla) < 1)
641 while (nla_get_state(nla) < NLA_STATE_AUTH_INFO)
643 Stream_SetPosition(s, 0);
644 const int status = transport_read_pdu(nla->transport, s);
648 WLog_ERR(TAG,
"nla_client_authenticate failure");
652 const int status2 = nla_recv_pdu(nla, s);
660 Stream_Free(s, TRUE);
668static int nla_server_init(rdpNla* nla)
672 const BYTE* data =
nullptr;
674 if (!transport_get_public_key(nla->transport, &data, &length))
676 WLog_ERR(TAG,
"Failed to get public key");
680 if (!nla_sec_buffer_alloc_from_data(&nla->PublicKey, data, 0, length))
682 WLog_ERR(TAG,
"Failed to allocate SecBuffer for public key");
686 if (!credssp_auth_init(nla->auth, NLA_AUTH_PKG,
nullptr))
689 if (!credssp_auth_setup_server(nla->auth))
692 nla_set_state(nla, NLA_STATE_INITIAL);
696static wStream* nla_server_recv_stream(rdpNla* nla)
703 s = Stream_New(
nullptr, 4096);
708 status = transport_read_pdu(nla->transport, s);
713 WLog_ERR(TAG,
"nla_recv() error: %d", status);
714 Stream_Free(s, TRUE);
721static BOOL nla_server_recv_credentials(rdpNla* nla)
725 if (nla_server_recv(nla) < 0)
728 if (!nla_decrypt_ts_credentials(nla))
731 if (!nla_impersonate(nla))
734 if (!nla_revert_to_self(nla))
747static int nla_server_authenticate(rdpNla* nla)
753 if (nla_server_init(nla) < 1)
762 credssp_auth_set_flags(nla->auth, ASC_REQ_MUTUAL_AUTH | ASC_REQ_CONFIDENTIALITY |
763 ASC_REQ_CONNECTION | ASC_REQ_USE_SESSION_KEY |
764 ASC_REQ_SEQUENCE_DETECT | ASC_REQ_EXTENDED_ERROR);
796 if (nla_server_recv(nla) < 0)
799 WLog_DBG(TAG,
"Receiving Authentication Token");
800 credssp_auth_take_input_buffer(nla->auth, &nla->negoToken);
802 res = credssp_auth_authenticate(nla->auth);
809 switch (GetLastError())
811 case ERROR_PASSWORD_MUST_CHANGE:
812 nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
815 case ERROR_PASSWORD_EXPIRED:
816 nla->errorCode = STATUS_PASSWORD_EXPIRED;
819 case ERROR_ACCOUNT_DISABLED:
820 nla->errorCode = STATUS_ACCOUNT_DISABLED;
824 nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
836 if (credssp_auth_have_output_token(nla->auth))
841 if (nla_server_recv(nla) < 0)
844 WLog_DBG(TAG,
"Receiving pubkey Token");
847 if (nla->peerVersion < 5)
848 res = nla_decrypt_public_key_echo(nla);
850 res = nla_decrypt_public_key_hash(nla);
856 sspi_SecBufferFree(&nla->negoToken);
858 if (nla->peerVersion < 5)
859 res = nla_encrypt_public_key_echo(nla);
861 res = nla_encrypt_public_key_hash(nla);
868 WLog_DBG(TAG,
"Sending Authentication Token");
881 if (!nla_server_recv_credentials(nla))
885 nla_buffer_free(nla);
896int nla_authenticate(rdpNla* nla)
901 return nla_server_authenticate(nla);
903 return nla_client_authenticate(nla);
906static void ap_integer_increment_le(BYTE* number,
size_t size)
908 WINPR_ASSERT(number || (size == 0));
910 for (
size_t index = 0; index < size; index++)
912 if (number[index] < 0xFF)
925static void ap_integer_decrement_le(BYTE* number,
size_t size)
927 WINPR_ASSERT(number || (size == 0));
929 for (
size_t index = 0; index < size; index++)
931 if (number[index] > 0)
938 number[index] = 0xFF;
944BOOL nla_encrypt_public_key_echo(rdpNla* nla)
950 sspi_SecBufferFree(&nla->pubKeyAuth);
954 if (!sspi_SecBufferAlloc(&buf, nla->PublicKey.cbBuffer))
956 ap_integer_increment_le(buf.pvBuffer, buf.cbBuffer);
958 credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++);
959 sspi_SecBufferFree(&buf);
963 status = credssp_auth_encrypt(nla->auth, &nla->PublicKey, &nla->pubKeyAuth,
nullptr,
970BOOL nla_encrypt_public_key_hash(rdpNla* nla)
973 WINPR_DIGEST_CTX* sha256 =
nullptr;
978 const BYTE* hashMagic = nla->server ? ServerClientHashMagic : ClientServerHashMagic;
979 const size_t hashSize =
980 nla->server ?
sizeof(ServerClientHashMagic) : sizeof(ClientServerHashMagic);
982 if (!sspi_SecBufferAlloc(&buf, WINPR_SHA256_DIGEST_LENGTH))
986 if (!(sha256 = winpr_Digest_New()))
989 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
993 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
996 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1000 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1003 if (!winpr_Digest_Final(sha256, buf.pvBuffer, WINPR_SHA256_DIGEST_LENGTH))
1006 sspi_SecBufferFree(&nla->pubKeyAuth);
1007 if (!credssp_auth_encrypt(nla->auth, &buf, &nla->pubKeyAuth,
nullptr, nla->sendSeqNum++))
1013 winpr_Digest_Free(sha256);
1014 sspi_SecBufferFree(&buf);
1018BOOL nla_decrypt_public_key_echo(rdpNla* nla)
1020 BOOL status = FALSE;
1021 SecBuffer public_key = WINPR_C_ARRAY_INIT;
1026 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &public_key, nla->recvSeqNum++))
1032 ap_integer_decrement_le(public_key.pvBuffer, public_key.cbBuffer);
1035 if (public_key.cbBuffer != nla->PublicKey.cbBuffer ||
1036 memcmp(public_key.pvBuffer, nla->PublicKey.pvBuffer, public_key.cbBuffer) != 0)
1038 WLog_ERR(TAG,
"Could not verify server's public key echo");
1039#if defined(WITH_DEBUG_NLA)
1040 WLog_ERR(TAG,
"Expected (length = %" PRIu32
"):", nla->PublicKey.cbBuffer);
1041 winpr_HexDump(TAG, WLOG_ERROR, nla->PublicKey.pvBuffer, nla->PublicKey.cbBuffer);
1042 WLog_ERR(TAG,
"Actual (length = %" PRIu32
"):", public_key.cbBuffer);
1043 winpr_HexDump(TAG, WLOG_ERROR, public_key.pvBuffer, public_key.cbBuffer);
1051 sspi_SecBufferFree(&public_key);
1055BOOL nla_decrypt_public_key_hash(rdpNla* nla)
1057 WINPR_DIGEST_CTX* sha256 =
nullptr;
1058 BYTE serverClientHash[WINPR_SHA256_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1059 BOOL status = FALSE;
1063 const BYTE* hashMagic = nla->server ? ClientServerHashMagic : ServerClientHashMagic;
1064 const size_t hashSize =
1065 nla->server ?
sizeof(ClientServerHashMagic) : sizeof(ServerClientHashMagic);
1068 if (!credssp_auth_decrypt(nla->auth, &nla->pubKeyAuth, &hash, nla->recvSeqNum++))
1072 if (!(sha256 = winpr_Digest_New()))
1075 if (!winpr_Digest_Init(sha256, WINPR_MD_SHA256))
1079 if (!winpr_Digest_Update(sha256, hashMagic, hashSize))
1082 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->ClientNonce))
1086 if (!nla_Digest_Update_From_SecBuffer(sha256, &nla->PublicKey))
1089 if (!winpr_Digest_Final(sha256, serverClientHash,
sizeof(serverClientHash)))
1093 if (hash.cbBuffer != WINPR_SHA256_DIGEST_LENGTH ||
1094 memcmp(serverClientHash, hash.pvBuffer, WINPR_SHA256_DIGEST_LENGTH) != 0)
1096 WLog_ERR(TAG,
"Could not verify server's hash");
1103 winpr_Digest_Free(sha256);
1104 sspi_SecBufferFree(&hash);
1108static BOOL set_creds_octetstring_to_settings(
WinPrAsn1Decoder* dec, WinPrAsn1_tagId tagId,
1109 BOOL optional, FreeRDP_Settings_Keys_String settingId,
1110 rdpSettings* settings)
1114 WinPrAsn1_tagId itemTag = 0;
1115 if (!WinPrAsn1DecPeekTag(dec, &itemTag) || (itemTag != (ER_TAG_CONTEXTUAL | tagId)))
1124 if (!WinPrAsn1DecReadContextualOctetString(dec, tagId, &error, &value, FALSE))
1128 value.len /
sizeof(WCHAR));
1131static BOOL nla_read_TSCspDataDetail(
WinPrAsn1Decoder* dec, rdpSettings* settings)
1136 WinPrAsn1_INTEGER keyspec = 0;
1137 if (!WinPrAsn1DecReadContextualInteger(dec, 0, &error, &keyspec))
1139 settings->KeySpec = (UINT32)keyspec;
1142 if (!set_creds_octetstring_to_settings(dec, 1, TRUE, FreeRDP_CardName, settings))
1146 if (!set_creds_octetstring_to_settings(dec, 2, TRUE, FreeRDP_ReaderName, settings))
1150 if (!set_creds_octetstring_to_settings(dec, 3, TRUE, FreeRDP_ContainerName, settings))
1154 return set_creds_octetstring_to_settings(dec, 4, TRUE, FreeRDP_CspName, settings);
1157static BOOL nla_messageTypeValid(UINT32 type)
1161 case KerbInvalidValue:
1162 case KerbInteractiveLogon:
1163 case KerbSmartCardLogon:
1164 case KerbWorkstationUnlockLogon:
1165 case KerbSmartCardUnlockLogon:
1166 case KerbProxyLogon:
1167 case KerbTicketLogon:
1168 case KerbTicketUnlockLogon:
1169#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0501)
1172#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0600)
1173 case KerbCertificateLogon:
1174 case KerbCertificateS4ULogon:
1175 case KerbCertificateUnlockLogon:
1177#if !defined(_WIN32_WINNT) || (_WIN32_WINNT >= 0x0602)
1178 case KerbNoElevationLogon:
1183 WLog_ERR(TAG,
"Invalid message type %" PRIu32, type);
1188static BOOL nla_read_KERB_TICKET_LOGON(WINPR_ATTR_UNUSED rdpNla* nla,
wStream* s,
1197 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
1201 const UINT32 type = Stream_Get_UINT32(s);
1202 if (!nla_messageTypeValid(type))
1205 ticket->MessageType = (KERB_LOGON_SUBMIT_TYPE)type;
1207 Stream_Read_UINT32(s, ticket->Flags);
1208 Stream_Read_UINT32(s, ticket->ServiceTicketLength);
1209 Stream_Read_UINT32(s, ticket->TicketGrantingTicketLength);
1211 if (ticket->MessageType != KerbTicketLogon)
1213 WLog_ERR(TAG,
"Not a KerbTicketLogon");
1217 if (!Stream_CheckAndLogRequiredLength(
1218 TAG, s, 16ull + ticket->ServiceTicketLength + ticket->TicketGrantingTicketLength))
1226 ticket->ServiceTicket = Stream_PointerAs(s, UCHAR);
1227 Stream_Seek(s, ticket->ServiceTicketLength);
1232 ticket->TicketGrantingTicket = Stream_PointerAs(s, UCHAR);
1236static BOOL nla_credentialTypeValid(UINT32 type)
1240 case InvalidCredKey:
1241 case DeprecatedIUMCredKey:
1242 case DomainUserCredKey:
1243 case LocalUserCredKey:
1244 case ExternallySuppliedCredKey:
1247 WLog_ERR(TAG,
"Invalid credential type %" PRIu32, type);
1252WINPR_ATTR_MALLOC(free, 1)
1260 if (!Stream_CheckAndLogRequiredLength(TAG, s, 32 + 4))
1263 size_t pos = Stream_GetPosition(s);
1266 ULONG EncryptedCredsSize = Stream_Get_UINT32(s);
1267 if (!Stream_CheckAndLogRequiredLength(TAG, s, EncryptedCredsSize))
1270 Stream_SetPosition(s, pos);
1277 ret->Version = Stream_Get_UINT32(s);
1278 ret->Flags = Stream_Get_UINT32(s);
1279 Stream_Read(s, ret->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1281 const UINT32 val = Stream_Get_UINT32(s);
1282 if (!nla_credentialTypeValid(val))
1287 ret->CredentialKeyType = WINPR_ASSERTING_INT_CAST(MSV1_0_CREDENTIAL_KEY_TYPE, val);
1289 ret->EncryptedCredsSize = EncryptedCredsSize;
1290 Stream_Read(s, ret->EncryptedCreds, EncryptedCredsSize);
1301} RemoteGuardPackageCredType;
1303static BOOL nla_read_TSRemoteGuardPackageCred(WINPR_ATTR_UNUSED rdpNla* nla,
WinPrAsn1Decoder* dec,
1304 RemoteGuardPackageCredType* credsType,
1310 char packageNameStr[100] = WINPR_C_ARRAY_INIT;
1314 WINPR_ASSERT(credsType);
1315 WINPR_ASSERT(payload);
1317 *credsType = RCG_TYPE_NONE;
1320 if (!WinPrAsn1DecReadContextualOctetString(dec, 0, &error, &packageName, FALSE) || error)
1323 ConvertMszWCharNToUtf8((WCHAR*)packageName.data, packageName.len /
sizeof(WCHAR),
1324 packageNameStr,
sizeof(packageNameStr));
1325 WLog_DBG(TAG,
"TSRemoteGuardPackageCred(%s)", packageNameStr);
1328 if (!WinPrAsn1DecReadContextualOctetString(dec, 1, &error, &credBuffer, FALSE) || error)
1331 if (_stricmp(packageNameStr,
"Kerberos") == 0)
1333 *credsType = RCG_TYPE_KERB;
1335 else if (_stricmp(packageNameStr,
"NTLM") == 0)
1337 *credsType = RCG_TYPE_NTLM;
1341 WLog_INFO(TAG,
"TSRemoteGuardPackageCred package %s not handled", packageNameStr);
1345 Stream_StaticInit(payload, credBuffer.data, credBuffer.len);
1352 TSCREDS_INVALID = 0,
1353 TSCREDS_USER_PASSWD = 1,
1354 TSCREDS_SMARTCARD = 2,
1355 TSCREDS_REMOTEGUARD = 6
1358static BOOL nla_read_ts_credentials(rdpNla* nla,
SecBuffer* data)
1364 WinPrAsn1_INTEGER credType = -1;
1370 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, (BYTE*)data->pvBuffer, data->cbBuffer);
1373 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1378 if (!WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &credType))
1382 if (!WinPrAsn1DecReadContextualOctetString(&dec, 1, &error, &credentials, FALSE))
1385 WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, credentials.data, credentials.len);
1387 rdpSettings* settings = nla->rdpcontext->settings;
1388 if (nego_get_remoteCredentialGuard(nla->rdpcontext->rdp->nego) &&
1389 credType != TSCREDS_REMOTEGUARD)
1391 WLog_ERR(TAG,
"connecting with RCG but it's not TSRemoteGuard credentials");
1397 case TSCREDS_USER_PASSWD:
1400 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1405 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Domain, settings))
1409 if (!set_creds_octetstring_to_settings(&dec, 1, FALSE, FreeRDP_Username, settings))
1413 return set_creds_octetstring_to_settings(&dec, 2, FALSE, FreeRDP_Password, settings);
1415 case TSCREDS_SMARTCARD:
1418 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1423 if (!set_creds_octetstring_to_settings(&dec, 0, FALSE, FreeRDP_Password, settings))
1425 settings->PasswordIsSmartcardPin = TRUE;
1429 if (!WinPrAsn1DecReadContextualSequence(&dec, 1, &error, &cspDetails) && error)
1431 if (!nla_read_TSCspDataDetail(&cspDetails, settings))
1435 if (!set_creds_octetstring_to_settings(&dec, 2, TRUE, FreeRDP_Username, settings))
1439 return set_creds_octetstring_to_settings(&dec, 3, TRUE, FreeRDP_Domain, settings);
1441 case TSCREDS_REMOTEGUARD:
1444 if (!WinPrAsn1DecReadSequence(&dec, &dec2))
1450 .ServiceTicketLength = 0,
1451 .TicketGrantingTicketLength = 0,
1452 .ServiceTicket =
nullptr,
1453 .TicketGrantingTicket =
nullptr };
1457 if (!WinPrAsn1DecReadContextualSequence(&dec2, 0, &error, &logonCredsSeq) || error)
1460 RemoteGuardPackageCredType logonCredsType = RCG_TYPE_NONE;
1461 wStream logonPayload = WINPR_C_ARRAY_INIT;
1462 if (!nla_read_TSRemoteGuardPackageCred(nla, &logonCredsSeq, &logonCredsType,
1465 if (logonCredsType != RCG_TYPE_KERB)
1467 WLog_ERR(TAG,
"logonCred must be some Kerberos creds");
1471 if (!nla_read_KERB_TICKET_LOGON(nla, &logonPayload, &kerbLogon))
1473 WLog_ERR(TAG,
"invalid KERB_TICKET_LOGON");
1481 if (WinPrAsn1DecReadContextualSequence(&dec2, 1, &error, &suppCredsSeq) &&
1482 Stream_GetRemainingLength(&suppCredsSeq.source))
1485 if (!WinPrAsn1DecReadSequence(&suppCredsSeq, &ntlmCredsSeq))
1488 RemoteGuardPackageCredType suppCredsType = RCG_TYPE_NONE;
1489 wStream ntlmPayload = WINPR_C_ARRAY_INIT;
1490 if (!nla_read_TSRemoteGuardPackageCred(nla, &ntlmCredsSeq, &suppCredsType,
1494 if (suppCredsType != RCG_TYPE_NTLM)
1496 WLog_ERR(TAG,
"supplementalCreds must be some NTLM creds");
1500 suppCreds = nla_read_NtlmCreds(nla, &ntlmPayload);
1503 WLog_ERR(TAG,
"invalid supplementalCreds");
1509 WLog_ERR(TAG,
"invalid supplementalCreds");
1513 freerdp_peer* peer = nla->rdpcontext->peer;
1514 ret = IFCALLRESULT(TRUE, peer->RemoteCredentials, peer, &kerbLogon, suppCreds);
1519 WLog_DBG(TAG,
"TSCredentials type %d not supported for now", credType);
1529 WINPR_ASSERT(ticket);
1531 if (!Stream_EnsureRemainingCapacity(s, (4ULL * 4) + 16ULL + ticket->ServiceTicketLength +
1532 ticket->TicketGrantingTicketLength))
1535 Stream_Write_UINT32(s, KerbTicketLogon);
1536 Stream_Write_UINT32(s, ticket->Flags);
1537 Stream_Write_UINT32(s, ticket->ServiceTicketLength);
1538 Stream_Write_UINT32(s, ticket->TicketGrantingTicketLength);
1540 Stream_Write_UINT64(s, 0x20);
1541 Stream_Write_UINT64(s, 0x20 + ticket->ServiceTicketLength);
1543 Stream_Write(s, ticket->ServiceTicket, ticket->ServiceTicketLength);
1544 Stream_Write(s, ticket->TicketGrantingTicket, ticket->TicketGrantingTicketLength);
1548static BOOL nla_get_KERB_TICKET_LOGON(rdpNla* nla,
KERB_TICKET_LOGON* logonTicket)
1551 WINPR_ASSERT(logonTicket);
1553 SecurityFunctionTable* table =
nullptr;
1555 credssp_auth_tableAndContext(nla->auth, &table, &context);
1556 return table->QueryContextAttributes(&context, SECPKG_CRED_ATTR_TICKET_LOGON, logonTicket) ==
1560static BOOL nla_write_TSRemoteGuardKerbCred(rdpNla* nla, WinPrAsn1Encoder* enc)
1564 char kerberos[] = {
'K',
'\0',
'e',
'\0',
'r',
'\0',
'b',
'\0',
1565 'e',
'\0',
'r',
'\0',
'o',
'\0',
's',
'\0' };
1570 logonTicket.ServiceTicket =
nullptr;
1571 logonTicket.TicketGrantingTicket =
nullptr;
1574 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1578 if (!nla_get_KERB_TICKET_LOGON(nla, &logonTicket))
1581 s = Stream_New(
nullptr, 2000);
1585 if (!nla_write_KERB_TICKET_LOGON(s, &logonTicket))
1588 credBuffer.len = Stream_GetPosition(s);
1589 credBuffer.data = Stream_Buffer(s);
1590 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1593 free(logonTicket.ServiceTicket);
1594 free(logonTicket.TicketGrantingTicket);
1595 Stream_Free(s, TRUE);
1599static BOOL nla_write_TSRemoteGuardNtlmCred(rdpNla* nla, WinPrAsn1Encoder* enc,
1604 BYTE ntlm[] = {
'N',
'\0',
'T',
'\0',
'L',
'\0',
'M',
'\0' };
1608 if (!WinPrAsn1EncContextualOctetString(enc, 0, &packageName))
1612 wStream* s = Stream_New(
nullptr, 300);
1616 Stream_Write_UINT32(s, pntlm->Version);
1617 Stream_Write_UINT32(s, pntlm->Flags);
1619 Stream_Write(s, pntlm->CredentialKey.Data, MSV1_0_CREDENTIAL_KEY_LENGTH);
1620 Stream_Write_UINT32(s, pntlm->CredentialKeyType);
1621 Stream_Write_UINT32(s, pntlm->EncryptedCredsSize);
1622 Stream_Write(s, pntlm->EncryptedCreds, pntlm->EncryptedCredsSize);
1623 Stream_Zero(s, 6 + 16 * 4 + 14);
1627 ret = WinPrAsn1EncContextualOctetString(enc, 1, &credBuffer) != 0;
1631 Stream_Free(s, TRUE);
1635static BOOL nla_encode_ts_smartcard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1639 WinPrAsn1_tagId tag;
1640 FreeRDP_Settings_Keys_String setting_id;
1641 } cspData_fields[] = { { 1, FreeRDP_CardName },
1642 { 2, FreeRDP_ReaderName },
1643 { 3, FreeRDP_ContainerName },
1644 { 4, FreeRDP_CspName } };
1649 WINPR_ASSERT(nla->rdpcontext);
1651 const rdpSettings* settings = nla->rdpcontext->settings;
1652 WINPR_ASSERT(settings);
1655 if (!WinPrAsn1EncSeqContainer(enc))
1662 octet_string.len = ss *
sizeof(WCHAR);
1663 BOOL res = WinPrAsn1EncContextualOctetString(enc, 0, &octet_string) > 0;
1664 free(octet_string.data);
1669 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1673 if (!WinPrAsn1EncContextualInteger(
1675 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER,
1679 for (
size_t i = 0; i < ARRAYSIZE(cspData_fields); i++)
1684 settings, cspData_fields[i].setting_id, &len);
1685 octet_string.len = len *
sizeof(WCHAR);
1686 if (octet_string.len)
1689 WinPrAsn1EncContextualOctetString(enc, cspData_fields[i].tag, &octet_string) > 0;
1690 free(octet_string.data);
1697 if (!WinPrAsn1EncEndContainer(enc))
1705 octet_string.len = ss *
sizeof(WCHAR);
1706 res = WinPrAsn1EncContextualOctetString(enc, 2, &octet_string) > 0;
1707 free(octet_string.data);
1717 octet_string.len = ss *
sizeof(WCHAR);
1718 res = WinPrAsn1EncContextualOctetString(enc, 3, &octet_string) > 0;
1719 free(octet_string.data);
1725 return WinPrAsn1EncEndContainer(enc) != 0;
1728static BOOL nla_encode_ts_password_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1736 WINPR_ASSERT(nla->rdpcontext);
1738 const rdpSettings* settings = nla->rdpcontext->settings;
1739 WINPR_ASSERT(settings);
1742 if (!WinPrAsn1EncSeqContainer(enc))
1745 if (!settings->DisableCredentialsDelegation && nla->identity)
1747 username.len = nla->identity->UserLength *
sizeof(WCHAR);
1748 username.data = (BYTE*)nla->identity->User;
1750 domain.len = nla->identity->DomainLength *
sizeof(WCHAR);
1751 domain.data = (BYTE*)nla->identity->Domain;
1753 password.len = nla->identity->PasswordLength *
sizeof(WCHAR);
1754 password.data = (BYTE*)nla->identity->Password;
1757 if (WinPrAsn1EncContextualOctetString(enc, 0, &domain) == 0)
1759 if (WinPrAsn1EncContextualOctetString(enc, 1, &username) == 0)
1761 if (WinPrAsn1EncContextualOctetString(enc, 2, &password) == 0)
1765 return WinPrAsn1EncEndContainer(enc) != 0;
1768static BOOL nla_encode_ts_remoteguard_credentials(rdpNla* nla, WinPrAsn1Encoder* enc)
1774 if (!WinPrAsn1EncSeqContainer(enc))
1778 if (!WinPrAsn1EncContextualSeqContainer(enc, 0))
1781 if (!nla_write_TSRemoteGuardKerbCred(nla, enc) || !WinPrAsn1EncEndContainer(enc))
1789 if (!WinPrAsn1EncContextualSeqContainer(enc, 1))
1792 if (!WinPrAsn1EncSeqContainer(enc))
1795 if (!nla_write_TSRemoteGuardNtlmCred(nla, enc, ntlm))
1798 if (!WinPrAsn1EncEndContainer(enc))
1801 if (!WinPrAsn1EncEndContainer(enc))
1806 return WinPrAsn1EncEndContainer(enc) != 0;
1816static BOOL nla_encode_ts_credentials(rdpNla* nla)
1819 WinPrAsn1Encoder* enc =
nullptr;
1821 wStream s = WINPR_C_ARRAY_INIT;
1822 TsCredentialsType credType = TSCREDS_INVALID;
1825 WINPR_ASSERT(nla->rdpcontext);
1827 rdpSettings* settings = nla->rdpcontext->settings;
1828 WINPR_ASSERT(settings);
1830 if (settings->RemoteCredentialGuard)
1831 credType = TSCREDS_REMOTEGUARD;
1832 else if (settings->SmartcardLogon)
1833 credType = TSCREDS_SMARTCARD;
1835 credType = TSCREDS_USER_PASSWD;
1837 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1842 if (!WinPrAsn1EncSeqContainer(enc))
1846 if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)credType))
1850 if (!WinPrAsn1EncContextualOctetStringContainer(enc, 1))
1855 case TSCREDS_SMARTCARD:
1856 if (!nla_encode_ts_smartcard_credentials(nla, enc))
1860 case TSCREDS_USER_PASSWD:
1861 if (!nla_encode_ts_password_credentials(nla, enc))
1865 case TSCREDS_REMOTEGUARD:
1866 if (!nla_encode_ts_remoteguard_credentials(nla, enc))
1874 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
1877 if (!WinPrAsn1EncStreamSize(enc, &length))
1880 if (!nla_sec_buffer_alloc(&nla->tsCredentials, length))
1882 WLog_ERR(TAG,
"sspi_SecBufferAlloc failed!");
1886 Stream_StaticInit(&s, (BYTE*)nla->tsCredentials.pvBuffer, length);
1888 ret = WinPrAsn1EncToStream(enc, &s);
1891 WinPrAsn1Encoder_Free(&enc);
1895static BOOL nla_encrypt_ts_credentials(rdpNla* nla)
1899 if (!nla_encode_ts_credentials(nla))
1902 sspi_SecBufferFree(&nla->authInfo);
1903 return (credssp_auth_encrypt(nla->auth, &nla->tsCredentials, &nla->authInfo,
nullptr,
1904 nla->sendSeqNum++));
1907static BOOL nla_decrypt_ts_credentials(rdpNla* nla)
1911 if (nla->authInfo.cbBuffer < 1)
1913 WLog_ERR(TAG,
"nla_decrypt_ts_credentials missing authInfo buffer");
1917 sspi_SecBufferFree(&nla->tsCredentials);
1918 if (!credssp_auth_decrypt(nla->auth, &nla->authInfo, &nla->tsCredentials, nla->recvSeqNum++))
1921 if (!nla_read_ts_credentials(nla, &nla->tsCredentials))
1927static BOOL nla_write_octet_string(WinPrAsn1Encoder* enc,
const SecBuffer* buffer,
1928 WinPrAsn1_tagId tagId,
const char* msg)
1933 WINPR_ASSERT(buffer);
1936 if (buffer->cbBuffer > 0)
1941 WLog_DBG(TAG,
" ----->> %s", msg);
1942 octet_string.data = buffer->pvBuffer;
1943 octet_string.len = buffer->cbBuffer;
1944 rc = WinPrAsn1EncContextualOctetString(enc, tagId, &octet_string);
1952static BOOL nla_write_octet_string_free(WinPrAsn1Encoder* enc,
SecBuffer* buffer,
1953 WinPrAsn1_tagId tagId,
const char* msg)
1955 const BOOL rc = nla_write_octet_string(enc, buffer, tagId, msg);
1956 sspi_SecBufferFree(buffer);
1968BOOL nla_send(rdpNla* nla)
1973 WinPrAsn1Encoder* enc =
nullptr;
1977 enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
1982 WLog_DBG(TAG,
"----->> sending...");
1983 if (!WinPrAsn1EncSeqContainer(enc))
1987 WLog_DBG(TAG,
" ----->> protocol version %" PRIu32, nla->version);
1988 if (!WinPrAsn1EncContextualInteger(enc, 0,
1989 WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->version)))
1993 if (nla_get_state(nla) <= NLA_STATE_NEGO_TOKEN && credssp_auth_have_output_token(nla->auth))
1995 const SecBuffer* buffer = credssp_auth_get_output_buffer(nla->auth);
1997 if (!WinPrAsn1EncContextualSeqContainer(enc, 1) || !WinPrAsn1EncSeqContainer(enc))
2001 if (!nla_write_octet_string(enc, buffer, 0,
"negoToken"))
2005 if (!WinPrAsn1EncEndContainer(enc) || !WinPrAsn1EncEndContainer(enc))
2010 if (nla->authInfo.cbBuffer > 0)
2012 if (!nla_write_octet_string_free(enc, &nla->authInfo, 2,
"auth info"))
2017 if (nla->pubKeyAuth.cbBuffer > 0)
2019 if (!nla_write_octet_string_free(enc, &nla->pubKeyAuth, 3,
"public key auth"))
2024 if (nla->errorCode && nla->peerVersion >= 3 && nla->peerVersion != 5)
2026 WLog_DBG(TAG,
" ----->> error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2027 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2028 if (!WinPrAsn1EncContextualInteger(
2029 enc, 4, WINPR_ASSERTING_INT_CAST(WinPrAsn1_INTEGER, nla->errorCode)))
2034 if (!nla->server && nla->ClientNonce.cbBuffer > 0)
2036 if (!nla_write_octet_string(enc, &nla->ClientNonce, 5,
"client nonce"))
2041 if (!WinPrAsn1EncEndContainer(enc))
2044 if (!WinPrAsn1EncStreamSize(enc, &length))
2047 s = Stream_New(
nullptr, length);
2051 if (!WinPrAsn1EncToStream(enc, s))
2054 WLog_DBG(TAG,
"[%" PRIuz
" bytes]", length);
2055 if (transport_write(nla->transport, s) < 0)
2060 Stream_Free(s, TRUE);
2061 WinPrAsn1Encoder_Free(&enc);
2065static int nla_decode_ts_request(rdpNla* nla,
wStream* s)
2070 WinPrAsn1_tagId tag = WINPR_C_ARRAY_INIT;
2071 WinPrAsn1_INTEGER val = WINPR_C_ARRAY_INIT;
2077 WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, s);
2079 WLog_DBG(TAG,
"<<----- receiving...");
2082 const size_t offset = WinPrAsn1DecReadSequence(&dec, &dec2);
2088 if (WinPrAsn1DecReadContextualInteger(&dec, 0, &error, &val) == 0)
2091 if (!Stream_SafeSeek(s, offset))
2094 version = (UINT)val;
2095 WLog_DBG(TAG,
" <<----- protocol version %" PRIu32, version);
2097 if (nla->peerVersion == 0)
2098 nla->peerVersion = version;
2101 if (nla->peerVersion != version)
2103 WLog_ERR(TAG,
"CredSSP peer changed protocol version from %" PRIu32
" to %" PRIu32,
2104 nla->peerVersion, version);
2108 while (WinPrAsn1DecReadContextualTag(&dec, &tag, &dec2) != 0)
2116 WLog_DBG(TAG,
" <<----- nego token");
2118 if ((WinPrAsn1DecReadSequence(&dec2, &dec3) == 0) ||
2119 (WinPrAsn1DecReadSequence(&dec3, &dec2) == 0))
2122 if ((WinPrAsn1DecReadContextualOctetString(&dec2, 0, &error, &octet_string,
2126 if (!nla_sec_buffer_alloc_from_data(&nla->negoToken, octet_string.data, 0,
2131 WLog_DBG(TAG,
" <<----- auth info");
2133 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2135 if (!nla_sec_buffer_alloc_from_data(&nla->authInfo, octet_string.data, 0,
2140 WLog_DBG(TAG,
" <<----- public key auth");
2142 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2144 if (!nla_sec_buffer_alloc_from_data(&nla->pubKeyAuth, octet_string.data, 0,
2150 if (WinPrAsn1DecReadInteger(&dec2, &val) == 0)
2152 nla->errorCode = val;
2153 WLog_DBG(TAG,
" <<----- error code %s 0x%08" PRIx32, NtStatus2Tag(nla->errorCode),
2154 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2157 WLog_DBG(TAG,
" <<----- client nonce");
2159 if (WinPrAsn1DecReadOctetString(&dec2, &octet_string, FALSE) == 0)
2161 if (!nla_sec_buffer_alloc_from_data(&nla->ClientNonce, octet_string.data, 0,
2173int nla_recv_pdu(rdpNla* nla,
wStream* s)
2178 if (nla_get_state(nla) == NLA_STATE_EARLY_USER_AUTH)
2181 Stream_Read_UINT32(s, code);
2182 if (code != AUTHZ_SUCCESS)
2184 WLog_DBG(TAG,
"Early User Auth active: FAILURE code 0x%08" PRIX32
"", code);
2185 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2186 freerdp_set_last_error_log(nla->rdpcontext, code);
2190 WLog_DBG(TAG,
"Early User Auth active: SUCCESS");
2194 if (nla_decode_ts_request(nla, s) < 1)
2201 switch (nla->errorCode)
2203 case STATUS_PASSWORD_MUST_CHANGE:
2204 code = FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE;
2207 case STATUS_PASSWORD_EXPIRED:
2208 code = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
2211 case STATUS_ACCOUNT_DISABLED:
2212 code = FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED;
2215 case STATUS_LOGON_FAILURE:
2216 code = FREERDP_ERROR_CONNECT_LOGON_FAILURE;
2219 case STATUS_WRONG_PASSWORD:
2220 code = FREERDP_ERROR_CONNECT_WRONG_PASSWORD;
2223 case STATUS_ACCESS_DENIED:
2224 code = FREERDP_ERROR_CONNECT_ACCESS_DENIED;
2227 case STATUS_ACCOUNT_RESTRICTION:
2228 code = FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION;
2231 case STATUS_ACCOUNT_LOCKED_OUT:
2232 code = FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT;
2235 case STATUS_ACCOUNT_EXPIRED:
2236 code = FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED;
2239 case STATUS_LOGON_TYPE_NOT_GRANTED:
2240 code = FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED;
2244 WLog_ERR(TAG,
"SPNEGO failed with NTSTATUS: %s [0x%08" PRIx32
"]",
2245 NtStatus2Tag(nla->errorCode),
2246 WINPR_CXX_COMPAT_CAST(uint32_t, nla->errorCode));
2247 code = FREERDP_ERROR_AUTHENTICATION_FAILED;
2251 freerdp_set_last_error_log(nla->rdpcontext, code);
2256 return nla_client_recv(nla);
2259int nla_server_recv(rdpNla* nla)
2265 wStream* s = nla_server_recv_stream(nla);
2268 status = nla_decode_ts_request(nla, s);
2271 Stream_Free(s, TRUE);
2284rdpNla* nla_new(rdpContext* context, rdpTransport* transport)
2286 WINPR_ASSERT(transport);
2287 WINPR_ASSERT(context);
2289 rdpSettings* settings = context->settings;
2290 WINPR_ASSERT(settings);
2292 rdpNla* nla = (rdpNla*)calloc(1,
sizeof(rdpNla));
2297 nla->rdpcontext = context;
2298 nla->server = settings->ServerMode;
2299 nla->transport = transport;
2300 nla->sendSeqNum = 0;
2301 nla->recvSeqNum = 0;
2303 nla->earlyUserAuth = FALSE;
2305 nla->identity = calloc(1,
sizeof(SEC_WINNT_AUTH_IDENTITY));
2309 nla->auth = credssp_auth_new(context);
2314 if (!nla_sec_buffer_alloc(&nla->ClientNonce, NonceLength))
2318 if (winpr_RAND(nla->ClientNonce.pvBuffer, NonceLength) < 0)
2323 WINPR_PRAGMA_DIAG_PUSH
2324 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
2326 WINPR_PRAGMA_DIAG_POP
2335void nla_free(rdpNla* nla)
2340 smartcardCertInfo_Free(nla->smartcardCert);
2341 nla_buffer_free(nla);
2342 sspi_SecBufferFree(&nla->tsCredentials);
2343 credssp_auth_free(nla->auth);
2345 sspi_FreeAuthIdentity(nla->identity);
2346 free(nla->pkinitArgs);
2347 free(nla->identity);
2351SEC_WINNT_AUTH_IDENTITY* nla_get_identity(rdpNla* nla)
2356 return nla->identity;
2359NLA_STATE nla_get_state(
const rdpNla* nla)
2362 return NLA_STATE_FINAL;
2367BOOL nla_set_state(rdpNla* nla, NLA_STATE state)
2372 WLog_DBG(TAG,
"-- %s\t--> %s", nla_get_state_str(nla->state), nla_get_state_str(state));
2377BOOL nla_set_service_principal(rdpNla* nla,
const char* service,
const char* hostname)
2379 return (credssp_auth_set_spn(nla->auth, service, hostname));
2382BOOL nla_impersonate(rdpNla* nla)
2384 return credssp_auth_impersonate(nla->auth);
2387BOOL nla_revert_to_self(rdpNla* nla)
2389 return credssp_auth_revert_to_self(nla->auth);
2392const char* nla_get_state_str(NLA_STATE state)
2396 case NLA_STATE_INITIAL:
2397 return "NLA_STATE_INITIAL";
2398 case NLA_STATE_NEGO_TOKEN:
2399 return "NLA_STATE_NEGO_TOKEN";
2400 case NLA_STATE_PUB_KEY_AUTH:
2401 return "NLA_STATE_PUB_KEY_AUTH";
2402 case NLA_STATE_AUTH_INFO:
2403 return "NLA_STATE_AUTH_INFO";
2404 case NLA_STATE_POST_NEGO:
2405 return "NLA_STATE_POST_NEGO";
2406 case NLA_STATE_EARLY_USER_AUTH:
2407 return "NLA_STATE_EARLY_USER_AUTH";
2408 case NLA_STATE_FINAL:
2409 return "NLA_STATE_FINAL";
2415DWORD nla_get_error(
const rdpNla* nla)
2418 return ERROR_INTERNAL_ERROR;
2419 return (UINT32)nla->errorCode;
2422INT32 nla_get_sspi_error(
const rdpNla* nla)
2425 return credssp_auth_sspi_error(nla->auth);
2431 WINPR_ASSERT(inBuffer);
2432 WINPR_ASSERT(outBuffer);
2433 return credssp_auth_encrypt(nla->auth, inBuffer, outBuffer,
nullptr, nla->sendSeqNum++);
2439 WINPR_ASSERT(inBuffer);
2440 WINPR_ASSERT(outBuffer);
2441 return credssp_auth_decrypt(nla->auth, inBuffer, outBuffer, nla->recvSeqNum++);
2444SECURITY_STATUS nla_QueryContextAttributes(rdpNla* nla, DWORD ulAttr, PVOID pBuffer)
2448 SecurityFunctionTable* table =
nullptr;
2450 credssp_auth_tableAndContext(nla->auth, &table, &context);
2452 return table->QueryContextAttributes(&context, ulAttr, pBuffer);
2455SECURITY_STATUS nla_FreeContextBuffer(rdpNla* nla, PVOID pBuffer)
2459 SecurityFunctionTable* table =
nullptr;
2461 credssp_auth_tableAndContext(nla->auth, &table, &context);
2463 return table->FreeContextBuffer(pBuffer);
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.
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 UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD 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.
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.
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings *settings, FreeRDP_Settings_Keys_String id, const char *val)
Sets a string settings value. The param is copied.