mirror of
https://github.com/reactos/reactos.git
synced 2024-11-18 21:13:52 +00:00
a66c7d2ecc
Calls to LsapCallAuthenticationPackage are routed to LsaApCallPackageUntrusted instead of LsaApCallPackage for untrusted clients.
1824 lines
60 KiB
C
1824 lines
60 KiB
C
/*
|
|
* PROJECT: Local Security Authority Server DLL
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE: dll/win32/lsasrv/authpackage.c
|
|
* PURPOSE: Authentication package management routines
|
|
* COPYRIGHT: Copyright 2013 Eric Kohl
|
|
*/
|
|
|
|
#include "lsasrv.h"
|
|
|
|
#include <ndk/sefuncs.h>
|
|
#include <ndk/umfuncs.h>
|
|
|
|
typedef enum _LSA_TOKEN_INFORMATION_TYPE
|
|
{
|
|
LsaTokenInformationNull,
|
|
LsaTokenInformationV1
|
|
} LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
|
|
|
|
typedef struct _LSA_TOKEN_INFORMATION_NULL
|
|
{
|
|
LARGE_INTEGER ExpirationTime;
|
|
PTOKEN_GROUPS Groups;
|
|
} LSA_TOKEN_INFORMATION_NULL, *PLSA_TOKEN_INFORMATION_NULL;
|
|
|
|
typedef struct _LSA_TOKEN_INFORMATION_V1
|
|
{
|
|
LARGE_INTEGER ExpirationTime;
|
|
TOKEN_USER User;
|
|
PTOKEN_GROUPS Groups;
|
|
TOKEN_PRIMARY_GROUP PrimaryGroup;
|
|
PTOKEN_PRIVILEGES Privileges;
|
|
TOKEN_OWNER Owner;
|
|
TOKEN_DEFAULT_DACL DefaultDacl;
|
|
} LSA_TOKEN_INFORMATION_V1, *PLSA_TOKEN_INFORMATION_V1;
|
|
|
|
typedef PVOID PLSA_CLIENT_REQUEST;
|
|
|
|
typedef NTSTATUS (NTAPI *PLSA_CREATE_LOGON_SESSION)(PLUID);
|
|
typedef NTSTATUS (NTAPI *PLSA_DELETE_LOGON_SESSION)(PLUID);
|
|
typedef NTSTATUS (NTAPI *PLSA_ADD_CREDENTIAL)(PLUID, ULONG, PLSA_STRING, PLSA_STRING);
|
|
typedef NTSTATUS (NTAPI *PLSA_GET_CREDENTIALS)(PLUID, ULONG, PULONG, BOOLEAN, PLSA_STRING, PULONG, PLSA_STRING);
|
|
typedef NTSTATUS (NTAPI *PLSA_DELETE_CREDENTIAL)(PLUID, ULONG, PLSA_STRING);
|
|
typedef PVOID (NTAPI *PLSA_ALLOCATE_LSA_HEAP)(ULONG);
|
|
typedef VOID (NTAPI *PLSA_FREE_LSA_HEAP)(PVOID);
|
|
typedef NTSTATUS (NTAPI *PLSA_ALLOCATE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG, PVOID*);
|
|
typedef NTSTATUS (NTAPI *PLSA_FREE_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, PVOID);
|
|
typedef NTSTATUS (NTAPI *PLSA_COPY_TO_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST, ULONG,
|
|
PVOID, PVOID);
|
|
typedef NTSTATUS (NTAPI *PLSA_COPY_FROM_CLIENT_BUFFER)(PLSA_CLIENT_REQUEST,
|
|
ULONG, PVOID, PVOID);
|
|
|
|
typedef struct LSA_DISPATCH_TABLE
|
|
{
|
|
PLSA_CREATE_LOGON_SESSION CreateLogonSession;
|
|
PLSA_DELETE_LOGON_SESSION DeleteLogonSession;
|
|
PLSA_ADD_CREDENTIAL AddCredential;
|
|
PLSA_GET_CREDENTIALS GetCredentials;
|
|
PLSA_DELETE_CREDENTIAL DeleteCredential;
|
|
PLSA_ALLOCATE_LSA_HEAP AllocateLsaHeap;
|
|
PLSA_FREE_LSA_HEAP FreeLsaHeap;
|
|
PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer;
|
|
PLSA_FREE_CLIENT_BUFFER FreeClientBuffer;
|
|
PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer;
|
|
PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer;
|
|
} LSA_DISPATCH_TABLE, *PLSA_DISPATCH_TABLE;
|
|
|
|
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_INITIALIZE_PACKAGE)(ULONG, PLSA_DISPATCH_TABLE,
|
|
PLSA_STRING, PLSA_STRING, PLSA_STRING *);
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_INTERNAL)(PLSA_CLIENT_REQUEST, PVOID, PVOID,
|
|
ULONG, PVOID *, PULONG, PNTSTATUS);
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_PASSTHROUGH)(PLSA_CLIENT_REQUEST,
|
|
PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_CALL_PACKAGE_UNTRUSTED)(PLSA_CLIENT_REQUEST,
|
|
PVOID, PVOID, ULONG, PVOID *, PULONG, PNTSTATUS);
|
|
typedef VOID (NTAPI *PLSA_AP_LOGON_TERMINATED)(PLUID);
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX2)(PLSA_CLIENT_REQUEST,
|
|
SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
|
|
PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
|
|
PUNICODE_STRING *, PVOID /*PSECPKG_PRIMARY_CRED*/, PVOID /*PSECPKG_SUPPLEMENTAL_CRED_ARRAY **/);
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_EX)(PLSA_CLIENT_REQUEST,
|
|
SECURITY_LOGON_TYPE, PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS,
|
|
PLSA_TOKEN_INFORMATION_TYPE, PVOID *, PUNICODE_STRING *, PUNICODE_STRING *,
|
|
PUNICODE_STRING *);
|
|
|
|
typedef NTSTATUS (NTAPI *PLSA_AP_LOGON_USER_INTERNAL)(PLSA_CLIENT_REQUEST, SECURITY_LOGON_TYPE,
|
|
PVOID, PVOID, ULONG, PVOID *, PULONG, PLUID, PNTSTATUS, PLSA_TOKEN_INFORMATION_TYPE,
|
|
PVOID *, PUNICODE_STRING *, PUNICODE_STRING *);
|
|
|
|
typedef struct _AUTH_PACKAGE
|
|
{
|
|
LIST_ENTRY Entry;
|
|
PSTRING Name;
|
|
ULONG Id;
|
|
PVOID ModuleHandle;
|
|
|
|
PLSA_AP_INITIALIZE_PACKAGE LsaApInitializePackage;
|
|
PLSA_AP_CALL_PACKAGE_INTERNAL LsaApCallPackage;
|
|
PLSA_AP_CALL_PACKAGE_PASSTHROUGH LsaApCallPackagePassthrough;
|
|
PLSA_AP_CALL_PACKAGE_UNTRUSTED LsaApCallPackageUntrusted;
|
|
PLSA_AP_LOGON_TERMINATED LsaApLogonTerminated;
|
|
PLSA_AP_LOGON_USER_EX2 LsaApLogonUserEx2;
|
|
PLSA_AP_LOGON_USER_EX LsaApLogonUserEx;
|
|
PLSA_AP_LOGON_USER_INTERNAL LsaApLogonUser;
|
|
} AUTH_PACKAGE, *PAUTH_PACKAGE;
|
|
|
|
VOID
|
|
NTAPI
|
|
LsaIFree_LSAPR_PRIVILEGE_SET(IN PLSAPR_PRIVILEGE_SET Ptr);
|
|
|
|
typedef wchar_t *PSAMPR_SERVER_NAME;
|
|
typedef void *SAMPR_HANDLE;
|
|
|
|
typedef struct _SAMPR_SID_INFORMATION
|
|
{
|
|
PRPC_SID SidPointer;
|
|
} SAMPR_SID_INFORMATION, *PSAMPR_SID_INFORMATION;
|
|
|
|
typedef struct _SAMPR_PSID_ARRAY
|
|
{
|
|
unsigned long Count;
|
|
PSAMPR_SID_INFORMATION Sids;
|
|
} SAMPR_PSID_ARRAY, *PSAMPR_PSID_ARRAY;
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
SamIConnect(
|
|
PSAMPR_SERVER_NAME ServerName,
|
|
SAMPR_HANDLE *ServerHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
BOOLEAN Trusted);
|
|
|
|
VOID
|
|
NTAPI
|
|
SamIFree_SAMPR_ULONG_ARRAY(
|
|
PSAMPR_ULONG_ARRAY Ptr);
|
|
|
|
NTSTATUS
|
|
__stdcall
|
|
SamrCloseHandle(
|
|
SAMPR_HANDLE *SamHandle);
|
|
|
|
NTSTATUS
|
|
__stdcall
|
|
SamrOpenDomain(
|
|
SAMPR_HANDLE ServerHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
PRPC_SID DomainId,
|
|
SAMPR_HANDLE *DomainHandle);
|
|
|
|
NTSTATUS
|
|
__stdcall
|
|
SamrGetAliasMembership(
|
|
SAMPR_HANDLE DomainHandle,
|
|
PSAMPR_PSID_ARRAY SidArray,
|
|
PSAMPR_ULONG_ARRAY Membership);
|
|
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
static LIST_ENTRY PackageListHead;
|
|
static ULONG PackageId;
|
|
static LSA_DISPATCH_TABLE DispatchTable;
|
|
|
|
#define CONST_LUID(x1, x2) {x1, x2}
|
|
static const LUID SeChangeNotifyPrivilege = CONST_LUID(SE_CHANGE_NOTIFY_PRIVILEGE, 0);
|
|
static const LUID SeCreateGlobalPrivilege = CONST_LUID(SE_CREATE_GLOBAL_PRIVILEGE, 0);
|
|
static const LUID SeImpersonatePrivilege = CONST_LUID(SE_IMPERSONATE_PRIVILEGE, 0);
|
|
|
|
|
|
/* FUNCTIONS ***************************************************************/
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
LsapAddAuthPackage(IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext)
|
|
{
|
|
PAUTH_PACKAGE Package = NULL;
|
|
UNICODE_STRING PackageName;
|
|
STRING ProcName;
|
|
PULONG Id;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
TRACE("LsapAddAuthPackage()\n");
|
|
|
|
PackageName.Length = (USHORT)ValueLength - sizeof(WCHAR);
|
|
PackageName.MaximumLength = (USHORT)ValueLength;
|
|
PackageName.Buffer = ValueData;
|
|
|
|
Id = (PULONG)Context;
|
|
|
|
Package = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(AUTH_PACKAGE));
|
|
if (Package == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
Status = LdrLoadDll(NULL,
|
|
NULL,
|
|
&PackageName,
|
|
&Package->ModuleHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrLoadDll failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApInitializePackage");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApInitializePackage);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApCallPackage");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApCallPackage);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApCallPackagePassthrough");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApCallPackagePassthrough);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApCallPackageUntrusted");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApCallPackageUntrusted);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApLogonTerminated");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApLogonTerminated);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
RtlInitAnsiString(&ProcName, "LsaApLogonUserEx2");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApLogonUserEx2);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
RtlInitAnsiString(&ProcName, "LsaApLogonUserEx");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApLogonUserEx);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
RtlInitAnsiString(&ProcName, "LsaApLogonUser");
|
|
Status = LdrGetProcedureAddress(Package->ModuleHandle,
|
|
&ProcName,
|
|
0,
|
|
(PVOID *)&Package->LsaApLogonUser);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LdrGetProcedureAddress() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Initialize the current package */
|
|
Status = Package->LsaApInitializePackage(*Id,
|
|
&DispatchTable,
|
|
NULL,
|
|
NULL,
|
|
&Package->Name);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("Package->LsaApInitializePackage() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
TRACE("Package Name: %s\n", Package->Name->Buffer);
|
|
|
|
Package->Id = *Id;
|
|
(*Id)++;
|
|
|
|
InsertTailList(&PackageListHead, &Package->Entry);
|
|
|
|
done:
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (Package != NULL)
|
|
{
|
|
if (Package->ModuleHandle != NULL)
|
|
LdrUnloadDll(Package->ModuleHandle);
|
|
|
|
if (Package->Name != NULL)
|
|
{
|
|
if (Package->Name->Buffer != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name->Buffer);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Package->Name);
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Package);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
PAUTH_PACKAGE
|
|
LsapGetAuthenticationPackage(IN ULONG PackageId)
|
|
{
|
|
PLIST_ENTRY ListEntry;
|
|
PAUTH_PACKAGE Package;
|
|
|
|
ListEntry = PackageListHead.Flink;
|
|
while (ListEntry != &PackageListHead)
|
|
{
|
|
Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
|
|
|
|
if (Package->Id == PackageId)
|
|
{
|
|
return Package;
|
|
}
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PVOID
|
|
NTAPI
|
|
LsapAllocateHeap(IN ULONG Length)
|
|
{
|
|
return RtlAllocateHeap(RtlGetProcessHeap(), 0, Length);
|
|
}
|
|
|
|
|
|
PVOID
|
|
NTAPI
|
|
LsapAllocateHeapZero(IN ULONG Length)
|
|
{
|
|
return RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
}
|
|
|
|
|
|
VOID
|
|
NTAPI
|
|
LsapFreeHeap(IN PVOID Base)
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Base);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
LsapAllocateClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
|
|
IN ULONG LengthRequired,
|
|
OUT PVOID *ClientBaseAddress)
|
|
{
|
|
PLSAP_LOGON_CONTEXT LogonContext;
|
|
SIZE_T Length;
|
|
|
|
*ClientBaseAddress = NULL;
|
|
|
|
LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
|
|
|
|
Length = LengthRequired;
|
|
return NtAllocateVirtualMemory(LogonContext->ClientProcessHandle,
|
|
ClientBaseAddress,
|
|
0,
|
|
&Length,
|
|
MEM_COMMIT,
|
|
PAGE_READWRITE);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
LsapFreeClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
|
|
IN PVOID ClientBaseAddress)
|
|
{
|
|
PLSAP_LOGON_CONTEXT LogonContext;
|
|
SIZE_T Length;
|
|
|
|
if (ClientBaseAddress == NULL)
|
|
return STATUS_SUCCESS;
|
|
|
|
LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
|
|
|
|
Length = 0;
|
|
return NtFreeVirtualMemory(LogonContext->ClientProcessHandle,
|
|
&ClientBaseAddress,
|
|
&Length,
|
|
MEM_RELEASE);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
LsapCopyToClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
|
|
IN ULONG Length,
|
|
IN PVOID ClientBaseAddress,
|
|
IN PVOID BufferToCopy)
|
|
{
|
|
PLSAP_LOGON_CONTEXT LogonContext;
|
|
|
|
LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
|
|
|
|
return NtWriteVirtualMemory(LogonContext->ClientProcessHandle,
|
|
ClientBaseAddress,
|
|
BufferToCopy,
|
|
Length,
|
|
NULL);
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
NTAPI
|
|
LsapCopyFromClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
|
|
IN ULONG Length,
|
|
IN PVOID BufferToCopy,
|
|
IN PVOID ClientBaseAddress)
|
|
{
|
|
PLSAP_LOGON_CONTEXT LogonContext;
|
|
|
|
LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
|
|
|
|
return NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
ClientBaseAddress,
|
|
BufferToCopy,
|
|
Length,
|
|
NULL);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapInitAuthPackages(VOID)
|
|
{
|
|
RTL_QUERY_REGISTRY_TABLE AuthPackageTable[] = {
|
|
{LsapAddAuthPackage, 0, L"Authentication Packages", NULL, REG_NONE, NULL, 0},
|
|
{NULL, 0, NULL, NULL, REG_NONE, NULL, 0}};
|
|
|
|
NTSTATUS Status;
|
|
|
|
InitializeListHead(&PackageListHead);
|
|
PackageId = 0;
|
|
|
|
/* Initialize the dispatch table */
|
|
DispatchTable.CreateLogonSession = &LsapCreateLogonSession;
|
|
DispatchTable.DeleteLogonSession = &LsapDeleteLogonSession;
|
|
DispatchTable.AddCredential = &LsapAddCredential;
|
|
DispatchTable.GetCredentials = &LsapGetCredentials;
|
|
DispatchTable.DeleteCredential = &LsapDeleteCredential;
|
|
DispatchTable.AllocateLsaHeap = &LsapAllocateHeapZero;
|
|
DispatchTable.FreeLsaHeap = &LsapFreeHeap;
|
|
DispatchTable.AllocateClientBuffer = &LsapAllocateClientBuffer;
|
|
DispatchTable.FreeClientBuffer = &LsapFreeClientBuffer;
|
|
DispatchTable.CopyToClientBuffer = &LsapCopyToClientBuffer;
|
|
DispatchTable.CopyFromClientBuffer = &LsapCopyFromClientBuffer;
|
|
|
|
/* Add registered authentication packages */
|
|
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
|
|
L"Lsa",
|
|
AuthPackageTable,
|
|
&PackageId,
|
|
NULL);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapLookupAuthenticationPackage(PLSA_API_MSG RequestMsg,
|
|
PLSAP_LOGON_CONTEXT LogonContext)
|
|
{
|
|
PLIST_ENTRY ListEntry;
|
|
PAUTH_PACKAGE Package;
|
|
ULONG PackageNameLength;
|
|
PCHAR PackageName;
|
|
|
|
TRACE("(%p %p)\n", RequestMsg, LogonContext);
|
|
|
|
PackageNameLength = RequestMsg->LookupAuthenticationPackage.Request.PackageNameLength;
|
|
PackageName = RequestMsg->LookupAuthenticationPackage.Request.PackageName;
|
|
|
|
TRACE("PackageName: %s\n", PackageName);
|
|
|
|
ListEntry = PackageListHead.Flink;
|
|
while (ListEntry != &PackageListHead)
|
|
{
|
|
Package = CONTAINING_RECORD(ListEntry, AUTH_PACKAGE, Entry);
|
|
|
|
if ((PackageNameLength == Package->Name->Length) &&
|
|
(_strnicmp(PackageName, Package->Name->Buffer, Package->Name->Length) == 0))
|
|
{
|
|
RequestMsg->LookupAuthenticationPackage.Reply.Package = Package->Id;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ListEntry = ListEntry->Flink;
|
|
}
|
|
|
|
return STATUS_NO_SUCH_PACKAGE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapCallAuthenticationPackage(PLSA_API_MSG RequestMsg,
|
|
PLSAP_LOGON_CONTEXT LogonContext)
|
|
{
|
|
PAUTH_PACKAGE Package;
|
|
PVOID LocalBuffer = NULL;
|
|
ULONG PackageId;
|
|
NTSTATUS Status;
|
|
|
|
TRACE("(%p %p)\n", RequestMsg, LogonContext);
|
|
|
|
PackageId = RequestMsg->CallAuthenticationPackage.Request.AuthenticationPackage;
|
|
|
|
/* Get the right authentication package */
|
|
Package = LsapGetAuthenticationPackage(PackageId);
|
|
if (Package == NULL)
|
|
{
|
|
TRACE("LsapGetAuthenticationPackage() failed to find a package\n");
|
|
return STATUS_NO_SUCH_PACKAGE;
|
|
}
|
|
|
|
if (RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength > 0)
|
|
{
|
|
LocalBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength);
|
|
if (LocalBuffer == NULL)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
|
|
LocalBuffer,
|
|
RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
if (LogonContext->Untrusted)
|
|
Status = Package->LsaApCallPackageUntrusted((PLSA_CLIENT_REQUEST)LogonContext,
|
|
LocalBuffer,
|
|
RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
|
|
RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
|
|
else
|
|
Status = Package->LsaApCallPackage((PLSA_CLIENT_REQUEST)LogonContext,
|
|
LocalBuffer,
|
|
RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
|
|
RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
|
|
&RequestMsg->CallAuthenticationPackage.Reply.ProtocolStatus);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("Package->LsaApCallPackage() failed (Status 0x%08lx)\n", Status);
|
|
}
|
|
|
|
if (LocalBuffer != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalBuffer);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapCopyLocalGroups(
|
|
IN PLSAP_LOGON_CONTEXT LogonContext,
|
|
IN PTOKEN_GROUPS ClientGroups,
|
|
IN ULONG ClientGroupsCount,
|
|
OUT PTOKEN_GROUPS *TokenGroups)
|
|
{
|
|
ULONG LocalGroupsLength = 0;
|
|
PTOKEN_GROUPS LocalGroups = NULL;
|
|
ULONG SidHeaderLength = 0;
|
|
PSID SidHeader = NULL;
|
|
PSID SrcSid, DstSid;
|
|
ULONG SidLength;
|
|
ULONG AllocatedSids = 0;
|
|
ULONG i;
|
|
NTSTATUS Status;
|
|
|
|
LocalGroupsLength = sizeof(TOKEN_GROUPS) +
|
|
(ClientGroupsCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
LocalGroups = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
LocalGroupsLength);
|
|
if (LocalGroups == NULL)
|
|
{
|
|
TRACE("RtlAllocateHeap() failed\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
ClientGroups,
|
|
LocalGroups,
|
|
LocalGroupsLength,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
|
|
SidHeaderLength = RtlLengthRequiredSid(0);
|
|
SidHeader = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
SidHeaderLength);
|
|
if (SidHeader == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
for (i = 0; i < ClientGroupsCount; i++)
|
|
{
|
|
SrcSid = LocalGroups->Groups[i].Sid;
|
|
|
|
Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
SrcSid,
|
|
SidHeader,
|
|
SidHeaderLength,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
goto done;
|
|
|
|
SidLength = RtlLengthSid(SidHeader);
|
|
TRACE("Sid %lu: Length %lu\n", i, SidLength);
|
|
|
|
DstSid = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
SidLength);
|
|
if (DstSid == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
SrcSid,
|
|
DstSid,
|
|
SidLength,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DstSid);
|
|
goto done;
|
|
}
|
|
|
|
LocalGroups->Groups[i].Sid = DstSid;
|
|
AllocatedSids++;
|
|
}
|
|
|
|
*TokenGroups = LocalGroups;
|
|
|
|
done:
|
|
if (SidHeader != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, SidHeader);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (LocalGroups != NULL)
|
|
{
|
|
for (i = 0; i < AllocatedSids; i++)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddLocalGroups(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
|
|
IN PTOKEN_GROUPS LocalGroups)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
PTOKEN_GROUPS Groups;
|
|
ULONG Length;
|
|
ULONG i;
|
|
ULONG j;
|
|
|
|
if (LocalGroups == NULL || LocalGroups->GroupCount == 0)
|
|
return STATUS_SUCCESS;
|
|
|
|
if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
if (TokenInfo1->Groups != NULL)
|
|
{
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
(LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Groups->GroupCount = LocalGroups->GroupCount + TokenInfo1->Groups->GroupCount;
|
|
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
{
|
|
Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
|
|
Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
|
|
}
|
|
|
|
for (j = 0; j < LocalGroups->GroupCount; i++, j++)
|
|
{
|
|
Groups->Groups[i].Sid = LocalGroups->Groups[j].Sid;
|
|
Groups->Groups[i].Attributes = LocalGroups->Groups[j].Attributes;
|
|
LocalGroups->Groups[j].Sid = NULL;
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
|
|
|
|
TokenInfo1->Groups = Groups;
|
|
}
|
|
else
|
|
{
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
(LocalGroups->GroupCount - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Groups->GroupCount = LocalGroups->GroupCount;
|
|
|
|
for (i = 0; i < LocalGroups->GroupCount; i++)
|
|
{
|
|
Groups->Groups[i].Sid = LocalGroups->Groups[i].Sid;
|
|
Groups->Groups[i].Attributes = LocalGroups->Groups[i].Attributes;
|
|
}
|
|
|
|
TokenInfo1->Groups = Groups;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddDefaultGroups(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType,
|
|
IN SECURITY_LOGON_TYPE LogonType)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
PTOKEN_GROUPS Groups;
|
|
ULONG i, Length;
|
|
PSID SrcSid;
|
|
|
|
if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
if (TokenInfo1->Groups != NULL)
|
|
{
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
(TokenInfo1->Groups->GroupCount + 2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Groups->GroupCount = TokenInfo1->Groups->GroupCount;
|
|
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
{
|
|
Groups->Groups[i].Sid = TokenInfo1->Groups->Groups[i].Sid;
|
|
Groups->Groups[i].Attributes = TokenInfo1->Groups->Groups[i].Attributes;
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, TokenInfo1->Groups);
|
|
|
|
TokenInfo1->Groups = Groups;
|
|
|
|
}
|
|
else
|
|
{
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
(2 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
TokenInfo1->Groups = Groups;
|
|
}
|
|
|
|
/* Append the World SID (aka Everyone) */
|
|
Length = RtlLengthSid(LsapWorldSid);
|
|
Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
Length);
|
|
if (Groups->Groups[Groups->GroupCount].Sid == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
|
|
LsapWorldSid,
|
|
Length);
|
|
|
|
Groups->Groups[Groups->GroupCount].Attributes =
|
|
SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
|
|
|
|
Groups->GroupCount++;
|
|
|
|
/* Append the logon type SID */
|
|
switch (LogonType)
|
|
{
|
|
case Interactive:
|
|
SrcSid = LsapInteractiveSid;
|
|
break;
|
|
|
|
case Network:
|
|
SrcSid = LsapNetworkSid;
|
|
break;
|
|
|
|
case Batch:
|
|
SrcSid = LsapBatchSid;
|
|
break;
|
|
|
|
case Service:
|
|
SrcSid = LsapServiceSid;
|
|
break;
|
|
|
|
default:
|
|
FIXME("LogonType %d is not supported!\n", LogonType);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
Length = RtlLengthSid(SrcSid);
|
|
Groups->Groups[Groups->GroupCount].Sid = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
Length);
|
|
if (Groups->Groups[Groups->GroupCount].Sid == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(Groups->Groups[Groups->GroupCount].Sid,
|
|
SrcSid,
|
|
Length);
|
|
|
|
Groups->Groups[Groups->GroupCount].Attributes =
|
|
SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
|
|
|
|
Groups->GroupCount++;
|
|
}
|
|
else
|
|
{
|
|
FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAppendSidToGroups(
|
|
IN PTOKEN_GROUPS *TokenGroups,
|
|
IN PSID DomainSid,
|
|
IN ULONG RelativeId)
|
|
{
|
|
PTOKEN_GROUPS Groups;
|
|
PSID Sid;
|
|
ULONG Length;
|
|
ULONG i;
|
|
|
|
Sid = LsapAppendRidToSid(DomainSid, RelativeId);
|
|
if (Sid == NULL)
|
|
{
|
|
ERR("Group SID creation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (*TokenGroups == NULL)
|
|
{
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
(1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Groups->GroupCount = 1;
|
|
|
|
Groups->Groups[0].Sid = Sid;
|
|
Groups->Groups[0].Attributes =
|
|
SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
|
|
|
|
*TokenGroups = Groups;
|
|
}
|
|
else
|
|
{
|
|
for (i = 0; i < (*TokenGroups)->GroupCount; i++)
|
|
{
|
|
if (RtlEqualSid((*TokenGroups)->Groups[i].Sid, Sid))
|
|
{
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
Length = sizeof(TOKEN_GROUPS) +
|
|
((*TokenGroups)->GroupCount + 1 - ANYSIZE_ARRAY) * sizeof(SID_AND_ATTRIBUTES);
|
|
|
|
Groups = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, Length);
|
|
if (Groups == NULL)
|
|
{
|
|
ERR("Group buffer allocation failed!\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Groups->GroupCount = (*TokenGroups)->GroupCount;
|
|
|
|
for (i = 0; i < (*TokenGroups)->GroupCount; i++)
|
|
{
|
|
Groups->Groups[i].Sid = (*TokenGroups)->Groups[i].Sid;
|
|
Groups->Groups[i].Attributes = (*TokenGroups)->Groups[i].Attributes;
|
|
}
|
|
|
|
Groups->Groups[Groups->GroupCount].Sid = Sid;
|
|
Groups->Groups[Groups->GroupCount].Attributes =
|
|
SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
|
|
|
|
Groups->GroupCount++;
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenGroups);
|
|
|
|
*TokenGroups = Groups;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddSamGroups(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
SAMPR_HANDLE ServerHandle = NULL;
|
|
SAMPR_HANDLE BuiltinDomainHandle = NULL;
|
|
SAMPR_HANDLE AccountDomainHandle = NULL;
|
|
SAMPR_PSID_ARRAY SidArray;
|
|
SAMPR_ULONG_ARRAY BuiltinMembership;
|
|
SAMPR_ULONG_ARRAY AccountMembership;
|
|
ULONG i;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (TokenInformationType != LsaTokenInformationV1)
|
|
return STATUS_SUCCESS;
|
|
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
SidArray.Count = TokenInfo1->Groups->GroupCount + 1;
|
|
SidArray.Sids = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
(TokenInfo1->Groups->GroupCount + 1) * sizeof(PRPC_SID));
|
|
if (SidArray.Sids == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
SidArray.Sids[0].SidPointer = TokenInfo1->User.User.Sid;
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
SidArray.Sids[i + 1].SidPointer = TokenInfo1->Groups->Groups[i].Sid;
|
|
|
|
BuiltinMembership.Element = NULL;
|
|
AccountMembership.Element = NULL;
|
|
|
|
Status = SamIConnect(NULL,
|
|
&ServerHandle,
|
|
SAM_SERVER_CONNECT | SAM_SERVER_LOOKUP_DOMAIN,
|
|
FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("SamIConnect failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = SamrOpenDomain(ServerHandle,
|
|
DOMAIN_GET_ALIAS_MEMBERSHIP,
|
|
BuiltinDomainSid,
|
|
&BuiltinDomainHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = SamrOpenDomain(ServerHandle,
|
|
DOMAIN_GET_ALIAS_MEMBERSHIP,
|
|
AccountDomainSid,
|
|
&AccountDomainHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("SamrOpenDomain failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = SamrGetAliasMembership(BuiltinDomainHandle,
|
|
&SidArray,
|
|
&BuiltinMembership);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = SamrGetAliasMembership(AccountDomainHandle,
|
|
&SidArray,
|
|
&AccountMembership);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("SamrGetAliasMembership failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
TRACE("Builtin Memberships: %lu\n", BuiltinMembership.Count);
|
|
for (i = 0; i < BuiltinMembership.Count; i++)
|
|
{
|
|
TRACE("RID %lu: %lu (0x%lx)\n", i, BuiltinMembership.Element[i], BuiltinMembership.Element[i]);
|
|
Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
|
|
BuiltinDomainSid,
|
|
BuiltinMembership.Element[i]);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
TRACE("Account Memberships: %lu\n", AccountMembership.Count);
|
|
for (i = 0; i < AccountMembership.Count; i++)
|
|
{
|
|
TRACE("RID %lu: %lu (0x%lx)\n", i, AccountMembership.Element[i], AccountMembership.Element[i]);
|
|
Status = LsapAppendSidToGroups(&TokenInfo1->Groups,
|
|
AccountDomainSid,
|
|
AccountMembership.Element[i]);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
TRACE("LsapAppendSidToGroups failed (Status %08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
done:
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, SidArray.Sids);
|
|
|
|
if (AccountMembership.Element != NULL)
|
|
SamIFree_SAMPR_ULONG_ARRAY(&AccountMembership);
|
|
|
|
if (BuiltinMembership.Element != NULL)
|
|
SamIFree_SAMPR_ULONG_ARRAY(&BuiltinMembership);
|
|
|
|
if (AccountDomainHandle != NULL)
|
|
SamrCloseHandle(&AccountDomainHandle);
|
|
|
|
if (BuiltinDomainHandle != NULL)
|
|
SamrCloseHandle(&BuiltinDomainHandle);
|
|
|
|
if (ServerHandle != NULL)
|
|
SamrCloseHandle(&ServerHandle);
|
|
|
|
// return Status;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapSetTokenOwner(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
PSID_AND_ATTRIBUTES OwnerSid = NULL;
|
|
ULONG i, Length;
|
|
|
|
if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
if (TokenInfo1->Owner.Owner != NULL)
|
|
return STATUS_SUCCESS;
|
|
|
|
OwnerSid = &TokenInfo1->User.User;
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
{
|
|
if (EqualSid(TokenInfo1->Groups->Groups[i].Sid, LsapAdministratorsSid))
|
|
{
|
|
OwnerSid = &TokenInfo1->Groups->Groups[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
Length = RtlLengthSid(OwnerSid->Sid);
|
|
TokenInfo1->Owner.Owner = DispatchTable.AllocateLsaHeap(Length);
|
|
if (TokenInfo1->Owner.Owner == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCopyMemory(TokenInfo1->Owner.Owner,
|
|
OwnerSid->Sid,
|
|
Length);
|
|
OwnerSid->Attributes |= SE_GROUP_OWNER;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddTokenDefaultDacl(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
PACL Dacl = NULL;
|
|
ULONG Length;
|
|
|
|
if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
|
|
return STATUS_SUCCESS;
|
|
|
|
Length = sizeof(ACL) +
|
|
(2 * sizeof(ACCESS_ALLOWED_ACE)) +
|
|
RtlLengthSid(TokenInfo1->Owner.Owner) +
|
|
RtlLengthSid(LsapLocalSystemSid);
|
|
|
|
Dacl = DispatchTable.AllocateLsaHeap(Length);
|
|
if (Dacl == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
RtlCreateAcl(Dacl, Length, ACL_REVISION);
|
|
|
|
RtlAddAccessAllowedAce(Dacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
TokenInfo1->Owner.Owner);
|
|
|
|
/* SID: S-1-5-18 */
|
|
RtlAddAccessAllowedAce(Dacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
LsapLocalSystemSid);
|
|
|
|
TokenInfo1->DefaultDacl.DefaultDacl = Dacl;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapAddPrivilegeToTokenPrivileges(PTOKEN_PRIVILEGES *TokenPrivileges,
|
|
PLSAPR_LUID_AND_ATTRIBUTES Privilege)
|
|
{
|
|
PTOKEN_PRIVILEGES LocalPrivileges;
|
|
ULONG Length, TokenPrivilegeCount, i;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
if (*TokenPrivileges == NULL)
|
|
{
|
|
Length = sizeof(TOKEN_PRIVILEGES) +
|
|
(1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
|
|
LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
Length);
|
|
if (LocalPrivileges == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
LocalPrivileges->PrivilegeCount = 1;
|
|
LocalPrivileges->Privileges[0].Luid = Privilege->Luid;
|
|
LocalPrivileges->Privileges[0].Attributes = Privilege->Attributes;
|
|
}
|
|
else
|
|
{
|
|
TokenPrivilegeCount = (*TokenPrivileges)->PrivilegeCount;
|
|
|
|
for (i = 0; i < TokenPrivilegeCount; i++)
|
|
{
|
|
if (RtlEqualLuid(&(*TokenPrivileges)->Privileges[i].Luid, &Privilege->Luid))
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
Length = sizeof(TOKEN_PRIVILEGES) +
|
|
(TokenPrivilegeCount + 1 - ANYSIZE_ARRAY) * sizeof(LUID_AND_ATTRIBUTES);
|
|
LocalPrivileges = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
0,
|
|
Length);
|
|
if (LocalPrivileges == NULL)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
LocalPrivileges->PrivilegeCount = TokenPrivilegeCount + 1;
|
|
for (i = 0; i < TokenPrivilegeCount; i++)
|
|
{
|
|
LocalPrivileges->Privileges[i].Luid = (*TokenPrivileges)->Privileges[i].Luid;
|
|
LocalPrivileges->Privileges[i].Attributes = (*TokenPrivileges)->Privileges[i].Attributes;
|
|
}
|
|
|
|
LocalPrivileges->Privileges[TokenPrivilegeCount].Luid = Privilege->Luid;
|
|
LocalPrivileges->Privileges[TokenPrivilegeCount].Attributes = Privilege->Attributes;
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, *TokenPrivileges);
|
|
}
|
|
|
|
*TokenPrivileges = LocalPrivileges;
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
LsapSetPrivileges(
|
|
IN PVOID TokenInformation,
|
|
IN LSA_TOKEN_INFORMATION_TYPE TokenInformationType)
|
|
{
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1;
|
|
LSAPR_HANDLE PolicyHandle = NULL;
|
|
LSAPR_HANDLE AccountHandle = NULL;
|
|
PLSAPR_PRIVILEGE_SET Privileges = NULL;
|
|
ULONG i, j;
|
|
NTSTATUS Status;
|
|
|
|
if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
Status = LsarOpenPolicy(NULL,
|
|
NULL,
|
|
0,
|
|
&PolicyHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
return Status;
|
|
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
{
|
|
Status = LsarOpenAccount(PolicyHandle,
|
|
TokenInfo1->Groups->Groups[i].Sid,
|
|
ACCOUNT_VIEW,
|
|
&AccountHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
continue;
|
|
|
|
Status = LsarEnumeratePrivilegesAccount(AccountHandle,
|
|
&Privileges);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
for (j = 0; j < Privileges->PrivilegeCount; j++)
|
|
{
|
|
Status = LsapAddPrivilegeToTokenPrivileges(&TokenInfo1->Privileges,
|
|
&(Privileges->Privilege[j]));
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* We failed, clean everything and return */
|
|
LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
|
|
LsarClose(&AccountHandle);
|
|
LsarClose(&PolicyHandle);
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
LsaIFree_LSAPR_PRIVILEGE_SET(Privileges);
|
|
Privileges = NULL;
|
|
}
|
|
|
|
LsarClose(&AccountHandle);
|
|
}
|
|
|
|
LsarClose(&PolicyHandle);
|
|
|
|
if (TokenInfo1->Privileges != NULL)
|
|
{
|
|
for (i = 0; i < TokenInfo1->Privileges->PrivilegeCount; i++)
|
|
{
|
|
if (RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeChangeNotifyPrivilege) ||
|
|
RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeCreateGlobalPrivilege) ||
|
|
RtlEqualLuid(&TokenInfo1->Privileges->Privileges[i].Luid, &SeImpersonatePrivilege))
|
|
{
|
|
TokenInfo1->Privileges->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
LsapLogonUser(PLSA_API_MSG RequestMsg,
|
|
PLSAP_LOGON_CONTEXT LogonContext)
|
|
{
|
|
PAUTH_PACKAGE Package;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
SECURITY_QUALITY_OF_SERVICE Qos;
|
|
LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
|
|
PVOID TokenInformation = NULL;
|
|
PLSA_TOKEN_INFORMATION_NULL TokenInfo0 = NULL;
|
|
PLSA_TOKEN_INFORMATION_V1 TokenInfo1 = NULL;
|
|
PUNICODE_STRING AccountName = NULL;
|
|
PUNICODE_STRING AuthenticatingAuthority = NULL;
|
|
PUNICODE_STRING MachineName = NULL;
|
|
PVOID LocalAuthInfo = NULL;
|
|
PTOKEN_GROUPS LocalGroups = NULL;
|
|
HANDLE TokenHandle = NULL;
|
|
ULONG i;
|
|
ULONG PackageId;
|
|
SECURITY_LOGON_TYPE LogonType;
|
|
NTSTATUS Status;
|
|
|
|
PUNICODE_STRING UserName = NULL;
|
|
PUNICODE_STRING LogonDomainName = NULL;
|
|
// UNICODE_STRING LogonServer;
|
|
|
|
|
|
TRACE("LsapLogonUser(%p %p)\n", RequestMsg, LogonContext);
|
|
|
|
PackageId = RequestMsg->LogonUser.Request.AuthenticationPackage;
|
|
LogonType = RequestMsg->LogonUser.Request.LogonType;
|
|
|
|
/* Get the right authentication package */
|
|
Package = LsapGetAuthenticationPackage(PackageId);
|
|
if (Package == NULL)
|
|
{
|
|
ERR("LsapGetAuthenticationPackage() failed to find a package\n");
|
|
return STATUS_NO_SUCH_PACKAGE;
|
|
}
|
|
|
|
if (RequestMsg->LogonUser.Request.AuthenticationInformationLength > 0)
|
|
{
|
|
/* Allocate the local authentication info buffer */
|
|
LocalAuthInfo = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformationLength);
|
|
if (LocalAuthInfo == NULL)
|
|
{
|
|
ERR("RtlAllocateHeap() failed\n");
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* Read the authentication info from the callers address space */
|
|
Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformation,
|
|
LocalAuthInfo,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtReadVirtualMemory() failed (Status 0x%08lx)\n", Status);
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
if (RequestMsg->LogonUser.Request.LocalGroupsCount > 0)
|
|
{
|
|
Status = LsapCopyLocalGroups(LogonContext,
|
|
RequestMsg->LogonUser.Request.LocalGroups,
|
|
RequestMsg->LogonUser.Request.LocalGroupsCount,
|
|
&LocalGroups);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapCopyLocalGroups failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
|
|
}
|
|
|
|
if (Package->LsaApLogonUserEx2 != NULL)
|
|
{
|
|
Status = Package->LsaApLogonUserEx2((PLSA_CLIENT_REQUEST)LogonContext,
|
|
RequestMsg->LogonUser.Request.LogonType,
|
|
LocalAuthInfo,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformation,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
|
|
&RequestMsg->LogonUser.Reply.ProfileBuffer,
|
|
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
|
|
&RequestMsg->LogonUser.Reply.LogonId,
|
|
&RequestMsg->LogonUser.Reply.SubStatus,
|
|
&TokenInformationType,
|
|
&TokenInformation,
|
|
&AccountName,
|
|
&AuthenticatingAuthority,
|
|
&MachineName,
|
|
NULL, /* FIXME: PSECPKG_PRIMARY_CRED PrimaryCredentials */
|
|
NULL); /* FIXME: PSECPKG_SUPPLEMENTAL_CRED_ARRAY *SupplementalCredentials */
|
|
}
|
|
else if (Package->LsaApLogonUserEx != NULL)
|
|
{
|
|
Status = Package->LsaApLogonUserEx((PLSA_CLIENT_REQUEST)LogonContext,
|
|
RequestMsg->LogonUser.Request.LogonType,
|
|
LocalAuthInfo,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformation,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
|
|
&RequestMsg->LogonUser.Reply.ProfileBuffer,
|
|
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
|
|
&RequestMsg->LogonUser.Reply.LogonId,
|
|
&RequestMsg->LogonUser.Reply.SubStatus,
|
|
&TokenInformationType,
|
|
&TokenInformation,
|
|
&AccountName,
|
|
&AuthenticatingAuthority,
|
|
&MachineName);
|
|
}
|
|
else
|
|
{
|
|
Status = Package->LsaApLogonUser((PLSA_CLIENT_REQUEST)LogonContext,
|
|
RequestMsg->LogonUser.Request.LogonType,
|
|
LocalAuthInfo,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformation,
|
|
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
|
|
&RequestMsg->LogonUser.Reply.ProfileBuffer,
|
|
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
|
|
&RequestMsg->LogonUser.Reply.LogonId,
|
|
&RequestMsg->LogonUser.Reply.SubStatus,
|
|
&TokenInformationType,
|
|
&TokenInformation,
|
|
&AccountName,
|
|
&AuthenticatingAuthority);
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
if (LocalGroups->GroupCount > 0)
|
|
{
|
|
/* Add local groups to the token information */
|
|
Status = LsapAddLocalGroups(TokenInformation,
|
|
TokenInformationType,
|
|
LocalGroups);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapAddLocalGroupsToTokenInfo() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
Status = LsapAddDefaultGroups(TokenInformation,
|
|
TokenInformationType,
|
|
LogonType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapAddDefaultGroups() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapAddSamGroups(TokenInformation,
|
|
TokenInformationType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapAddSamGroups() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapSetTokenOwner(TokenInformation,
|
|
TokenInformationType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapSetTokenOwner() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapAddTokenDefaultDacl(TokenInformation,
|
|
TokenInformationType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapAddTokenDefaultDacl() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
Status = LsapSetPrivileges(TokenInformation,
|
|
TokenInformationType);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapSetPrivileges() failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
if (TokenInformationType == LsaTokenInformationNull)
|
|
{
|
|
TOKEN_USER TokenUser;
|
|
TOKEN_PRIMARY_GROUP TokenPrimaryGroup;
|
|
TOKEN_GROUPS NoGroups = {0};
|
|
TOKEN_PRIVILEGES NoPrivileges = {0};
|
|
|
|
TokenInfo0 = (PLSA_TOKEN_INFORMATION_NULL)TokenInformation;
|
|
|
|
TokenUser.User.Sid = LsapWorldSid;
|
|
TokenUser.User.Attributes = 0;
|
|
TokenPrimaryGroup.PrimaryGroup = LsapWorldSid;
|
|
|
|
Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
Qos.ImpersonationLevel = SecurityImpersonation;
|
|
Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
|
Qos.EffectiveOnly = TRUE;
|
|
|
|
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
|
ObjectAttributes.RootDirectory = NULL;
|
|
ObjectAttributes.ObjectName = NULL;
|
|
ObjectAttributes.Attributes = 0;
|
|
ObjectAttributes.SecurityDescriptor = NULL;
|
|
ObjectAttributes.SecurityQualityOfService = &Qos;
|
|
|
|
/* Create the logon token */
|
|
Status = NtCreateToken(&TokenHandle,
|
|
TOKEN_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
TokenImpersonation,
|
|
&RequestMsg->LogonUser.Reply.LogonId,
|
|
&TokenInfo0->ExpirationTime,
|
|
&TokenUser,
|
|
&NoGroups,
|
|
&NoPrivileges,
|
|
NULL,
|
|
&TokenPrimaryGroup,
|
|
NULL,
|
|
&RequestMsg->LogonUser.Request.SourceContext);
|
|
}
|
|
else if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TOKEN_PRIVILEGES NoPrivileges = {0};
|
|
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
Qos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
Qos.ImpersonationLevel = SecurityImpersonation;
|
|
Qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
|
|
Qos.EffectiveOnly = FALSE;
|
|
|
|
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
|
|
ObjectAttributes.RootDirectory = NULL;
|
|
ObjectAttributes.ObjectName = NULL;
|
|
ObjectAttributes.Attributes = 0;
|
|
ObjectAttributes.SecurityDescriptor = NULL;
|
|
ObjectAttributes.SecurityQualityOfService = &Qos;
|
|
|
|
/* Create the logon token */
|
|
Status = NtCreateToken(&TokenHandle,
|
|
TOKEN_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
(RequestMsg->LogonUser.Request.LogonType == Network) ? TokenImpersonation : TokenPrimary,
|
|
&RequestMsg->LogonUser.Reply.LogonId,
|
|
&TokenInfo1->ExpirationTime,
|
|
&TokenInfo1->User,
|
|
TokenInfo1->Groups,
|
|
TokenInfo1->Privileges ? TokenInfo1->Privileges : &NoPrivileges,
|
|
&TokenInfo1->Owner,
|
|
&TokenInfo1->PrimaryGroup,
|
|
&TokenInfo1->DefaultDacl,
|
|
&RequestMsg->LogonUser.Request.SourceContext);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtCreateToken failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto done;
|
|
}
|
|
|
|
if (LogonType == Interactive ||
|
|
LogonType == Batch ||
|
|
LogonType == Service)
|
|
{
|
|
UserName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->UserName;
|
|
LogonDomainName = &((PMSV1_0_INTERACTIVE_LOGON)LocalAuthInfo)->LogonDomainName;
|
|
}
|
|
else
|
|
{
|
|
FIXME("LogonType %lu is not supported yet!\n", LogonType);
|
|
}
|
|
|
|
Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId,
|
|
LogonType,
|
|
UserName,
|
|
LogonDomainName,
|
|
TokenInfo1->User.User.Sid);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/*
|
|
* Duplicate the token handle into the client process.
|
|
* This must be the last step because we cannot
|
|
* close the duplicated token handle in case something fails.
|
|
*/
|
|
Status = NtDuplicateObject(NtCurrentProcess(),
|
|
TokenHandle,
|
|
LogonContext->ClientProcessHandle,
|
|
&RequestMsg->LogonUser.Reply.Token,
|
|
0,
|
|
0,
|
|
DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ERR("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Notify the authentification package of the failure */
|
|
Package->LsaApLogonTerminated(&RequestMsg->LogonUser.Reply.LogonId);
|
|
|
|
/* Delete the logon session */
|
|
LsapDeleteLogonSession(&RequestMsg->LogonUser.Reply.LogonId);
|
|
|
|
/* Release the profile buffer */
|
|
LsapFreeClientBuffer((PLSA_CLIENT_REQUEST)LogonContext,
|
|
RequestMsg->LogonUser.Reply.ProfileBuffer);
|
|
RequestMsg->LogonUser.Reply.ProfileBuffer = NULL;
|
|
}
|
|
|
|
if (TokenHandle != NULL)
|
|
NtClose(TokenHandle);
|
|
|
|
/* Free the local groups */
|
|
if (LocalGroups != NULL)
|
|
{
|
|
for (i = 0; i < LocalGroups->GroupCount; i++)
|
|
{
|
|
if (LocalGroups->Groups[i].Sid != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
|
|
}
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
|
|
}
|
|
|
|
/* Free the local authentication info buffer */
|
|
if (LocalAuthInfo != NULL)
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, LocalAuthInfo);
|
|
|
|
/* Free the token information */
|
|
if (TokenInformation != NULL)
|
|
{
|
|
if (TokenInformationType == LsaTokenInformationNull)
|
|
{
|
|
TokenInfo0 = (PLSA_TOKEN_INFORMATION_NULL)TokenInformation;
|
|
|
|
if (TokenInfo0 != NULL)
|
|
{
|
|
if (TokenInfo0->Groups != NULL)
|
|
{
|
|
for (i = 0; i < TokenInfo0->Groups->GroupCount; i++)
|
|
{
|
|
if (TokenInfo0->Groups->Groups[i].Sid != NULL)
|
|
LsapFreeHeap(TokenInfo0->Groups->Groups[i].Sid);
|
|
}
|
|
|
|
LsapFreeHeap(TokenInfo0->Groups);
|
|
}
|
|
|
|
LsapFreeHeap(TokenInfo0);
|
|
}
|
|
}
|
|
else if (TokenInformationType == LsaTokenInformationV1)
|
|
{
|
|
TokenInfo1 = (PLSA_TOKEN_INFORMATION_V1)TokenInformation;
|
|
|
|
if (TokenInfo1 != NULL)
|
|
{
|
|
if (TokenInfo1->User.User.Sid != NULL)
|
|
LsapFreeHeap(TokenInfo1->User.User.Sid);
|
|
|
|
if (TokenInfo1->Groups != NULL)
|
|
{
|
|
for (i = 0; i < TokenInfo1->Groups->GroupCount; i++)
|
|
{
|
|
if (TokenInfo1->Groups->Groups[i].Sid != NULL)
|
|
LsapFreeHeap(TokenInfo1->Groups->Groups[i].Sid);
|
|
}
|
|
|
|
LsapFreeHeap(TokenInfo1->Groups);
|
|
}
|
|
|
|
if (TokenInfo1->PrimaryGroup.PrimaryGroup != NULL)
|
|
LsapFreeHeap(TokenInfo1->PrimaryGroup.PrimaryGroup);
|
|
|
|
if (TokenInfo1->Privileges != NULL)
|
|
LsapFreeHeap(TokenInfo1->Privileges);
|
|
|
|
if (TokenInfo1->Owner.Owner != NULL)
|
|
LsapFreeHeap(TokenInfo1->Owner.Owner);
|
|
|
|
if (TokenInfo1->DefaultDacl.DefaultDacl != NULL)
|
|
LsapFreeHeap(TokenInfo1->DefaultDacl.DefaultDacl);
|
|
|
|
LsapFreeHeap(TokenInfo1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
|
|
}
|
|
}
|
|
|
|
/* Free the account name */
|
|
if (AccountName != NULL)
|
|
{
|
|
if (AccountName->Buffer != NULL)
|
|
LsapFreeHeap(AccountName->Buffer);
|
|
|
|
LsapFreeHeap(AccountName);
|
|
}
|
|
|
|
/* Free the authentication authority */
|
|
if (AuthenticatingAuthority != NULL)
|
|
{
|
|
if (AuthenticatingAuthority != NULL)
|
|
LsapFreeHeap(AuthenticatingAuthority->Buffer);
|
|
|
|
LsapFreeHeap(AuthenticatingAuthority);
|
|
}
|
|
|
|
/* Free the machine name */
|
|
if (MachineName != NULL)
|
|
{
|
|
if (MachineName->Buffer != NULL)
|
|
LsapFreeHeap(MachineName->Buffer);
|
|
|
|
LsapFreeHeap(MachineName);
|
|
}
|
|
|
|
TRACE("LsapLogonUser done (Status 0x%08lx)\n", Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/* EOF */
|