* COPYRIGHT: Copyright 2013 Eric Kohl
*/
-/* INCLUDES ****************************************************************/
-
#include "lsasrv.h"
-WINE_DEFAULT_DEBUG_CHANNEL(lsasrv);
-
typedef enum _LSA_TOKEN_INFORMATION_TYPE
{
LsaTokenInformationNull,
LsaTokenInformationV1
} LSA_TOKEN_INFORMATION_TYPE, *PLSA_TOKEN_INFORMATION_TYPE;
+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 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
{
- PVOID /*PLSA_CREATE_LOGON_SESSION */ CreateLogonSession;
- PVOID /*PLSA_DELETE_LOGON_SESSION */ DeleteLogonSession;
+ PLSA_CREATE_LOGON_SESSION CreateLogonSession;
+ PLSA_DELETE_LOGON_SESSION DeleteLogonSession;
PVOID /*PLSA_ADD_CREDENTIAL */ AddCredential;
PVOID /*PLSA_GET_CREDENTIALS */ GetCredentials;
PVOID /*PLSA_DELETE_CREDENTIAL */ DeleteCredential;
PLSA_FREE_LSA_HEAP FreeLsaHeap;
PLSA_ALLOCATE_CLIENT_BUFFER AllocateClientBuffer;
PLSA_FREE_CLIENT_BUFFER FreeClientBuffer;
- PVOID /*PLSA_COPY_TO_CLIENT_BUFFER */ CopyToClientBuffer;
- PVOID /*PLSA_COPY_FROM_CLIENT_BUFFER */ CopyFromClientBuffer;
+ PLSA_COPY_TO_CLIENT_BUFFER CopyToClientBuffer;
+ PLSA_COPY_FROM_CLIENT_BUFFER CopyFromClientBuffer;
} LSA_DISPATCH_TABLE, *PLSA_DISPATCH_TABLE;
TRACE("Package Name: %s\n", Package->Name->Buffer);
Package->Id = *Id;
- *Id++;
+ (*Id)++;
InsertTailList(&PackageListHead, &Package->Entry);
IN ULONG LengthRequired,
OUT PVOID *ClientBaseAddress)
{
- FIXME("() stub\n");
- return STATUS_NOT_IMPLEMENTED;
+ PLSAP_LOGON_CONTEXT LogonContext;
+ ULONG Length;
+
+ *ClientBaseAddress = NULL;
+
+ LogonContext = (PLSAP_LOGON_CONTEXT)ClientRequest;
+
+ Length = LengthRequired;
+ return NtAllocateVirtualMemory(LogonContext->ClientProcessHandle,
+ ClientBaseAddress,
+ 0,
+ &Length,
+ MEM_COMMIT,
+ PAGE_READWRITE);
}
LsapFreeClientBuffer(IN PLSA_CLIENT_REQUEST ClientRequest,
IN PVOID ClientBaseAddress)
{
- FIXME("() stub\n");
- return STATUS_NOT_IMPLEMENTED;
+ PLSAP_LOGON_CONTEXT LogonContext;
+ ULONG 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);
}
PackageId = 0;
/* Initialize the dispatch table */
- DispatchTable.CreateLogonSession = NULL;
- DispatchTable.DeleteLogonSession = NULL;
+ DispatchTable.CreateLogonSession = &LsapCreateLogonSession;
+ DispatchTable.DeleteLogonSession = &LsapDeleteLogonSession;
DispatchTable.AddCredential = NULL;
DispatchTable.GetCredentials = NULL;
DispatchTable.DeleteCredential = NULL;
DispatchTable.FreeLsaHeap = &LsapFreeHeap;
DispatchTable.AllocateClientBuffer = &LsapAllocateClientBuffer;
DispatchTable.FreeClientBuffer = &LsapFreeClientBuffer;
- DispatchTable.CopyToClientBuffer = NULL;
- DispatchTable.CopyFromClientBuffer = NULL;
+ DispatchTable.CopyToClientBuffer = &LsapCopyToClientBuffer;
+ DispatchTable.CopyFromClientBuffer = &LsapCopyFromClientBuffer;
/* Add registered authentication packages */
Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
&PackageId,
NULL);
-
- return STATUS_SUCCESS;
+ return Status;
}
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)
{
return STATUS_NO_SUCH_PACKAGE;
}
- Status = Package->LsaApCallPackage(NULL, /* FIXME: PLSA_CLIENT_REQUEST ClientRequest */
+ 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;
+ }
+ }
+
+ Status = Package->LsaApCallPackage((PLSA_CLIENT_REQUEST)LogonContext,
+ LocalBuffer,
RequestMsg->CallAuthenticationPackage.Request.ProtocolSubmitBuffer,
- NULL, /* FIXME: PVOID ClientBufferBase */
RequestMsg->CallAuthenticationPackage.Request.SubmitBufferLength,
&RequestMsg->CallAuthenticationPackage.Reply.ProtocolReturnBuffer,
&RequestMsg->CallAuthenticationPackage.Reply.ReturnBufferLength,
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 Sid;
+ ULONG SidLength;
+ ULONG CopiedSids = 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++)
+ {
+ Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
+ LocalGroups->Groups[i].Sid,
+ SidHeader,
+ SidHeaderLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ SidLength = RtlLengthSid(SidHeader);
+ TRACE("Sid %lu: Length %lu\n", i, SidLength);
+
+ Sid = RtlAllocateHeap(RtlGetProcessHeap(),
+ HEAP_ZERO_MEMORY,
+ SidLength);
+ if (SidHeader == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto done;
+ }
+
+ Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
+ LocalGroups->Groups[i].Sid,
+ Sid,
+ SidLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ RtlFreeHeap(RtlGetProcessHeap(), 0, Sid);
+ goto done;
+ }
+
+ LocalGroups->Groups[i].Sid = Sid;
+ CopiedSids++;
+ }
+
+ *TokenGroups = LocalGroups;
+
+done:
+ if (SidHeader != NULL)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, SidHeader);
+
+ if (!NT_SUCCESS(Status))
+ {
+ if (LocalGroups != NULL)
+ {
+ for (i = 0; i < CopiedSids; i++)
+ RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups->Groups[i].Sid);
+
+ RtlFreeHeap(RtlGetProcessHeap(), 0, LocalGroups);
+ }
+ }
+
return Status;
}
PLSAP_LOGON_CONTEXT LogonContext)
{
PAUTH_PACKAGE Package;
- ULONG PackageId;
- NTSTATUS Status;
-
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ SECURITY_QUALITY_OF_SERVICE Qos;
LSA_TOKEN_INFORMATION_TYPE TokenInformationType;
PVOID TokenInformation = 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;
+ NTSTATUS Status;
TRACE("(%p %p)\n", RequestMsg, LogonContext);
PackageId = RequestMsg->LogonUser.Request.AuthenticationPackage;
+ /* Get the right authentication package */
Package = LsapGetAuthenticationPackage(PackageId);
if (Package == NULL)
{
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)
+ {
+ TRACE("RtlAllocateHeap() failed\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Read the authentication info from the callers adress space */
+ Status = NtReadVirtualMemory(LogonContext->ClientProcessHandle,
+ RequestMsg->LogonUser.Request.AuthenticationInformation,
+ LocalAuthInfo,
+ RequestMsg->LogonUser.Request.AuthenticationInformationLength,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("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))
+ goto done;
+
+ TRACE("GroupCount: %lu\n", LocalGroups->GroupCount);
+ }
+
if (Package->LsaApLogonUserEx2 != NULL)
{
- Status = Package->LsaApLogonUserEx2(NULL, /* FIXME: PLSA_CLIENT_REQUEST ClientRequest */
+ Status = Package->LsaApLogonUserEx2((PLSA_CLIENT_REQUEST)LogonContext,
RequestMsg->LogonUser.Request.LogonType,
+ LocalAuthInfo,
RequestMsg->LogonUser.Request.AuthenticationInformation,
- NULL, /* FIXME: PVOID ClientBufferBase*/
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
&RequestMsg->LogonUser.Reply.ProfileBuffer,
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
}
else if (Package->LsaApLogonUserEx != NULL)
{
- Status = Package->LsaApLogonUserEx(NULL, /* FIXME: PLSA_CLIENT_REQUEST ClientRequest */
+ Status = Package->LsaApLogonUserEx((PLSA_CLIENT_REQUEST)LogonContext,
RequestMsg->LogonUser.Request.LogonType,
+ LocalAuthInfo,
RequestMsg->LogonUser.Request.AuthenticationInformation,
- NULL, /* FIXME: PVOID ClientBufferBase*/
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
&RequestMsg->LogonUser.Reply.ProfileBuffer,
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
}
else
{
- Status = Package->LsaApLogonUser(NULL, /* FIXME: PLSA_CLIENT_REQUEST ClientRequest */
+ Status = Package->LsaApLogonUser((PLSA_CLIENT_REQUEST)LogonContext,
RequestMsg->LogonUser.Request.LogonType,
+ LocalAuthInfo,
RequestMsg->LogonUser.Request.AuthenticationInformation,
- NULL, /* FIXME: PVOID ClientBufferBase*/
RequestMsg->LogonUser.Request.AuthenticationInformationLength,
&RequestMsg->LogonUser.Reply.ProfileBuffer,
&RequestMsg->LogonUser.Reply.ProfileBufferLength,
&AuthenticatingAuthority);
}
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("LsaApLogonUser/Ex/2 failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
- if (TokenInformation != NULL)
+ if (TokenInformationType == LsaTokenInformationV1)
+ {
+ 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,
+ TokenPrimary,
+ &RequestMsg->LogonUser.Reply.LogonId,
+ &TokenInfo1->ExpirationTime,
+ &TokenInfo1->User,
+ TokenInfo1->Groups,
+ TokenInfo1->Privileges,
+ &TokenInfo1->Owner,
+ &TokenInfo1->PrimaryGroup,
+ &TokenInfo1->DefaultDacl,
+ &RequestMsg->LogonUser.Request.SourceContext);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("NtCreateToken failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+ }
+ else
{
+ FIXME("TokenInformationType %d is not supported!\n", TokenInformationType);
+ Status = STATUS_NOT_IMPLEMENTED;
+ goto done;
+ }
+ /* Duplicate the token handle into the client process */
+ 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))
+ {
+ TRACE("NtDuplicateObject failed (Status 0x%08lx)\n", Status);
+ goto done;
}
- if (AuthenticatingAuthority != NULL)
+ TokenHandle = NULL;
+
+ Status = LsapSetLogonSessionData(&RequestMsg->LogonUser.Reply.LogonId);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("LsapSetLogonSessionData failed (Status 0x%08lx)\n", Status);
+ goto done;
+ }
+
+done:
+ if (!NT_SUCCESS(Status))
{
+ if (TokenHandle != NULL)
+ NtClose(TokenHandle);
+ }
+ /* Free the local groups */
+ if (LocalGroups != NULL)
+ {
+ for (i = 0; i < LocalGroups->GroupCount; i++)
+ 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 == 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;
}