https://git.reactos.org/?p=reactos.git;a=commitdiff;h=99dcd6f71cb72a973e8588...
commit 99dcd6f71cb72a973e85888903b5ed31241ad5c3 Author: Andreas Maier staubim@quantentunnel.de AuthorDate: Thu Jul 16 20:44:01 2020 +0200 Commit: Victor Perevertkin victor@perevertkin.ru CommitDate: Sat Dec 25 15:55:43 2021 +0300
[MSV1_0] Implement LsaApLogonUserEx2_Network (5/5)
This is a part of the Partial Network Login Implementation PR. --- dll/win32/msv1_0/CMakeLists.txt | 1 + dll/win32/msv1_0/lsa.c | 1 - dll/win32/msv1_0/lsa.h | 3 - dll/win32/msv1_0/msv1_0.c | 209 +++++++++++++++++----- dll/win32/msv1_0/msv1_0.h | 58 +++++++ dll/win32/msv1_0/ntlm/global.c | 41 +++++ dll/win32/msv1_0/ntlm/global.h | 22 ++- dll/win32/msv1_0/ntlm/protocol.h | 24 +++ dll/win32/msv1_0/ntlm/util.c | 367 +++++++++++++++++++++++++++++++++++++++ dll/win32/msv1_0/ntlm/util.h | 64 +++++++ dll/win32/msv1_0/precomp.h | 2 + dll/win32/msv1_0/sam.c | 2 + dll/win32/msv1_0/sam.h | 12 ++ 13 files changed, 758 insertions(+), 48 deletions(-)
diff --git a/dll/win32/msv1_0/CMakeLists.txt b/dll/win32/msv1_0/CMakeLists.txt index 50fa39aa44b..a336c7a6a4e 100644 --- a/dll/win32/msv1_0/CMakeLists.txt +++ b/dll/win32/msv1_0/CMakeLists.txt @@ -5,6 +5,7 @@ list(APPEND SOURCE lsa.c msv1_0.c ntlm/global.c + ntlm/util.c sam.c user.c usercontext.c diff --git a/dll/win32/msv1_0/lsa.c b/dll/win32/msv1_0/lsa.c index 0bbf4699c66..e8e4da8854e 100644 --- a/dll/win32/msv1_0/lsa.c +++ b/dll/win32/msv1_0/lsa.c @@ -10,7 +10,6 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
-SECPKG_FUNCTION_TABLE NtlmLsaFn[1];
NTSTATUS NTAPI diff --git a/dll/win32/msv1_0/lsa.h b/dll/win32/msv1_0/lsa.h index 2df98a710c6..3577dbce361 100644 --- a/dll/win32/msv1_0/lsa.h +++ b/dll/win32/msv1_0/lsa.h @@ -7,9 +7,6 @@
#pragma once
-// functions we provide to LSA in SpLsaModeInitialize -extern SECPKG_FUNCTION_TABLE NtlmLsaFn[1]; - NTSTATUS NTAPI SpInitialize( diff --git a/dll/win32/msv1_0/msv1_0.c b/dll/win32/msv1_0/msv1_0.c index eefddf3d0e0..63aad086fd9 100644 --- a/dll/win32/msv1_0/msv1_0.c +++ b/dll/win32/msv1_0/msv1_0.c @@ -13,11 +13,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msv1_0);
-/* GLOBALS *****************************************************************/ - -LSA_DISPATCH_TABLE DispatchTable; - - /* FUNCTIONS ***************************************************************/
static @@ -176,6 +171,110 @@ done: }
+static +NTSTATUS +BuildLm20LogonProfileBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ PSAMPR_USER_INFO_BUFFER UserInfo, + _In_ PLSA_SAM_PWD_DATA LogonPwdData, + _Out_ PMSV1_0_LM20_LOGON_PROFILE *ProfileBuffer, + _Out_ PULONG ProfileBufferLength) +{ + PMSV1_0_LM20_LOGON_PROFILE LocalBuffer; + NTLM_CLIENT_BUFFER Buffer; + PBYTE PtrOffset; + ULONG BufferLength; + NTSTATUS Status = STATUS_SUCCESS; + UNICODE_STRING ComputerNameUCS; + + *ProfileBuffer = NULL; + *ProfileBufferLength = 0; + + if (!NtlmUStrAlloc(&ComputerNameUCS, LogonPwdData->ComputerName->Length + sizeof(WCHAR) * 3, 0)) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto done; + } + Status = RtlAppendUnicodeToString(&ComputerNameUCS, L"\\"); + if (!NT_SUCCESS(Status)) + { + ERR("RtlAppendUnicodeToString failed 0x%lx\n", Status); + goto done; + } + Status = RtlAppendUnicodeStringToString(&ComputerNameUCS, LogonPwdData->ComputerName); + if (!NT_SUCCESS(Status)) + { + ERR("RtlAppendUnicodeStringToString failed 0x%lx\n", Status); + goto done; + } + + BufferLength = sizeof(MSV1_0_LM20_LOGON_PROFILE) + ComputerNameUCS.Length + sizeof(WCHAR); + + Status = NtlmAllocateClientBuffer(ClientRequest, BufferLength, &Buffer); + if (!NT_SUCCESS(Status)) + { + TRACE("DispatchTable.AllocateClientBuffer failed (Status 0x%08lx)\n", Status); + goto done; + } + + TRACE("ClientBaseAddress: %p\n", Buffer.ClientBaseAddress); + + LocalBuffer = (PMSV1_0_LM20_LOGON_PROFILE)Buffer.LocalBuffer; + PtrOffset = (PBYTE)(LocalBuffer + 1); + + LocalBuffer->MessageType = MsV1_0Lm20LogonProfile; + LocalBuffer->KickOffTime.LowPart = UserInfo->All.AccountExpires.LowPart; + LocalBuffer->KickOffTime.HighPart = UserInfo->All.AccountExpires.HighPart; + LocalBuffer->LogoffTime.LowPart = UserInfo->All.AccountExpires.LowPart; + LocalBuffer->LogoffTime.HighPart = UserInfo->All.AccountExpires.HighPart; + + memcpy(LocalBuffer->UserSessionKey, + &LogonPwdData->UserSessionKey, + MSV1_0_USER_SESSION_KEY_LENGTH); + + //FIXME: Set Domainname if we domain joined + // what to do if not? WORKGROUP + RtlInitUnicodeString(&LocalBuffer->LogonDomainName, NULL); + + memcpy(LocalBuffer->LanmanSessionKey, + &LogonPwdData->LanmanSessionKey, + MSV1_0_LANMAN_SESSION_KEY_LENGTH); + + if (!NtlmUStrWriteToStruct(LocalBuffer, + BufferLength, + &LocalBuffer->LogonServer, + &ComputerNameUCS, + &PtrOffset, + TRUE)) + { + ERR("NtlmStructWriteUCS failed.\n"); + Status = ERROR_INTERNAL_ERROR; + goto done; + } + /* not supported */ + RtlInitUnicodeString(&LocalBuffer->UserParameters, NULL); + /* Build user flags */ + LocalBuffer->UserFlags = 0x0; + if (LogonPwdData->LogonType == NetLogonLmKey) + LocalBuffer->UserFlags |= LOGON_USED_LM_PASSWORD; + + /* copy data to client buffer */ + Status = NtlmCopyToClientBuffer(ClientRequest, BufferLength, &Buffer); + if (!NT_SUCCESS(Status)) + { + TRACE("DispatchTable.CopyToClientBuffer failed (Status 0x%08lx)\n", Status); + goto done; + } + + *ProfileBuffer = (PMSV1_0_LM20_LOGON_PROFILE)Buffer.ClientBaseAddress; + *ProfileBufferLength = BufferLength; +done: + /* On success Buffer.ClientBaseAddress will not be free */ + NtlmFreeClientBuffer(ClientRequest, !NT_SUCCESS(Status), &Buffer); + NtlmUStrFree(&ComputerNameUCS); + return Status; +} + static PSID AppendRidToSid(PSID SrcSid, @@ -931,7 +1030,72 @@ LsaApLogonUserEx2_Network( _Out_ PULONG LogonProfileSize, _Out_ PNTSTATUS SubStatus) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + PMSV1_0_LM20_LOGON LogonInfo; + ULONG_PTR PtrOffset; + + *LogonProfile = NULL; + *LogonProfileSize = 0; + *UserInfoPtr = NULL; + *AccountDomainSidPtr = NULL; + *SpecialAccount = FALSE; + LogonInfo = ProtocolSubmitBuffer; + + if (SubmitBufferSize < sizeof(MSV1_0_LM20_LOGON)) + { + ERR("Invalid SubmitBufferSize %lu\n", SubmitBufferSize); + return STATUS_INVALID_PARAMETER; + } + + /* Fix-up pointers in the authentication info */ + PtrOffset = (ULONG_PTR)ProtocolSubmitBuffer - (ULONG_PTR)ClientBufferBase; + + if ((!NtlmFixupAndValidateUStr(&LogonInfo->LogonDomainName, PtrOffset)) || + (!NtlmFixupAndValidateUStr(&LogonInfo->UserName, PtrOffset)) || + (!NtlmFixupAndValidateUStr(&LogonInfo->Workstation, PtrOffset)) || + (!NtlmFixupAStr(&LogonInfo->CaseSensitiveChallengeResponse, PtrOffset)) || + (!NtlmFixupAStr(&LogonInfo->CaseInsensitiveChallengeResponse, PtrOffset))) + { + return STATUS_INVALID_PARAMETER; + } + + LogonPwdData->IsNetwork = TRUE; + LogonPwdData->LogonInfo = LogonInfo; + LogonPwdData->ComputerName = ComputerName; + Status = SamValidateUser(Network, + &LogonInfo->UserName, + &LogonInfo->LogonDomainName, + LogonPwdData, + ComputerName, + SpecialAccount, + AccountDomainSidPtr, + UserHandlePtr, + UserInfoPtr, + SubStatus); + if (!NT_SUCCESS(Status)) + { + ERR("SamValidateUser failed with 0x%lx\n", Status); + return Status; + } + + if (LogonInfo->ParameterControl & MSV1_0_RETURN_PROFILE_PATH) + { + Status = BuildLm20LogonProfileBuffer(ClientRequest, + *UserInfoPtr, + LogonPwdData, + LogonProfile, + LogonProfileSize); + if (!NT_SUCCESS(Status)) + { + ERR("BuildLm20LogonProfileBuffer failed with 0x%lx\n", Status); + return Status; + } + } + + *LogonUserRef = &LogonInfo->UserName; + *LogonDomainRef = &LogonInfo->LogonDomainName; + + return Status; }
/* @@ -1325,39 +1489,6 @@ SpLsaModeInitialize(
*PackageVersion = SECPKG_INTERFACE_VERSION;
- RtlZeroMemory(NtlmLsaFn, sizeof(NtlmLsaFn)); - - /* msv1_0 (XP, win2k) returns NULL for - * InitializePackage, LsaLogonUser,LsaLogonUserEx, - * SpQueryContextAttributes and SpAddCredentials */ - NtlmLsaFn[0].InitializePackage = NULL; - NtlmLsaFn[0].LsaLogonUser = NULL; - NtlmLsaFn[0].CallPackage = LsaApCallPackage; - NtlmLsaFn[0].LogonTerminated = LsaApLogonTerminated; - NtlmLsaFn[0].CallPackageUntrusted = LsaApCallPackageUntrusted; - NtlmLsaFn[0].CallPackagePassthrough = LsaApCallPackagePassthrough; - NtlmLsaFn[0].LogonUserEx = NULL; - NtlmLsaFn[0].LogonUserEx2 = LsaApLogonUserEx2; - NtlmLsaFn[0].Initialize = SpInitialize; - NtlmLsaFn[0].Shutdown = LsaSpShutDown; - NtlmLsaFn[0].GetInfo = LsaSpGetInfoW; - NtlmLsaFn[0].AcceptCredentials = SpAcceptCredentials; - NtlmLsaFn[0].SpAcquireCredentialsHandle = LsaSpAcquireCredentialsHandle; - NtlmLsaFn[0].SpQueryCredentialsAttributes = LsaSpQueryCredentialsAttributes; - NtlmLsaFn[0].FreeCredentialsHandle = LsaSpFreeCredentialsHandle; - NtlmLsaFn[0].SaveCredentials = LsaSpSaveCredentials; - NtlmLsaFn[0].GetCredentials = LsaSpGetCredentials; - NtlmLsaFn[0].DeleteCredentials = LsaSpDeleteCredentials; - NtlmLsaFn[0].InitLsaModeContext = LsaSpInitLsaModeContext; - NtlmLsaFn[0].AcceptLsaModeContext = LsaSpAcceptLsaModeContext; - NtlmLsaFn[0].DeleteContext = LsaSpDeleteContext; - NtlmLsaFn[0].ApplyControlToken = LsaSpApplyControlToken; - NtlmLsaFn[0].GetUserInfo = LsaSpGetUserInfo; - NtlmLsaFn[0].GetExtendedInformation = LsaSpGetExtendedInformation; - NtlmLsaFn[0].SpQueryContextAttributes = NULL; - NtlmLsaFn[0].SpAddCredentials = NULL; - NtlmLsaFn[0].SetExtendedInformation = LsaSpSetExtendedInformation; - *ppTables = NtlmLsaFn; *pcTables = 1;
diff --git a/dll/win32/msv1_0/msv1_0.h b/dll/win32/msv1_0/msv1_0.h index 1b656bca4f1..40b6c6bfc75 100644 --- a/dll/win32/msv1_0/msv1_0.h +++ b/dll/win32/msv1_0/msv1_0.h @@ -326,4 +326,62 @@ SystemFunction012(const BYTE *in, const BYTE *key, LPBYTE out);
+NTSTATUS +NTAPI +LsaApCallPackage( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ PVOID ProtocolSubmitBuffer, + _In_ PVOID ClientBufferBase, + _In_ ULONG SubmitBufferLength, + _Out_ PVOID *ProtocolReturnBuffer, + _Out_ PULONG ReturnBufferLength, + _Out_ PNTSTATUS ProtocolStatus); + +NTSTATUS +NTAPI +LsaApCallPackagePassthrough( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ PVOID ProtocolSubmitBuffer, + _In_ PVOID ClientBufferBase, + _In_ ULONG SubmitBufferLength, + _Out_ PVOID *ProtocolReturnBuffer, + _Out_ PULONG ReturnBufferLength, + _Out_ PNTSTATUS ProtocolStatus); + +NTSTATUS +NTAPI +LsaApCallPackageUntrusted( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ PVOID ProtocolSubmitBuffer, + _In_ PVOID ClientBufferBase, + _In_ ULONG SubmitBufferLength, + _Out_ PVOID *ProtocolReturnBuffer, + _Out_ PULONG ReturnBufferLength, + _Out_ PNTSTATUS ProtocolStatus); + +VOID +NTAPI +LsaApLogonTerminated( + _In_ PLUID LogonId); + +NTSTATUS +NTAPI +LsaApLogonUserEx2( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ SECURITY_LOGON_TYPE LogonType, + _In_ PVOID ProtocolSubmitBuffer, + _In_ PVOID ClientBufferBase, + _In_ ULONG SubmitBufferSize, + _Out_ PVOID *ProfileBuffer, + _Out_ PULONG ProfileBufferSize, + _Out_ PLUID LogonId, + _Out_ PNTSTATUS SubStatus, + _Out_ PLSA_TOKEN_INFORMATION_TYPE TokenInformationType, + _Out_ PVOID *TokenInformation, + _Out_ PUNICODE_STRING *AccountName, + _Out_ PUNICODE_STRING *AuthenticatingAuthority, + _Out_ PUNICODE_STRING *MachineName, + _Out_ PSECPKG_PRIMARY_CRED PrimaryCredentials, + _Out_ PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials); + /* EOF */ diff --git a/dll/win32/msv1_0/ntlm/global.c b/dll/win32/msv1_0/ntlm/global.c index ba1082f9ff9..12057fd2084 100644 --- a/dll/win32/msv1_0/ntlm/global.c +++ b/dll/win32/msv1_0/ntlm/global.c @@ -12,6 +12,47 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
/* globals */ +NTLM_MODE NtlmMode = NtlmUnknownMode; + +LSA_DISPATCH_TABLE DispatchTable; + +PLSA_SECPKG_FUNCTION_TABLE LsaFunctions = NULL; +/* msv1_0 (XP, win2k) returns NULL for + * InitializePackage, LsaLogonUser,LsaLogonUserEx, + * SpQueryContextAttributes and SpAddCredentials */ +SECPKG_FUNCTION_TABLE NtlmLsaFn[1] = +{ + { + .InitializePackage = NULL, + .LsaLogonUser = NULL, + .CallPackage = LsaApCallPackage, + .LogonTerminated = LsaApLogonTerminated, + .CallPackageUntrusted = LsaApCallPackageUntrusted, + .CallPackagePassthrough = LsaApCallPackagePassthrough, + .LogonUserEx = NULL, + .LogonUserEx2 = LsaApLogonUserEx2, + .Initialize = SpInitialize, + .Shutdown = LsaSpShutDown, + .GetInfo = LsaSpGetInfoW, + .AcceptCredentials = SpAcceptCredentials, + .SpAcquireCredentialsHandle = LsaSpAcquireCredentialsHandle, + .SpQueryCredentialsAttributes = LsaSpQueryCredentialsAttributes, + .FreeCredentialsHandle = LsaSpFreeCredentialsHandle, + .SaveCredentials = LsaSpSaveCredentials, + .GetCredentials = LsaSpGetCredentials, + .DeleteCredentials = LsaSpDeleteCredentials, + .InitLsaModeContext = LsaSpInitLsaModeContext, + .AcceptLsaModeContext = LsaSpAcceptLsaModeContext, + .DeleteContext = LsaSpDeleteContext, + .ApplyControlToken = LsaSpApplyControlToken, + .GetUserInfo = LsaSpGetUserInfo, + .GetExtendedInformation = LsaSpGetExtendedInformation, + .SpQueryContextAttributes = NULL, + .SpAddCredentials = NULL, + .SetExtendedInformation = LsaSpSetExtendedInformation + } +}; + PSECPKG_DLL_FUNCTIONS UsrFunctions = NULL; SECPKG_USER_FUNCTION_TABLE NtlmUsrFn[1] = { diff --git a/dll/win32/msv1_0/ntlm/global.h b/dll/win32/msv1_0/ntlm/global.h index 2ee2f1092dd..4b83d232bc4 100644 --- a/dll/win32/msv1_0/ntlm/global.h +++ b/dll/win32/msv1_0/ntlm/global.h @@ -1,17 +1,29 @@ /* * PROJECT: Authentication Package DLL * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) - * PURPOSE: ntlm globals definitions (header) + * PURPOSE: NTLM globals definitions (header) * COPYRIGHT: Copyright 2011 Samuel Serapión - * Copyright 2020 Andreas Maier (staubim@quantentunnel.de) + * Copyright 2020 Andreas Maier staubim@quantentunnel.de */
-#ifndef _MSV1_0_NTLM_GLOBALS_H_ -#define _MSV1_0_NTLM_GLOBALS_H_ +#pragma once
+/* functions provided by LSA in SpInitialize */ +extern PLSA_SECPKG_FUNCTION_TABLE LsaFunctions; +/* functions we provide to LSA in SpLsaModeInitialize */ +extern SECPKG_FUNCTION_TABLE NtlmLsaFn[1]; /* functions provided by LSA in SpInstanceInit */ extern PSECPKG_DLL_FUNCTIONS UsrFunctions; /* functions we provide to LSA in SpUserModeInitialize */ extern SECPKG_USER_FUNCTION_TABLE NtlmUsrFn[1];
-#endif +extern LSA_DISPATCH_TABLE DispatchTable; + +typedef enum _NTLM_MODE +{ + NtlmUnknownMode = 0, + NtlmLsaMode = 1, + NtlmUserMode +} NTLM_MODE, *PNTLM_MODE; + +extern NTLM_MODE NtlmMode; diff --git a/dll/win32/msv1_0/ntlm/protocol.h b/dll/win32/msv1_0/ntlm/protocol.h new file mode 100644 index 00000000000..e379845eb80 --- /dev/null +++ b/dll/win32/msv1_0/ntlm/protocol.h @@ -0,0 +1,24 @@ +/* + * PROJECT: Authentication Package DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: NTLM protocol definitions (header) + * COPYRIGHT: Copyright 2011 Samuel Serapión + * Copyright 2020 Andreas Maier staubim@quantentunnel.de + */ + +#pragma once + +typedef struct _CYPHER_BLOCK +{ + CHAR data[8]; +} CYPHER_BLOCK, *PCYPHER_BLOCK; + +typedef struct _USER_SESSION_KEY +{ + CYPHER_BLOCK data[2]; +} USER_SESSION_KEY, *PUSER_SESSION_KEY; + +typedef struct _LANMAN_SESSION_KEY +{ + UINT8 data[MSV1_0_LANMAN_SESSION_KEY_LENGTH]; +} LANMAN_SESSION_KEY, *PLANMAN_SESSION_KEY; diff --git a/dll/win32/msv1_0/ntlm/util.c b/dll/win32/msv1_0/ntlm/util.c new file mode 100644 index 00000000000..948a0b72e09 --- /dev/null +++ b/dll/win32/msv1_0/ntlm/util.c @@ -0,0 +1,367 @@ +/* + * PROJECT: Authentication Package DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Utils for msv1_0 + * COPYRIGHT: Copyright 2011 Samuel Serapión + * Copyright 2020 Andreas Maier staubim@quantentunnel.de + */ + +#include "../precomp.h" + +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(ntlm); + +#define NTLM_ALLOC_TAG "NTLM" +#define NTLM_ALLOC_TAG_SIZE strlen(NTLM_ALLOC_TAG) + +PVOID +NtlmAllocate( + _In_ size_t Size, + _In_ bool UsePrivateLsaHeap) +{ + PVOID buffer = NULL; + + if (Size == 0) + { + ERR("Allocating 0 bytes!\n"); + return NULL; + } + + Size += NTLM_ALLOC_TAG_SIZE; + + switch (NtlmMode) + { + case NtlmLsaMode: + { + if (UsePrivateLsaHeap) + buffer = LsaFunctions->AllocatePrivateHeap(Size); + else + buffer = LsaFunctions->AllocateLsaHeap(Size); + + if (buffer != NULL) + RtlZeroMemory(buffer, Size); + break; + } + case NtlmUserMode: + { + buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size); + break; + } + default: + { + ERR("NtlmState unknown!\n"); + break; + } + } + + memcpy(buffer, NTLM_ALLOC_TAG, NTLM_ALLOC_TAG_SIZE); + buffer = (PBYTE)buffer + NTLM_ALLOC_TAG_SIZE; + + return buffer; +} + +VOID +NtlmFree( + _In_ PVOID Buffer, + _In_ bool FromPrivateLsaHeap) +{ + if (Buffer) + { + Buffer = (PBYTE)Buffer - NTLM_ALLOC_TAG_SIZE; + ASSERT(memcmp(Buffer, NTLM_ALLOC_TAG, NTLM_ALLOC_TAG_SIZE) == 0); + *(char*)Buffer = 'D'; + + switch (NtlmMode) + { + case NtlmLsaMode: + { + if (FromPrivateLsaHeap) + LsaFunctions->FreePrivateHeap(Buffer); + else + LsaFunctions->FreeLsaHeap(Buffer); + break; + } + case NtlmUserMode: + { + HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, Buffer); + break; + } + default: + { + ERR("NtlmState unknown!\n"); + break; + } + } + } + else + { + ERR("Trying to free NULL!\n"); + } +} + +bool +NtlmUStrAlloc( + _Inout_ PUNICODE_STRING Dst, + _In_ UINT16 SizeInBytes, + _In_ UINT16 InitLength) +{ + Dst->Length = InitLength; + Dst->MaximumLength = SizeInBytes; + Dst->Buffer = NtlmAllocate(SizeInBytes, false); + return (Dst->Buffer != NULL); +} + +VOID +NtlmUStrFree( + _In_ PUNICODE_STRING String) +{ + if (String == NULL || String->Buffer == NULL || String->MaximumLength == 0) + return; + + NtlmFree(String->Buffer, false); + String->Buffer = NULL; + String->MaximumLength = 0; +} + +/** + * @brief Helper to fill a WCHAR-String in a struct. + * The stringdata is appended to the struct. + * The function does not allocate memory. + * + * @param[in] DataStart + * Start address of the struct + * + * @param[in] DataSize + * Size of allocated memory (including payload) + * + * @param[out] DstDataWPtr + * Pointer to the WCHAR* datafield. The address of the data will be written to it. + * + * @param[in] SrcDataW + * Data to write/append at pOffset (payload). pOffset will be increased after writing data. + * + * @param[in] SrcDataLen + * SrcDataLen is the length in bytes without terminator. + * if 0 it will be autodetected by assuming a 0-terminating string. + * + * @param[in,out] AbsoluteOffsetPtr + * Current absolute offset. Will be increased by data length. + * + * @param[in] TerminateWith0 + * Whether to terminate the string with a NULL-char. + * + * @return FALSE if something went wrong + */ +static +bool +NtlmStructWriteStrW( + _In_ PVOID DataStart, + _In_ ULONG DataSize, + _Out_ PWCHAR* DstDataWPtr, + _In_ const WCHAR* SrcDataW, + _In_ ULONG SrcDataLen, + _Inout_ PBYTE* AbsoluteOffsetPtr, + _In_ bool TerminateWith0) +{ + ULONG SrcDataMaxLen; + + if (SrcDataLen == 0) + SrcDataLen = wcslen(SrcDataW) * sizeof(WCHAR); + + SrcDataMaxLen = SrcDataLen; + if (TerminateWith0) + SrcDataMaxLen += sizeof(WCHAR); + + if (*AbsoluteOffsetPtr < (PBYTE)DataStart) + { + ERR("Invalid offset\n"); + return false; + } + + if (*AbsoluteOffsetPtr + SrcDataMaxLen > (PBYTE)DataStart + DataSize) + { + ERR("Out of bounds!\n"); + return false; + } + + memcpy(*AbsoluteOffsetPtr, SrcDataW, SrcDataLen); + *DstDataWPtr = (WCHAR*)*AbsoluteOffsetPtr; + if (TerminateWith0) + (*DstDataWPtr)[SrcDataLen / sizeof(WCHAR)] = 0; + *AbsoluteOffsetPtr += SrcDataMaxLen; + + return true; +} + +bool +NtlmUStrWriteToStruct( + _In_ PVOID DataStart, + _In_ ULONG DataSize, + _Out_ PUNICODE_STRING DstData, + _In_ const PUNICODE_STRING SrcData, + _Inout_ PBYTE* AbsoluteOffsetPtr, + _In_ bool TerminateWith0) +{ + if (!NtlmStructWriteStrW(DataStart, + DataSize, + &DstData->Buffer, + SrcData->Buffer, + SrcData->Length, + AbsoluteOffsetPtr, + TerminateWith0)) + return false; + + DstData->Length = SrcData->Length; + DstData->MaximumLength = SrcData->Length; + if (TerminateWith0) + SrcData->MaximumLength += sizeof(WCHAR); + + return true; +} + +bool +NtlmFixupAndValidateUStr( + _Inout_ PUNICODE_STRING String, + _In_ ULONG_PTR FixupOffset) +{ + NTSTATUS Status; + + if (String->Length) + { + String->Buffer = FIXUP_POINTER(String->Buffer, FixupOffset); + String->MaximumLength = String->Length; + } + else + { + String->Buffer = NULL; + String->MaximumLength = 0; + } + + Status = RtlValidateUnicodeString(0, String); + return NT_SUCCESS(Status); +} + +bool +NtlmFixupAStr( + _Inout_ PSTRING String, + _In_ ULONG_PTR FixupOffset) +{ + if (String->Length) + { + String->Buffer = (PCHAR)FIXUP_POINTER(String->Buffer, FixupOffset); + String->MaximumLength = String->Length; + } + else + { + String->Buffer = NULL; + String->MaximumLength = 0; + } + + return true; +} + +NTSTATUS +NtlmAllocateClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ ULONG BufferLength, + _Inout_ PNTLM_CLIENT_BUFFER Buffer) +{ + NTSTATUS Status = STATUS_SUCCESS; + + if (!Buffer) + return STATUS_NO_MEMORY; + + Buffer->LocalBuffer = NtlmAllocate(BufferLength, false); + if (!Buffer->LocalBuffer) + return STATUS_NO_MEMORY; + + if ((HANDLE)ClientRequest == INVALID_HANDLE_VALUE) + { + Buffer->ClientBaseAddress = Buffer->LocalBuffer; + //if (!ClientBaseAddress) + // return STATUS_INSUFFICIENT_RESOURCES; + } + else + { + Status = DispatchTable.AllocateClientBuffer(ClientRequest, + BufferLength, + &Buffer->ClientBaseAddress); + if (!NT_SUCCESS(Status)) + { + NtlmFree(Buffer->LocalBuffer, false); + Buffer->LocalBuffer = NULL; + } + //FIXME: Maybe we have to free ClientBaseAddress if something + // goes wrong ...? I'm not sure about that ... + } + return Status; +} + +NTSTATUS +NtlmCopyToClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ ULONG BufferLength, + _Inout_ PNTLM_CLIENT_BUFFER Buffer) +{ + NTSTATUS Status = STATUS_SUCCESS; + + if ((HANDLE)ClientRequest == INVALID_HANDLE_VALUE) + { + // If ClientRequest ist INVALID_HANDLE_VALUE + // Buffer->LocalBuffer == Buffer->ClientBaseAddress + if (Buffer->ClientBaseAddress != Buffer->LocalBuffer) + { + ERR("Buffer->ClientBaseAddress != Buffer->LocalBuffer (something must be wrong!)\n"); + return STATUS_INTERNAL_ERROR; + } + } + else + { + if (!Buffer->ClientBaseAddress || + !Buffer->LocalBuffer) + { + ERR("Invalid Buffer - not allocated!\n"); + return STATUS_NO_MEMORY; + } + Status = DispatchTable.CopyToClientBuffer(ClientRequest, + BufferLength, + Buffer->ClientBaseAddress, + Buffer->LocalBuffer); + } + return Status; +} + +VOID +NtlmFreeClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ bool FreeClientBuffer, + _Inout_ PNTLM_CLIENT_BUFFER Buffer) +{ + if (!Buffer->ClientBaseAddress) + return; + + if ((HANDLE)ClientRequest == INVALID_HANDLE_VALUE) + { + if (Buffer->ClientBaseAddress != Buffer->LocalBuffer) + { + ERR("Buffer->ClientBaseAddress != Buffer->LocalBuffer (something must be wrong!)\n"); + return; + } + // LocalBuffer and ClientBaseAddress is the same + // so we have only to free it if FreeClientBuffer is TRUE. + Buffer->LocalBuffer = NULL; + if (FreeClientBuffer) + { + NtlmFree(Buffer->ClientBaseAddress, false); + Buffer->ClientBaseAddress = NULL; + } + } + else + { + NtlmFree(Buffer->LocalBuffer, false); + Buffer->LocalBuffer = NULL; + if (FreeClientBuffer) + DispatchTable.FreeClientBuffer(ClientRequest, Buffer->ClientBaseAddress); + Buffer->ClientBaseAddress = NULL; + } +} diff --git a/dll/win32/msv1_0/ntlm/util.h b/dll/win32/msv1_0/ntlm/util.h new file mode 100644 index 00000000000..69cfa5077ce --- /dev/null +++ b/dll/win32/msv1_0/ntlm/util.h @@ -0,0 +1,64 @@ +/* + * PROJECT: Authentication Package DLL + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Utils for msv1_0 (header) + * COPYRIGHT: Copyright 2011 Samuel Serapión + * Copyright 2020 Andreas Maier staubim@quantentunnel.de + */ + +#pragma once + +bool +NtlmUStrAlloc( + _Out_ PUNICODE_STRING Dst, + _In_ UINT16 SizeInBytes, + _In_ UINT16 InitLength); + +VOID +NtlmUStrFree( + _In_ PUNICODE_STRING String); + +bool +NtlmUStrWriteToStruct( + _In_ PVOID DataStart, + _In_ ULONG DataSize, + _Out_ PUNICODE_STRING DstData, + _In_ const PUNICODE_STRING SrcData, + _In_ OUT PBYTE* AbsoluteOffsetPtr, + _In_ bool TerminateWith0); + +/* misc */ +bool +NtlmFixupAndValidateUStr( + _Inout_ PUNICODE_STRING String, + _In_ ULONG_PTR FixupOffset); + +bool +NtlmFixupAStr( + _Inout_ PSTRING String, + _In_ ULONG_PTR FixupOffset); + +/* ClientBuffer */ +typedef struct _NTLM_CLIENT_BUFFER +{ + PVOID ClientBaseAddress; + PVOID LocalBuffer; +} NTLM_CLIENT_BUFFER, *PNTLM_CLIENT_BUFFER; + +NTSTATUS +NtlmAllocateClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ ULONG BufferLength, + _Inout_ PNTLM_CLIENT_BUFFER Buffer); + +NTSTATUS +NtlmCopyToClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ ULONG BufferLength, + _In_ OUT PNTLM_CLIENT_BUFFER Buffer); + +VOID +NtlmFreeClientBuffer( + _In_ PLSA_CLIENT_REQUEST ClientRequest, + _In_ bool FreeClientBuffer, + _Inout_ PNTLM_CLIENT_BUFFER Buffer); diff --git a/dll/win32/msv1_0/precomp.h b/dll/win32/msv1_0/precomp.h index cf7b0842d50..71b2524844c 100644 --- a/dll/win32/msv1_0/precomp.h +++ b/dll/win32/msv1_0/precomp.h @@ -32,6 +32,8 @@ //#include <lsass/lsasrv.h>
#include "ntlm/global.h" +#include "ntlm/protocol.h" +#include "ntlm/util.h" #include "lsa.h" #include "msv1_0.h" #include "sam.h" diff --git a/dll/win32/msv1_0/sam.c b/dll/win32/msv1_0/sam.c index 0ffcf20d4f7..684a9f89506 100644 --- a/dll/win32/msv1_0/sam.c +++ b/dll/win32/msv1_0/sam.c @@ -476,6 +476,8 @@ SamValidateUser( NTSTATUS Status = STATUS_SUCCESS;
*SpecialAccount = FALSE; + *UserInfoPtr = NULL; + *SubStatus = STATUS_SUCCESS;
/* Check for special accounts */ // FIXME: Windows does not do this that way!! (msv1_0 does not contain these hardcoded values) diff --git a/dll/win32/msv1_0/sam.h b/dll/win32/msv1_0/sam.h index 2f82f0e1c6f..d02f2263751 100644 --- a/dll/win32/msv1_0/sam.h +++ b/dll/win32/msv1_0/sam.h @@ -7,6 +7,13 @@
#pragma once
+typedef enum _LSA_SAM_NETLOGON_TYPE +{ + NetLogonAnonymous = 0, + NetLogonLmKey, + NetLogonNtKey +} LSA_SAM_NETLOGON_TYPE; + typedef struct _LSA_SAM_PWD_DATA { /* TRUE: PlainPwd is filled, @@ -15,7 +22,12 @@ typedef struct _LSA_SAM_PWD_DATA PUNICODE_STRING PlainPwd;
/* Input (IsNetwork = TRUE) */ + PMSV1_0_LM20_LOGON LogonInfo; PUNICODE_STRING ComputerName; + /* Result (IsNetwork = TRUE) */ + LSA_SAM_NETLOGON_TYPE LogonType; + LANMAN_SESSION_KEY LanmanSessionKey; + USER_SESSION_KEY UserSessionKey; } LSA_SAM_PWD_DATA, *PLSA_SAM_PWD_DATA;
/**