https://git.reactos.org/?p=reactos.git;a=commitdiff;h=99dcd6f71cb72a973e858…
commit 99dcd6f71cb72a973e85888903b5ed31241ad5c3
Author: Andreas Maier <staubim(a)quantentunnel.de>
AuthorDate: Thu Jul 16 20:44:01 2020 +0200
Commit: Victor Perevertkin <victor(a)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(a)quantentunnel.de)
+ * Copyright 2020 Andreas Maier <staubim(a)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(a)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(a)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(a)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;
/**