20#include <winpr/config.h>
23#include <winpr/assert.h>
24#include <winpr/sspi.h>
25#include <winpr/print.h>
26#include <winpr/string.h>
27#include <winpr/tchar.h>
28#include <winpr/sysinfo.h>
29#include <winpr/registry.h>
30#include <winpr/endian.h>
31#include <winpr/build-config.h>
34#include "ntlm_export.h"
37#include "ntlm_message.h"
39#include "../../utils.h"
42#define TAG WINPR_TAG("sspi.NTLM")
44#define WINPR_KEY "Software\\%s\\WinPR\\NTLM"
46static char* NTLM_PACKAGE_NAME =
"NTLM";
48#define check_context(ctx) check_context_((ctx), __FILE__, __func__, __LINE__)
49static BOOL check_context_(
NTLM_CONTEXT* context,
const char* file,
const char* fkt,
size_t line)
52 wLog* log = WLog_Get(TAG);
53 const DWORD log_level = WLOG_ERROR;
57 if (WLog_IsLevelActive(log, log_level))
58 WLog_PrintTextMessage(log, log_level, line, file, fkt,
"invalid context");
63 if (!context->RecvRc4Seal)
65 if (WLog_IsLevelActive(log, log_level))
66 WLog_PrintTextMessage(log, log_level, line, file, fkt,
"invalid context->RecvRc4Seal");
69 if (!context->SendRc4Seal)
71 if (WLog_IsLevelActive(log, log_level))
72 WLog_PrintTextMessage(log, log_level, line, file, fkt,
"invalid context->SendRc4Seal");
76 if (!context->SendSigningKey)
78 if (WLog_IsLevelActive(log, log_level))
79 WLog_PrintTextMessage(log, log_level, line, file, fkt,
80 "invalid context->SendSigningKey");
83 if (!context->RecvSigningKey)
85 if (WLog_IsLevelActive(log, log_level))
86 WLog_PrintTextMessage(log, log_level, line, file, fkt,
87 "invalid context->RecvSigningKey");
90 if (!context->SendSealingKey)
92 if (WLog_IsLevelActive(log, log_level))
93 WLog_PrintTextMessage(log, log_level, line, file, fkt,
94 "invalid context->SendSealingKey");
97 if (!context->RecvSealingKey)
99 if (WLog_IsLevelActive(log, log_level))
100 WLog_PrintTextMessage(log, log_level, line, file, fkt,
101 "invalid context->RecvSealingKey");
107static char* get_name(COMPUTER_NAME_FORMAT type)
111 if (GetComputerNameExA(type,
nullptr, &nSize))
114 if (GetLastError() != ERROR_MORE_DATA)
117 char* computerName = calloc(1, nSize);
122 if (!GetComputerNameExA(type, computerName, &nSize))
131static int ntlm_SetContextWorkstation(
NTLM_CONTEXT* context,
char* Workstation)
133 char* ws = Workstation;
134 CHAR* computerName =
nullptr;
136 WINPR_ASSERT(context);
140 computerName = get_name(ComputerNameNetBIOS);
147 context->Workstation.Buffer = ConvertUtf8ToWCharAlloc(ws, &len);
151 if (!context->Workstation.Buffer || (len > UINT16_MAX /
sizeof(WCHAR)))
154 context->Workstation.Length = (USHORT)(len *
sizeof(WCHAR));
158static int ntlm_SetContextServicePrincipalNameW(
NTLM_CONTEXT* context, LPWSTR ServicePrincipalName)
160 WINPR_ASSERT(context);
162 if (!ServicePrincipalName)
164 context->ServicePrincipalName.Buffer =
nullptr;
165 context->ServicePrincipalName.Length = 0;
169 context->ServicePrincipalName.Length = (USHORT)(_wcslen(ServicePrincipalName) * 2);
170 context->ServicePrincipalName.Buffer = (PWSTR)malloc(context->ServicePrincipalName.Length + 2);
172 if (!context->ServicePrincipalName.Buffer)
175 memcpy(context->ServicePrincipalName.Buffer, ServicePrincipalName,
176 context->ServicePrincipalName.Length + 2);
180static int ntlm_SetContextTargetName(
NTLM_CONTEXT* context,
char* TargetName)
182 char* name = TargetName;
184 CHAR* computerName =
nullptr;
186 WINPR_ASSERT(context);
190 if (GetComputerNameExA(ComputerNameNetBIOS,
nullptr, &nSize) ||
191 GetLastError() != ERROR_MORE_DATA)
194 computerName = calloc(nSize,
sizeof(CHAR));
199 if (!GetComputerNameExA(ComputerNameNetBIOS, computerName, &nSize))
205 if (nSize > MAX_COMPUTERNAME_LENGTH)
206 computerName[MAX_COMPUTERNAME_LENGTH] =
'\0';
217 context->TargetName.pvBuffer = ConvertUtf8ToWCharAlloc(name, &len);
219 if (!context->TargetName.pvBuffer || (len > UINT16_MAX /
sizeof(WCHAR)))
221 free(context->TargetName.pvBuffer);
222 context->TargetName.pvBuffer =
nullptr;
230 context->TargetName.cbBuffer = (USHORT)(len *
sizeof(WCHAR));
249 context->NTLMv2 = TRUE;
250 context->UseMIC = FALSE;
251 context->SendVersionInfo = TRUE;
252 context->SendSingleHostData = FALSE;
253 context->SendWorkstationName = TRUE;
254 context->NegotiateKeyExchange = TRUE;
255 context->UseSamFileDatabase = TRUE;
258 char* key = winpr_getApplicatonDetailsRegKey(WINPR_KEY);
262 RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, 0, KEY_READ | KEY_WOW64_64KEY, &hKey);
265 if (status == ERROR_SUCCESS)
267 if (RegQueryValueEx(hKey, _T(
"NTLMv2"),
nullptr, &dwType, (BYTE*)&dwValue,
268 &dwSize) == ERROR_SUCCESS)
269 context->NTLMv2 = dwValue ? 1 : 0;
271 if (RegQueryValueEx(hKey, _T(
"UseMIC"),
nullptr, &dwType, (BYTE*)&dwValue,
272 &dwSize) == ERROR_SUCCESS)
273 context->UseMIC = dwValue ? 1 : 0;
275 if (RegQueryValueEx(hKey, _T(
"SendVersionInfo"),
nullptr, &dwType, (BYTE*)&dwValue,
276 &dwSize) == ERROR_SUCCESS)
277 context->SendVersionInfo = dwValue ? 1 : 0;
279 if (RegQueryValueEx(hKey, _T(
"SendSingleHostData"),
nullptr, &dwType,
280 (BYTE*)&dwValue, &dwSize) == ERROR_SUCCESS)
281 context->SendSingleHostData = dwValue ? 1 : 0;
283 if (RegQueryValueEx(hKey, _T(
"SendWorkstationName"),
nullptr, &dwType,
284 (BYTE*)&dwValue, &dwSize) == ERROR_SUCCESS)
285 context->SendWorkstationName = dwValue ? 1 : 0;
287 if (RegQueryValueEx(hKey, _T(
"WorkstationName"),
nullptr, &dwType,
nullptr,
288 &dwSize) == ERROR_SUCCESS)
290 char* workstation = (
char*)malloc(dwSize + 1);
298 const LONG rc = RegQueryValueExA(hKey,
"WorkstationName",
nullptr, &dwType,
299 (BYTE*)workstation, &dwSize);
300 if (rc != ERROR_SUCCESS)
301 WLog_WARN(TAG,
"Key ''WorkstationName' not found");
302 workstation[dwSize] =
'\0';
304 if (ntlm_SetContextWorkstation(context, workstation) < 0)
323 context->SuppressExtendedProtection = FALSE;
325 RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(
"System\\CurrentControlSet\\Control\\LSA"), 0,
326 KEY_READ | KEY_WOW64_64KEY, &hKey);
328 if (status == ERROR_SUCCESS)
330 if (RegQueryValueEx(hKey, _T(
"SuppressExtendedProtection"),
nullptr, &dwType,
331 (BYTE*)&dwValue, &dwSize) == ERROR_SUCCESS)
332 context->SuppressExtendedProtection = dwValue ? 1 : 0;
337 context->NegotiateFlags = 0;
338 context->LmCompatibilityLevel = 3;
339 ntlm_change_state(context, NTLM_STATE_INITIAL);
340 FillMemory(context->MachineID,
sizeof(context->MachineID), 0xAA);
343 context->UseMIC = TRUE;
353 winpr_RC4_Free(context->SendRc4Seal);
354 winpr_RC4_Free(context->RecvRc4Seal);
355 sspi_SecBufferFree(&context->NegotiateMessage);
356 sspi_SecBufferFree(&context->ChallengeMessage);
357 sspi_SecBufferFree(&context->AuthenticateMessage);
358 sspi_SecBufferFree(&context->ChallengeTargetInfo);
359 sspi_SecBufferFree(&context->TargetName);
360 sspi_SecBufferFree(&context->NtChallengeResponse);
361 sspi_SecBufferFree(&context->LmChallengeResponse);
362 free(context->ServicePrincipalName.Buffer);
363 free(context->Workstation.Buffer);
366 memset(context->NtlmHash, 0,
sizeof(context->NtlmHash));
367 memset(context->NtlmV2Hash, 0,
sizeof(context->NtlmV2Hash));
368 memset(context->SessionBaseKey, 0,
sizeof(context->SessionBaseKey));
369 memset(context->KeyExchangeKey, 0,
sizeof(context->KeyExchangeKey));
370 memset(context->RandomSessionKey, 0,
sizeof(context->RandomSessionKey));
371 memset(context->ExportedSessionKey, 0,
sizeof(context->ExportedSessionKey));
372 memset(context->EncryptedRandomSessionKey, 0,
sizeof(context->EncryptedRandomSessionKey));
373 memset(context->NtProofString, 0,
sizeof(context->NtProofString));
377static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(
378 WINPR_ATTR_UNUSED SEC_WCHAR* pszPrincipal, WINPR_ATTR_UNUSED SEC_WCHAR* pszPackage,
379 ULONG fCredentialUse, WINPR_ATTR_UNUSED
void* pvLogonID,
void* pAuthData,
380 SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
385 if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && (fCredentialUse != SECPKG_CRED_INBOUND) &&
386 (fCredentialUse != SECPKG_CRED_BOTH))
388 return SEC_E_INVALID_PARAMETER;
394 return SEC_E_INTERNAL_ERROR;
396 credentials->fCredentialUse = fCredentialUse;
397 credentials->pGetKeyFn = pGetKeyFn;
398 credentials->pvGetKeyArgument = pvGetKeyArgument;
402 UINT32 identityFlags = sspi_GetAuthIdentityFlags(pAuthData);
404 if (sspi_CopyAuthIdentity(&(credentials->identity),
407 sspi_CredentialsFree(credentials);
408 return SEC_E_INVALID_PARAMETER;
411 if (identityFlags & SEC_WINNT_AUTH_IDENTITY_EXTENDED)
417 if (settings->samFile)
419 credentials->ntlmSettings.samFile = _strdup(settings->samFile);
420 if (!credentials->ntlmSettings.samFile)
422 sspi_CredentialsFree(credentials);
423 return SEC_E_INSUFFICIENT_MEMORY;
426 credentials->ntlmSettings.hashCallback = settings->hashCallback;
427 credentials->ntlmSettings.hashCallbackArg = settings->hashCallbackArg;
430 sspi_SecureHandleSetLowerPointer(phCredential, (
void*)credentials);
431 sspi_SecureHandleSetUpperPointer(phCredential, (
void*)NTLM_PACKAGE_NAME);
435static SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleA(
436 SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, ULONG fCredentialUse,
void* pvLogonID,
437 void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
void* pvGetKeyArgument,
PCredHandle phCredential,
440 SECURITY_STATUS status = SEC_E_INSUFFICIENT_MEMORY;
441 SEC_WCHAR* principal =
nullptr;
442 SEC_WCHAR*
package = nullptr;
446 principal = ConvertUtf8ToWCharAlloc(pszPrincipal,
nullptr);
452 package = ConvertUtf8ToWCharAlloc(pszPackage, nullptr);
458 ntlm_AcquireCredentialsHandleW(principal, package, fCredentialUse, pvLogonID, pAuthData,
459 pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
468static SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(
PCredHandle phCredential)
471 return SEC_E_INVALID_HANDLE;
475 sspi_SecureHandleInvalidate(phCredential);
477 return SEC_E_INVALID_HANDLE;
479 sspi_CredentialsFree(credentials);
483static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(
484 WINPR_ATTR_UNUSED
PCredHandle phCredential, WINPR_ATTR_UNUSED ULONG ulAttribute,
485 WINPR_ATTR_UNUSED
void* pBuffer)
487 if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
492 WLog_ERR(TAG,
"TODO: Implement");
493 return SEC_E_UNSUPPORTED_FUNCTION;
496static SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(
PCredHandle phCredential,
497 ULONG ulAttribute,
void* pBuffer)
499 return ntlm_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
505static SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(
508 WINPR_ATTR_UNUSED PULONG pfContextAttr, WINPR_ATTR_UNUSED
PTimeStamp ptsTimeStamp)
510 SECURITY_STATUS status = 0;
516 if (phContext && !phContext->dwLower && !phContext->dwUpper)
517 return SEC_E_INVALID_HANDLE;
523 context = ntlm_ContextNew();
526 return SEC_E_INSUFFICIENT_MEMORY;
528 context->server = TRUE;
530 if (fContextReq & ASC_REQ_CONFIDENTIALITY)
531 context->confidentiality = TRUE;
533 credentials = (
SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
534 context->credentials = credentials;
535 context->SamFile = credentials->ntlmSettings.samFile;
536 context->HashCallback = credentials->ntlmSettings.hashCallback;
537 context->HashCallbackArg = credentials->ntlmSettings.hashCallbackArg;
539 ntlm_SetContextTargetName(context,
nullptr);
540 sspi_SecureHandleSetLowerPointer(phNewContext, context);
541 sspi_SecureHandleSetUpperPointer(phNewContext, (
void*)NTLM_PACKAGE_NAME);
544 switch (ntlm_get_state(context))
546 case NTLM_STATE_INITIAL:
548 ntlm_change_state(context, NTLM_STATE_NEGOTIATE);
551 return SEC_E_INVALID_TOKEN;
553 if (pInput->cBuffers < 1)
554 return SEC_E_INVALID_TOKEN;
556 input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
559 return SEC_E_INVALID_TOKEN;
561 if (input_buffer->cbBuffer < 1)
562 return SEC_E_INVALID_TOKEN;
564 status = ntlm_read_NegotiateMessage(context, input_buffer);
565 if (status != SEC_I_CONTINUE_NEEDED)
568 if (ntlm_get_state(context) == NTLM_STATE_CHALLENGE)
571 return SEC_E_INVALID_TOKEN;
573 if (pOutput->cBuffers < 1)
574 return SEC_E_INVALID_TOKEN;
576 output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
578 if (!output_buffer->BufferType)
579 return SEC_E_INVALID_TOKEN;
581 if (output_buffer->cbBuffer < 1)
582 return SEC_E_INSUFFICIENT_MEMORY;
584 return ntlm_write_ChallengeMessage(context, output_buffer);
587 return SEC_E_OUT_OF_SEQUENCE;
590 case NTLM_STATE_AUTHENTICATE:
593 return SEC_E_INVALID_TOKEN;
595 if (pInput->cBuffers < 1)
596 return SEC_E_INVALID_TOKEN;
598 input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
601 return SEC_E_INVALID_TOKEN;
603 if (input_buffer->cbBuffer < 1)
604 return SEC_E_INVALID_TOKEN;
606 status = ntlm_read_AuthenticateMessage(context, input_buffer);
610 for (ULONG i = 0; i < pOutput->cBuffers; i++)
612 pOutput->pBuffers[i].cbBuffer = 0;
613 pOutput->pBuffers[i].BufferType = SECBUFFER_TOKEN;
621 return SEC_E_OUT_OF_SEQUENCE;
625static SECURITY_STATUS SEC_ENTRY
626ntlm_ImpersonateSecurityContext(WINPR_ATTR_UNUSED
PCtxtHandle phContext)
631static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(
633 WINPR_ATTR_UNUSED ULONG Reserved1, WINPR_ATTR_UNUSED ULONG TargetDataRep,
PSecBufferDesc pInput,
635 WINPR_ATTR_UNUSED PULONG pfContextAttr, WINPR_ATTR_UNUSED
PTimeStamp ptsExpiry)
637 SECURITY_STATUS status = 0;
643 if (phContext && !phContext->dwLower && !phContext->dwUpper)
644 return SEC_E_INVALID_HANDLE;
650 input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
655 context = ntlm_ContextNew();
658 return SEC_E_INSUFFICIENT_MEMORY;
660 if (fContextReq & ISC_REQ_CONFIDENTIALITY)
661 context->confidentiality = TRUE;
663 credentials = (
SSPI_CREDENTIALS*)sspi_SecureHandleGetLowerPointer(phCredential);
664 context->credentials = credentials;
666 if (context->Workstation.Length < 1)
668 if (ntlm_SetContextWorkstation(context,
nullptr) < 0)
670 ntlm_ContextFree(context);
671 return SEC_E_INTERNAL_ERROR;
675 if (ntlm_SetContextServicePrincipalNameW(context, pszTargetName) < 0)
677 ntlm_ContextFree(context);
678 return SEC_E_INTERNAL_ERROR;
681 sspi_SecureHandleSetLowerPointer(phNewContext, context);
682 sspi_SecureHandleSetUpperPointer(phNewContext, NTLM_SSP_NAME);
685 if ((!input_buffer) || (ntlm_get_state(context) == NTLM_STATE_AUTHENTICATE))
688 return SEC_E_INVALID_TOKEN;
690 if (pOutput->cBuffers < 1)
691 return SEC_E_INVALID_TOKEN;
693 output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
696 return SEC_E_INVALID_TOKEN;
698 if (output_buffer->cbBuffer < 1)
699 return SEC_E_INVALID_TOKEN;
701 if (ntlm_get_state(context) == NTLM_STATE_INITIAL)
702 ntlm_change_state(context, NTLM_STATE_NEGOTIATE);
704 if (ntlm_get_state(context) == NTLM_STATE_NEGOTIATE)
705 return ntlm_write_NegotiateMessage(context, output_buffer);
707 return SEC_E_OUT_OF_SEQUENCE;
712 return SEC_E_INVALID_TOKEN;
714 if (input_buffer->cbBuffer < 1)
715 return SEC_E_INVALID_TOKEN;
717 PSecBuffer channel_bindings = sspi_FindSecBuffer(pInput, SECBUFFER_CHANNEL_BINDINGS);
719 if (channel_bindings)
721 context->Bindings.BindingsLength = channel_bindings->cbBuffer;
725 if (ntlm_get_state(context) == NTLM_STATE_CHALLENGE)
727 status = ntlm_read_ChallengeMessage(context, input_buffer);
729 if (status != SEC_I_CONTINUE_NEEDED)
733 return SEC_E_INVALID_TOKEN;
735 if (pOutput->cBuffers < 1)
736 return SEC_E_INVALID_TOKEN;
738 output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
741 return SEC_E_INVALID_TOKEN;
743 if (output_buffer->cbBuffer < 1)
744 return SEC_E_INSUFFICIENT_MEMORY;
746 if (ntlm_get_state(context) == NTLM_STATE_AUTHENTICATE)
747 return ntlm_write_AuthenticateMessage(context, output_buffer);
750 return SEC_E_OUT_OF_SEQUENCE;
753 return SEC_E_OUT_OF_SEQUENCE;
759static SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(
761 ULONG Reserved1, ULONG TargetDataRep,
PSecBufferDesc pInput, ULONG Reserved2,
764 SECURITY_STATUS status = 0;
765 SEC_WCHAR* pszTargetNameW =
nullptr;
769 pszTargetNameW = ConvertUtf8ToWCharAlloc(pszTargetName,
nullptr);
771 return SEC_E_INTERNAL_ERROR;
774 status = ntlm_InitializeSecurityContextW(phCredential, phContext, pszTargetNameW, fContextReq,
775 Reserved1, TargetDataRep, pInput, Reserved2,
776 phNewContext, pOutput, pfContextAttr, ptsExpiry);
777 free(pszTargetNameW);
783static SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(
PCtxtHandle phContext)
786 sspi_SecureHandleInvalidate(phContext);
787 ntlm_ContextFree(context);
793 BYTE* blob =
nullptr;
797 WINPR_ASSERT(ntproof);
799 target = &ntlm->ChallengeTargetInfo;
801 if (!sspi_SecBufferAlloc(ntproof, 36 + target->cbBuffer))
802 return SEC_E_INSUFFICIENT_MEMORY;
804 blob = (BYTE*)ntproof->pvBuffer;
805 CopyMemory(blob, ntlm->ServerChallenge, 8);
809 CopyMemory(&blob[16], ntlm->Timestamp, 8);
810 CopyMemory(&blob[24], ntlm->ClientChallenge, 8);
813 CopyMemory(&blob[36], target->pvBuffer, target->cbBuffer);
819 BYTE* blob =
nullptr;
823 WINPR_ASSERT(micvalue);
825 msgSize = ntlm->NegotiateMessage.cbBuffer + ntlm->ChallengeMessage.cbBuffer +
826 ntlm->AuthenticateMessage.cbBuffer;
828 if (!sspi_SecBufferAlloc(micvalue, msgSize))
829 return SEC_E_INSUFFICIENT_MEMORY;
831 blob = (BYTE*)micvalue->pvBuffer;
832 CopyMemory(blob, ntlm->NegotiateMessage.pvBuffer, ntlm->NegotiateMessage.cbBuffer);
833 blob += ntlm->NegotiateMessage.cbBuffer;
834 CopyMemory(blob, ntlm->ChallengeMessage.pvBuffer, ntlm->ChallengeMessage.cbBuffer);
835 blob += ntlm->ChallengeMessage.cbBuffer;
836 CopyMemory(blob, ntlm->AuthenticateMessage.pvBuffer, ntlm->AuthenticateMessage.cbBuffer);
837 blob += ntlm->MessageIntegrityCheckOffset;
838 ZeroMemory(blob, 16);
844static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(
PCtxtHandle phContext,
845 ULONG ulAttribute,
void* pBuffer)
848 return SEC_E_INVALID_HANDLE;
851 return SEC_E_INSUFFICIENT_MEMORY;
854 if (!check_context(context))
855 return SEC_E_INVALID_HANDLE;
857 if (ulAttribute == SECPKG_ATTR_SIZES)
860 ContextSizes->cbMaxToken = 2010;
861 ContextSizes->cbMaxSignature = 16;
862 ContextSizes->cbBlockSize = 0;
863 ContextSizes->cbSecurityTrailer = 16;
867 else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
873 WINPR_ASSERT(AuthIdentity);
874 *AuthIdentity = empty;
876 context->UseSamFileDatabase = FALSE;
877 credentials = context->credentials;
879 if (credentials->identity.UserLength > 0)
881 if (ConvertWCharNToUtf8(credentials->identity.User, credentials->identity.UserLength,
882 AuthIdentity->User, ARRAYSIZE(AuthIdentity->User)) <= 0)
883 return SEC_E_INTERNAL_ERROR;
886 if (credentials->identity.DomainLength > 0)
888 if (ConvertWCharNToUtf8(credentials->identity.Domain,
889 credentials->identity.DomainLength, AuthIdentity->Domain,
890 ARRAYSIZE(AuthIdentity->Domain)) <= 0)
891 return SEC_E_INTERNAL_ERROR;
896 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_NTPROOF_VALUE)
898 return ntlm_computeProofValue(context, (
SecBuffer*)pBuffer);
900 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_RANDKEY)
905 if (!sspi_SecBufferAlloc(randkey, 16))
906 return (SEC_E_INSUFFICIENT_MEMORY);
908 CopyMemory(randkey->pvBuffer, context->EncryptedRandomSessionKey, 16);
911 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC)
916 if (!sspi_SecBufferAlloc(mic, 16))
917 return (SEC_E_INSUFFICIENT_MEMORY);
919 CopyMemory(mic->pvBuffer, message->MessageIntegrityCheck, 16);
922 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MIC_VALUE)
924 return ntlm_computeMicValue(context, (
SecBuffer*)pBuffer);
926 else if (ulAttribute == SECPKG_ATTR_PACKAGE_INFO)
931 (
SecPkgInfoA*)sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size);
934 return SEC_E_INSUFFICIENT_MEMORY;
936 pPackageInfo->fCapabilities = NTLM_SecPkgInfoA.fCapabilities;
937 pPackageInfo->wVersion = NTLM_SecPkgInfoA.wVersion;
938 pPackageInfo->wRPCID = NTLM_SecPkgInfoA.wRPCID;
939 pPackageInfo->cbMaxToken = NTLM_SecPkgInfoA.cbMaxToken;
940 pPackageInfo->Name = _strdup(NTLM_SecPkgInfoA.Name);
941 pPackageInfo->Comment = _strdup(NTLM_SecPkgInfoA.Comment);
943 if (!pPackageInfo->Name || !pPackageInfo->Comment)
945 sspi_ContextBufferFree(pPackageInfo);
946 return SEC_E_INSUFFICIENT_MEMORY;
948 PackageInfo->PackageInfo = pPackageInfo;
952 WLog_ERR(TAG,
"TODO: Implement ulAttribute=0x%08" PRIx32, ulAttribute);
953 return SEC_E_UNSUPPORTED_FUNCTION;
956static SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(
PCtxtHandle phContext,
957 ULONG ulAttribute,
void* pBuffer)
959 return ntlm_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
962static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesW(
PCtxtHandle phContext,
963 ULONG ulAttribute,
void* pBuffer,
967 return SEC_E_INVALID_HANDLE;
970 return SEC_E_INVALID_PARAMETER;
974 return SEC_E_INVALID_HANDLE;
976 if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_HASH)
981 return SEC_E_INVALID_PARAMETER;
983 if (AuthNtlmHash->Version == 1)
984 CopyMemory(context->NtlmHash, AuthNtlmHash->NtlmHash, 16);
985 else if (AuthNtlmHash->Version == 2)
986 CopyMemory(context->NtlmV2Hash, AuthNtlmHash->NtlmHash, 16);
990 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_MESSAGE)
995 return SEC_E_INVALID_PARAMETER;
997 if (AuthNtlmMessage->type == 1)
999 sspi_SecBufferFree(&context->NegotiateMessage);
1001 if (!sspi_SecBufferAlloc(&context->NegotiateMessage, AuthNtlmMessage->length))
1002 return SEC_E_INSUFFICIENT_MEMORY;
1004 CopyMemory(context->NegotiateMessage.pvBuffer, AuthNtlmMessage->buffer,
1005 AuthNtlmMessage->length);
1007 else if (AuthNtlmMessage->type == 2)
1009 sspi_SecBufferFree(&context->ChallengeMessage);
1011 if (!sspi_SecBufferAlloc(&context->ChallengeMessage, AuthNtlmMessage->length))
1012 return SEC_E_INSUFFICIENT_MEMORY;
1014 CopyMemory(context->ChallengeMessage.pvBuffer, AuthNtlmMessage->buffer,
1015 AuthNtlmMessage->length);
1017 else if (AuthNtlmMessage->type == 3)
1019 sspi_SecBufferFree(&context->AuthenticateMessage);
1021 if (!sspi_SecBufferAlloc(&context->AuthenticateMessage, AuthNtlmMessage->length))
1022 return SEC_E_INSUFFICIENT_MEMORY;
1024 CopyMemory(context->AuthenticateMessage.pvBuffer, AuthNtlmMessage->buffer,
1025 AuthNtlmMessage->length);
1030 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_TIMESTAMP)
1036 return SEC_E_INVALID_PARAMETER;
1038 if (AuthNtlmTimestamp->ChallengeOrResponse)
1039 CopyMemory(context->ChallengeTimestamp, AuthNtlmTimestamp->Timestamp, 8);
1041 CopyMemory(context->Timestamp, AuthNtlmTimestamp->Timestamp, 8);
1045 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_CLIENT_CHALLENGE)
1051 return SEC_E_INVALID_PARAMETER;
1053 CopyMemory(context->ClientChallenge, AuthNtlmClientChallenge->ClientChallenge, 8);
1056 else if (ulAttribute == SECPKG_ATTR_AUTH_NTLM_SERVER_CHALLENGE)
1062 return SEC_E_INVALID_PARAMETER;
1064 CopyMemory(context->ServerChallenge, AuthNtlmServerChallenge->ServerChallenge, 8);
1068 WLog_ERR(TAG,
"TODO: Implement ulAttribute=%08" PRIx32, ulAttribute);
1069 return SEC_E_UNSUPPORTED_FUNCTION;
1072static SECURITY_STATUS SEC_ENTRY ntlm_SetContextAttributesA(
PCtxtHandle phContext,
1073 ULONG ulAttribute,
void* pBuffer,
1076 return ntlm_SetContextAttributesW(phContext, ulAttribute, pBuffer, cbBuffer);
1079static SECURITY_STATUS SEC_ENTRY ntlm_SetCredentialsAttributesW(
1080 WINPR_ATTR_UNUSED
PCredHandle phCredential, WINPR_ATTR_UNUSED ULONG ulAttribute,
1081 WINPR_ATTR_UNUSED
void* pBuffer, WINPR_ATTR_UNUSED ULONG cbBuffer)
1083 return SEC_E_UNSUPPORTED_FUNCTION;
1086static SECURITY_STATUS SEC_ENTRY ntlm_SetCredentialsAttributesA(
1087 WINPR_ATTR_UNUSED
PCredHandle phCredential, WINPR_ATTR_UNUSED ULONG ulAttribute,
1088 WINPR_ATTR_UNUSED
void* pBuffer, WINPR_ATTR_UNUSED ULONG cbBuffer)
1090 return SEC_E_UNSUPPORTED_FUNCTION;
1093static SECURITY_STATUS SEC_ENTRY ntlm_RevertSecurityContext(WINPR_ATTR_UNUSED
PCtxtHandle phContext)
1098static SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(
PCtxtHandle phContext,
1099 WINPR_ATTR_UNUSED ULONG fQOP,
1102 const UINT32 SeqNo = MessageSeqNo;
1104 BYTE digest[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1105 BYTE checksum[8] = WINPR_C_ARRAY_INIT;
1110 if (!check_context(context))
1111 return SEC_E_INVALID_HANDLE;
1113 for (ULONG index = 0; index < pMessage->cBuffers; index++)
1115 SecBuffer* cur = &pMessage->pBuffers[index];
1117 if (cur->BufferType & SECBUFFER_DATA)
1119 else if (cur->BufferType & SECBUFFER_TOKEN)
1120 signature_buffer = cur;
1124 return SEC_E_INVALID_TOKEN;
1126 if (!signature_buffer)
1127 return SEC_E_INVALID_TOKEN;
1130 ULONG length = data_buffer->cbBuffer;
1131 void* data = malloc(length);
1134 return SEC_E_INSUFFICIENT_MEMORY;
1136 CopyMemory(data, data_buffer->pvBuffer, length);
1138 WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
1140 BOOL success = FALSE;
1144 if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH))
1147 winpr_Data_Write_UINT32(&value, SeqNo);
1149 if (!winpr_HMAC_Update(hmac, (
void*)&value, 4))
1151 if (!winpr_HMAC_Update(hmac, data, length))
1153 if (!winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH))
1160 winpr_HMAC_Free(hmac);
1164 return SEC_E_INSUFFICIENT_MEMORY;
1168 if ((data_buffer->BufferType & SECBUFFER_READONLY) == 0)
1170 if (context->confidentiality)
1172 if (!winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*)data,
1173 (BYTE*)data_buffer->pvBuffer))
1176 return SEC_E_INSUFFICIENT_MEMORY;
1180 CopyMemory(data_buffer->pvBuffer, data, length);
1183#ifdef WITH_DEBUG_NTLM
1184 WLog_DBG(TAG,
"Data Buffer (length = %" PRIu32
")", length);
1185 winpr_HexDump(TAG, WLOG_DEBUG, data, length);
1186 WLog_DBG(TAG,
"Encrypted Data Buffer (length = %" PRIu32
")", data_buffer->cbBuffer);
1187 winpr_HexDump(TAG, WLOG_DEBUG, data_buffer->pvBuffer, data_buffer->cbBuffer);
1191 if (!winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum))
1192 return SEC_E_INSUFFICIENT_MEMORY;
1193 if ((signature_buffer->BufferType & SECBUFFER_READONLY) == 0)
1195 BYTE* signature = signature_buffer->pvBuffer;
1197 winpr_Data_Write_UINT32(signature, version);
1198 CopyMemory(&signature[4], (
void*)checksum, 8);
1199 winpr_Data_Write_UINT32(&signature[12], SeqNo);
1201 context->SendSeqNum++;
1202#ifdef WITH_DEBUG_NTLM
1203 WLog_DBG(TAG,
"Signature (length = %" PRIu32
")", signature_buffer->cbBuffer);
1204 winpr_HexDump(TAG, WLOG_DEBUG, signature_buffer->pvBuffer, signature_buffer->cbBuffer);
1211 WINPR_ATTR_UNUSED PULONG pfQOP)
1213 const UINT32 SeqNo = (UINT32)MessageSeqNo;
1215 BYTE digest[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1216 BYTE checksum[8] = WINPR_C_ARRAY_INIT;
1218 BYTE expected_signature[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1222 if (!check_context(context))
1223 return SEC_E_INVALID_HANDLE;
1225 for (ULONG index = 0; index < pMessage->cBuffers; index++)
1227 if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
1228 data_buffer = &pMessage->pBuffers[index];
1229 else if (pMessage->pBuffers[index].BufferType == SECBUFFER_TOKEN)
1230 signature_buffer = &pMessage->pBuffers[index];
1234 return SEC_E_INVALID_TOKEN;
1236 if (!signature_buffer)
1237 return SEC_E_INVALID_TOKEN;
1240 const ULONG length = data_buffer->cbBuffer;
1241 void* data = malloc(length);
1244 return SEC_E_INSUFFICIENT_MEMORY;
1246 CopyMemory(data, data_buffer->pvBuffer, length);
1250 if (context->confidentiality)
1252 if (!winpr_RC4_Update(context->RecvRc4Seal, length, (BYTE*)data,
1253 (BYTE*)data_buffer->pvBuffer))
1256 return SEC_E_INSUFFICIENT_MEMORY;
1260 CopyMemory(data_buffer->pvBuffer, data, length);
1263 WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
1265 BOOL success = FALSE;
1270 if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH))
1273 winpr_Data_Write_UINT32(&value, SeqNo);
1275 if (!winpr_HMAC_Update(hmac, (
void*)&value, 4))
1277 if (!winpr_HMAC_Update(hmac, data_buffer->pvBuffer, data_buffer->cbBuffer))
1279 if (!winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH))
1285 winpr_HMAC_Free(hmac);
1289 return SEC_E_INSUFFICIENT_MEMORY;
1292#ifdef WITH_DEBUG_NTLM
1293 WLog_DBG(TAG,
"Encrypted Data Buffer (length = %" PRIu32
")", length);
1294 winpr_HexDump(TAG, WLOG_DEBUG, data, length);
1295 WLog_DBG(TAG,
"Data Buffer (length = %" PRIu32
")", data_buffer->cbBuffer);
1296 winpr_HexDump(TAG, WLOG_DEBUG, data_buffer->pvBuffer, data_buffer->cbBuffer);
1300 if (!winpr_RC4_Update(context->RecvRc4Seal, 8, digest, checksum))
1301 return SEC_E_MESSAGE_ALTERED;
1304 winpr_Data_Write_UINT32(expected_signature, version);
1305 CopyMemory(&expected_signature[4], (
void*)checksum, 8);
1306 winpr_Data_Write_UINT32(&expected_signature[12], SeqNo);
1307 context->RecvSeqNum++;
1309 if (memcmp(signature_buffer->pvBuffer, expected_signature, 16) != 0)
1312 WLog_ERR(TAG,
"signature verification failed, something nasty is going on!");
1313#ifdef WITH_DEBUG_NTLM
1314 WLog_ERR(TAG,
"Expected Signature:");
1315 winpr_HexDump(TAG, WLOG_ERROR, expected_signature, 16);
1316 WLog_ERR(TAG,
"Actual Signature:");
1317 winpr_HexDump(TAG, WLOG_ERROR, (BYTE*)signature_buffer->pvBuffer, 16);
1319 return SEC_E_MESSAGE_ALTERED;
1325static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(
PCtxtHandle phContext,
1326 WINPR_ATTR_UNUSED ULONG fQOP,
1329 SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
1333 BYTE digest[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1334 BYTE checksum[8] = WINPR_C_ARRAY_INIT;
1336 NTLM_CONTEXT* context = sspi_SecureHandleGetLowerPointer(phContext);
1337 if (!check_context(context))
1338 return SEC_E_INVALID_HANDLE;
1340 for (ULONG i = 0; i < pMessage->cBuffers; i++)
1342 if (pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
1343 data_buffer = &pMessage->pBuffers[i];
1344 else if (pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
1345 sig_buffer = &pMessage->pBuffers[i];
1348 if (!data_buffer || !sig_buffer)
1349 return SEC_E_INVALID_TOKEN;
1351 WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
1353 if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH))
1356 winpr_Data_Write_UINT32(&seq_no, MessageSeqNo);
1357 if (!winpr_HMAC_Update(hmac, (BYTE*)&seq_no, 4))
1359 if (!winpr_HMAC_Update(hmac, data_buffer->pvBuffer, data_buffer->cbBuffer))
1361 if (!winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH))
1364 if (!winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum))
1367 BYTE* signature = sig_buffer->pvBuffer;
1368 winpr_Data_Write_UINT32(signature, 1L);
1369 CopyMemory(&signature[4], checksum, 8);
1370 winpr_Data_Write_UINT32(&signature[12], seq_no);
1371 sig_buffer->cbBuffer = 16;
1376 winpr_HMAC_Free(hmac);
1380static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(
PCtxtHandle phContext,
1382 WINPR_ATTR_UNUSED PULONG pfQOP)
1384 SECURITY_STATUS status = SEC_E_INTERNAL_ERROR;
1388 BYTE digest[WINPR_MD5_DIGEST_LENGTH] = WINPR_C_ARRAY_INIT;
1389 BYTE checksum[8] = WINPR_C_ARRAY_INIT;
1390 BYTE signature[16] = WINPR_C_ARRAY_INIT;
1392 NTLM_CONTEXT* context = sspi_SecureHandleGetLowerPointer(phContext);
1393 if (!check_context(context))
1394 return SEC_E_INVALID_HANDLE;
1396 for (ULONG i = 0; i < pMessage->cBuffers; i++)
1398 if (pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
1399 data_buffer = &pMessage->pBuffers[i];
1400 else if (pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
1401 sig_buffer = &pMessage->pBuffers[i];
1404 if (!data_buffer || !sig_buffer)
1405 return SEC_E_INVALID_TOKEN;
1407 WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
1409 if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH))
1412 winpr_Data_Write_UINT32(&seq_no, MessageSeqNo);
1413 if (!winpr_HMAC_Update(hmac, (BYTE*)&seq_no, 4))
1415 if (!winpr_HMAC_Update(hmac, data_buffer->pvBuffer, data_buffer->cbBuffer))
1417 if (!winpr_HMAC_Final(hmac, digest, WINPR_MD5_DIGEST_LENGTH))
1420 if (!winpr_RC4_Update(context->RecvRc4Seal, 8, digest, checksum))
1423 winpr_Data_Write_UINT32(signature, 1L);
1424 CopyMemory(&signature[4], checksum, 8);
1425 winpr_Data_Write_UINT32(&signature[12], seq_no);
1428 if (memcmp(sig_buffer->pvBuffer, signature, 16) != 0)
1429 status = SEC_E_MESSAGE_ALTERED;
1432 winpr_HMAC_Free(hmac);
1439 ntlm_QueryCredentialsAttributesA,
1440 ntlm_AcquireCredentialsHandleA,
1441 ntlm_FreeCredentialsHandle,
1443 ntlm_InitializeSecurityContextA,
1444 ntlm_AcceptSecurityContext,
1446 ntlm_DeleteSecurityContext,
1448 ntlm_QueryContextAttributesA,
1449 ntlm_ImpersonateSecurityContext,
1450 ntlm_RevertSecurityContext,
1452 ntlm_VerifySignature,
1462 ntlm_EncryptMessage,
1463 ntlm_DecryptMessage,
1464 ntlm_SetContextAttributesA,
1465 ntlm_SetCredentialsAttributesA,
1471 ntlm_QueryCredentialsAttributesW,
1472 ntlm_AcquireCredentialsHandleW,
1473 ntlm_FreeCredentialsHandle,
1475 ntlm_InitializeSecurityContextW,
1476 ntlm_AcceptSecurityContext,
1478 ntlm_DeleteSecurityContext,
1480 ntlm_QueryContextAttributesW,
1481 ntlm_ImpersonateSecurityContext,
1482 ntlm_RevertSecurityContext,
1484 ntlm_VerifySignature,
1494 ntlm_EncryptMessage,
1495 ntlm_DecryptMessage,
1496 ntlm_SetContextAttributesW,
1497 ntlm_SetCredentialsAttributesW,
1506 "NTLM Security Package"
1509static WCHAR NTLM_SecPkgInfoW_NameBuffer[32] = WINPR_C_ARRAY_INIT;
1510static WCHAR NTLM_SecPkgInfoW_CommentBuffer[32] = WINPR_C_ARRAY_INIT;
1517 NTLM_SecPkgInfoW_NameBuffer,
1518 NTLM_SecPkgInfoW_CommentBuffer
1521char* ntlm_negotiate_flags_string(
char* buffer,
size_t size, UINT32 flags)
1523 if (!buffer || (size == 0))
1526 (void)_snprintf(buffer, size,
"[0x%08" PRIx32
"] ", flags);
1528 for (
int x = 0; x < 31; x++)
1530 const UINT32 mask = 1u << x;
1531 size_t len = strnlen(buffer, size);
1534 const char* str = ntlm_get_negotiate_string(mask);
1535 const size_t flen = strlen(str);
1537 if ((len > 0) && (buffer[len - 1] !=
' '))
1541 winpr_str_append(
"|", buffer, size,
nullptr);
1545 if (size - len < flen)
1547 winpr_str_append(str, buffer, size,
nullptr);
1554const char* ntlm_message_type_string(UINT32 messageType)
1556 switch (messageType)
1558 case MESSAGE_TYPE_NEGOTIATE:
1559 return "MESSAGE_TYPE_NEGOTIATE";
1560 case MESSAGE_TYPE_CHALLENGE:
1561 return "MESSAGE_TYPE_CHALLENGE";
1562 case MESSAGE_TYPE_AUTHENTICATE:
1563 return "MESSAGE_TYPE_AUTHENTICATE";
1565 return "MESSAGE_TYPE_UNKNOWN";
1569const char* ntlm_state_string(NTLM_STATE state)
1573 case NTLM_STATE_INITIAL:
1574 return "NTLM_STATE_INITIAL";
1575 case NTLM_STATE_NEGOTIATE:
1576 return "NTLM_STATE_NEGOTIATE";
1577 case NTLM_STATE_CHALLENGE:
1578 return "NTLM_STATE_CHALLENGE";
1579 case NTLM_STATE_AUTHENTICATE:
1580 return "NTLM_STATE_AUTHENTICATE";
1581 case NTLM_STATE_FINAL:
1582 return "NTLM_STATE_FINAL";
1584 return "NTLM_STATE_UNKNOWN";
1587void ntlm_change_state(
NTLM_CONTEXT* ntlm, NTLM_STATE state)
1590 WLog_DBG(TAG,
"change state from %s to %s", ntlm_state_string(ntlm->state),
1591 ntlm_state_string(state));
1592 ntlm->state = state;
1601BOOL ntlm_reset_cipher_state(
PSecHandle phContext)
1603 NTLM_CONTEXT* context = sspi_SecureHandleGetLowerPointer(phContext);
1607 check_context(context);
1608 winpr_RC4_Free(context->SendRc4Seal);
1609 winpr_RC4_Free(context->RecvRc4Seal);
1610 context->SendRc4Seal = winpr_RC4_New(context->RecvSealingKey, 16);
1611 context->RecvRc4Seal = winpr_RC4_New(context->SendSealingKey, 16);
1613 if (!context->SendRc4Seal)
1615 WLog_ERR(TAG,
"Failed to allocate context->SendRc4Seal");
1618 if (!context->RecvRc4Seal)
1620 WLog_ERR(TAG,
"Failed to allocate context->RecvRc4Seal");
1630 InitializeConstWCharFromUtf8(NTLM_SecPkgInfoA.Name, NTLM_SecPkgInfoW_NameBuffer,
1631 ARRAYSIZE(NTLM_SecPkgInfoW_NameBuffer));
1632 InitializeConstWCharFromUtf8(NTLM_SecPkgInfoA.Comment, NTLM_SecPkgInfoW_CommentBuffer,
1633 ARRAYSIZE(NTLM_SecPkgInfoW_CommentBuffer));