[NTOSKRNL][LSASRV]
authorEric Kohl <eric.kohl@reactos.org>
Sun, 25 Oct 2015 14:33:27 +0000 (14:33 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 25 Oct 2015 14:33:27 +0000 (14:33 +0000)
- Add the SRM code from Timos kernel-fun branch.
- Move its lsasrv code to a separate file.
Thank you very much, Timo!

svn path=/trunk/; revision=69697

reactos/dll/win32/lsasrv/CMakeLists.txt
reactos/dll/win32/lsasrv/lsasrv.c
reactos/dll/win32/lsasrv/lsasrv.h
reactos/dll/win32/lsasrv/srm.c [new file with mode: 0644]
reactos/ntoskrnl/ex/init.c
reactos/ntoskrnl/include/internal/se.h
reactos/ntoskrnl/ntos.cmake
reactos/ntoskrnl/se/srm.c [new file with mode: 0644]

index e1b250a..6bde681 100644 (file)
@@ -22,6 +22,7 @@ list(APPEND SOURCE
     registry.c
     security.c
     session.c
+    srm.c
     utils.c
     lsasrv.h
     ${CMAKE_CURRENT_BINARY_DIR}/dssetup_s.c
index 045a745..a887ab1 100644 (file)
@@ -6,6 +6,8 @@
  * COPYRIGHT:   Copyright 2006-2009 Eric Kohl
  */
 
+/* INCLUDES ****************************************************************/
+
 #include "lsasrv.h"
 
 /* FUNCTIONS ***************************************************************/
@@ -140,6 +142,14 @@ LsapInitLsa(VOID)
     /* Initialize the well known SIDs */
     LsapInitSids();
 
+    /* Initialize the SRM server */
+    Status = LsapRmInitializeServer();
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmInitializeServer() failed (Status 0x%08lx)\n", Status);
+        return Status;
+    }
+
     /* Initialize the LSA database */
     LsapInitDatabase();
 
index 1fefc9b..0a1ad31 100644 (file)
@@ -421,6 +421,10 @@ LsapEnumLogonSessions(IN OUT PLSA_API_MSG RequestMsg);
 NTSTATUS
 LsapGetLogonSessionData(IN OUT PLSA_API_MSG RequestMsg);
 
+/* srm.c */
+NTSTATUS
+LsapRmInitializeServer(VOID);
+
 /* utils.c */
 INT
 LsapLoadString(HINSTANCE hInstance,
diff --git a/reactos/dll/win32/lsasrv/srm.c b/reactos/dll/win32/lsasrv/srm.c
new file mode 100644 (file)
index 0000000..9eb9b23
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * COPYRIGHT:   See COPYING in the top level directory
+ * PROJECT:     Local Security Authority Server DLL
+ * FILE:        dll/win32/lsasrv/srm.c
+ * PURPOSE:     Security Reference Monitor Server
+ *
+ * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include "lsasrv.h"
+#include <ndk/ntndk.h>
+
+typedef struct _LSAP_RM_API_MESSAGE
+{
+    PORT_MESSAGE Header;
+    ULONG ApiNumber;
+    union
+    {
+        UCHAR Fill[PORT_MAXIMUM_MESSAGE_LENGTH - sizeof(PORT_MESSAGE)];
+        struct
+        {
+            ULONG Info1;
+        } WriteLog;
+
+    } u;
+} LSAP_RM_API_MESSAGE, *PLSAP_RM_API_MESSAGE;
+
+enum _LSAP_API_NUMBER
+{
+    LsapAdtWriteLogApi = 1,
+    LsapComponentTestApi,
+    LsapAsyncApi
+};
+
+/* GLOBALS *****************************************************************/
+
+HANDLE SeLsaCommandPort;
+HANDLE SeRmCommandPort;
+
+/* FUNCTIONS ***************************************************************/
+
+static
+VOID
+LsapComponentTest(
+    PLSAP_RM_API_MESSAGE Message)
+{
+    ERR("Security: LSA Component Test Command Received\n");
+}
+
+static
+VOID
+LsapAdtWriteLog(
+    PLSAP_RM_API_MESSAGE Message)
+{
+    ERR("LsapAdtWriteLog\n");
+}
+
+static
+VOID
+LsapAsync(
+    PLSAP_RM_API_MESSAGE Message)
+{
+    ERR("LsapAsync\n");
+}
+
+static
+DWORD
+WINAPI
+LsapRmServerThread(
+    PVOID StartContext)
+{
+    LSAP_RM_API_MESSAGE Message;
+    PPORT_MESSAGE ReplyMessage;
+    REMOTE_PORT_VIEW RemotePortView;
+    HANDLE MessagePort, DummyPortHandle;
+    NTSTATUS Status;
+
+    /* Initialize the port message */
+    Message.Header.u1.s1.TotalLength = sizeof(Message);
+    Message.Header.u1.s1.DataLength = 0;
+
+    /* Listen on the LSA command port */
+    Status = NtListenPort(SeLsaCommandPort, &Message.Header);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmServerThread - Port Listen failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Setup the Port View Structure */
+    RemotePortView.Length = sizeof(REMOTE_PORT_VIEW);
+    RemotePortView.ViewSize = 0;
+    RemotePortView.ViewBase = NULL;
+
+    /* Accept the connection */
+    Status = NtAcceptConnectPort(&MessagePort,
+                                 0,
+                                 &Message.Header,
+                                 TRUE,
+                                 NULL,
+                                 &RemotePortView);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmServerThread - Port Accept Connect failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Complete the connection */
+    Status = NtCompleteConnectPort(MessagePort);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmServerThread - Port Complete Connect failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* No reply yet */
+    ReplyMessage = NULL;
+
+    /* Start looping */
+    while (TRUE)
+    {
+        /* Wait for a message */
+        Status = NtReplyWaitReceivePort(MessagePort,
+                                        NULL,
+                                        ReplyMessage,
+                                        &Message.Header);
+        if (!NT_SUCCESS(Status))
+        {
+            ERR("LsapRmServerThread - Failed to get message: 0x%lx", Status);
+            ReplyMessage = NULL;
+            continue;
+        }
+
+        /* Check if this is a connection request */
+        if (Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
+        {
+            /* Reject connection request */
+            NtAcceptConnectPort(&DummyPortHandle,
+                                NULL,
+                                &Message.Header,
+                                FALSE,
+                                NULL,
+                                NULL);
+
+            /* Start over */
+            ReplyMessage = NULL;
+            continue;
+        }
+
+        /* Check if this is an actual request */
+        if (Message.Header.u2.s2.Type == LPC_REQUEST)
+        {
+            ReplyMessage = &Message.Header;
+
+            switch (Message.ApiNumber)
+            {
+                case LsapAdtWriteLogApi:
+                    LsapAdtWriteLog(&Message);
+                    break;
+
+                case LsapAsyncApi:
+                    LsapAsync(&Message);
+                    break;
+
+                case LsapComponentTestApi:
+                    LsapComponentTest(&Message);
+                    break;
+
+                default:
+                    ERR("LsapRmServerThread - invalid API number: 0x%lx\n",
+                        Message.ApiNumber);
+                    ReplyMessage = NULL;
+            }
+
+            continue;
+        }
+
+        ERR("LsapRmServerThread - unexpected message type: 0x%lx\n",
+            Message.Header.u2.s2.Type);
+
+        /* Start over */
+        ReplyMessage = NULL;
+    }
+}
+
+NTSTATUS
+LsapRmInitializeServer(VOID)
+{
+    UNICODE_STRING Name;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    SECURITY_QUALITY_OF_SERVICE SecurityQos;
+    HANDLE InitEvent;
+    HANDLE ThreadHandle;
+    DWORD ThreadId;
+    NTSTATUS Status;
+
+    /* Create the LSA command port */
+    RtlInitUnicodeString(&Name, L"\\SeLsaCommandPort");
+    InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
+    Status = NtCreatePort(&SeLsaCommandPort,
+                          &ObjectAttributes,
+                          0,
+                          PORT_MAXIMUM_MESSAGE_LENGTH,
+                          2 * PAGE_SIZE);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmInitializeServer - Port Create failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Open the LSA init event */
+    RtlInitUnicodeString(&Name, L"\\SeLsaInitEvent");
+    InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
+    Status = NtOpenEvent(&InitEvent, 2, &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmInitializeServer - Lsa Init Event Open failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Signal the kernel, that we are ready */
+    Status = NtSetEvent(InitEvent, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmInitializeServer - Set Init Event failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Setup the QoS structure */
+    SecurityQos.ImpersonationLevel = SecurityIdentification;
+    SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+    SecurityQos.EffectiveOnly = TRUE;
+
+    /* Connect to the kernel server */
+    RtlInitUnicodeString(&Name, L"\\SeRmCommandPort");
+    Status = NtConnectPort(&SeRmCommandPort,
+                           &Name,
+                           &SecurityQos,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("LsapRmInitializeServer - Connect to Rm Command Port failed 0x%lx\n", Status);
+        return Status;
+    }
+
+    /* Create the server thread */
+    ThreadHandle = CreateThread(NULL, 0, LsapRmServerThread, NULL, 0, &ThreadId);
+    if (ThreadHandle == NULL)
+    {
+        ERR("LsapRmInitializeServer - Create Thread  failed 0x%lx\n", Status);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Close the server thread handle */
+    CloseHandle(ThreadHandle);
+
+    return STATUS_SUCCESS;
+}
index 5db7a96..ed6e39e 100644 (file)
@@ -1950,6 +1950,9 @@ Phase1InitializationDiscard(IN PVOID Context)
     MmFreeLoaderBlock(LoaderBlock);
     LoaderBlock = Context = NULL;
 
+    /* Initialize the SRM in phase 1 */
+    if (!SeRmInitPhase1()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
+
     /* Update progress bar */
     InbvUpdateProgressBar(100);
 
index 1b737be..d71d16d 100644 (file)
@@ -267,6 +267,10 @@ BOOLEAN
 NTAPI
 SepInitSDs(VOID);
 
+BOOLEAN
+NTAPI
+SeRmInitPhase1(VOID);
+
 VOID
 NTAPI
 SeDeassignPrimaryToken(struct _EPROCESS *Process);
index d6dc35e..ebde0b1 100644 (file)
@@ -266,6 +266,7 @@ list(APPEND SOURCE
     ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sd.c
     ${REACTOS_SOURCE_DIR}/ntoskrnl/se/semgr.c
     ${REACTOS_SOURCE_DIR}/ntoskrnl/se/sid.c
+    ${REACTOS_SOURCE_DIR}/ntoskrnl/se/srm.c
     ${REACTOS_SOURCE_DIR}/ntoskrnl/se/token.c
     ${REACTOS_SOURCE_DIR}/ntoskrnl/vf/driver.c
     ${REACTOS_SOURCE_DIR}/ntoskrnl/wmi/guidobj.c
diff --git a/reactos/ntoskrnl/se/srm.c b/reactos/ntoskrnl/se/srm.c
new file mode 100644 (file)
index 0000000..bd680ba
--- /dev/null
@@ -0,0 +1,623 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/se/srm.c
+ * PURPOSE:         Security Reference Monitor Server
+ *
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+extern LUID SeSystemAuthenticationId;
+extern LUID SeAnonymousAuthenticationId;
+
+/* PRIVATE DEFINITIONS ********************************************************/
+
+#define SEP_LOGON_SESSION_TAG 'sLeS'
+
+enum _RM_API_NUMBER
+{
+    RmAuditSetCommand = 1,
+    RmCreateLogonSession = 2,
+    RmDeleteLogonSession = 3
+};
+
+typedef struct _SEP_RM_API_MESSAGE
+{
+    PORT_MESSAGE Header;
+    ULONG ApiNumber;
+    union
+    {
+        UCHAR Fill[PORT_MAXIMUM_MESSAGE_LENGTH - sizeof(PORT_MESSAGE)];
+        NTSTATUS ResultStatus;
+        struct
+        {
+            BOOLEAN Enabled;
+            ULONG Flags[9];
+        } SetAuditEvent;
+        LUID LogonLuid;
+    } u;
+} SEP_RM_API_MESSAGE, *PSEP_RM_API_MESSAGE;
+
+typedef struct _SEP_LOGON_SESSION_REFERENCES
+{
+    struct _SEP_LOGON_SESSION_REFERENCES *Next;
+    LUID LogonId;
+    ULONG ReferenceCount;
+    ULONG Flags;
+    PDEVICE_MAP pDeviceMap;
+    LIST_ENTRY TokenList;
+} SEP_LOGON_SESSION_REFERENCES, *PSEP_LOGON_SESSION_REFERENCES;
+
+VOID
+NTAPI
+SepRmCommandServerThread(
+    PVOID StartContext);
+
+static
+NTSTATUS
+SepRmCreateLogonSession(
+    PLUID LogonLuid);
+
+
+/* GLOBALS ********************************************************************/
+
+HANDLE SeRmCommandPort;
+HANDLE SeLsaInitEvent;
+
+PVOID SepCommandPortViewBase;
+PVOID SepCommandPortViewRemoteBase;
+ULONG_PTR SepCommandPortViewBaseOffset;
+
+static HANDLE SepRmCommandMessagePort;
+
+BOOLEAN SepAdtAuditingEnabled;
+ULONG SepAdtMinListLength = 0x2000;
+ULONG SepAdtMaxListLength = 0x3000;
+
+#define POLICY_AUDIT_EVENT_TYPE_COUNT 9 // (AuditCategoryAccountLogon - AuditCategorySystem + 1)
+UCHAR SeAuditingState[POLICY_AUDIT_EVENT_TYPE_COUNT];
+
+KGUARDED_MUTEX SepRmDbLock;
+PSEP_LOGON_SESSION_REFERENCES SepLogonSessions;
+
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+NTSTATUS
+NTAPI
+SepRegQueryHelper(
+    PCWSTR KeyName,
+    PCWSTR ValueName,
+    ULONG ValueType,
+    ULONG DataLength,
+    PVOID ValueData)
+{
+    UNICODE_STRING ValueNameString;
+    UNICODE_STRING KeyNameString;
+    ULONG ResultLength;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE KeyHandle = NULL;
+    struct
+    {
+        KEY_VALUE_PARTIAL_INFORMATION Partial;
+        UCHAR Buffer[64];
+    } KeyValueInformation;
+    NTSTATUS Status, CloseStatus;
+    PAGED_CODE();
+
+    RtlInitUnicodeString(&KeyNameString, KeyName);
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyNameString,
+                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+
+    Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    RtlInitUnicodeString(&ValueNameString, ValueName);
+    Status = ZwQueryValueKey(KeyHandle,
+                             &ValueNameString,
+                             KeyValuePartialInformation,
+                             &KeyValueInformation.Partial,
+                             sizeof(KeyValueInformation),
+                             &ResultLength);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Cleanup;
+    }
+
+    if ((KeyValueInformation.Partial.Type != ValueType) ||
+        (KeyValueInformation.Partial.DataLength != DataLength))
+    {
+        Status = STATUS_OBJECT_TYPE_MISMATCH;
+        goto Cleanup;
+    }
+
+
+    if (ValueType == REG_BINARY)
+    {
+        RtlCopyMemory(ValueData, KeyValueInformation.Partial.Data, DataLength);
+    }
+    else if (ValueType == REG_DWORD)
+    {
+        *(PULONG)ValueData = *(PULONG)KeyValueInformation.Partial.Data;
+    }
+    else
+    {
+        Status = STATUS_INVALID_PARAMETER;
+    }
+
+Cleanup:
+    CloseStatus = ZwClose(KeyHandle);
+    ASSERT(NT_SUCCESS( CloseStatus ));
+
+    return Status;
+}
+
+
+BOOLEAN
+NTAPI
+SeRmInitPhase1(VOID)
+{
+    UNICODE_STRING Name;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE ThreadHandle;
+    NTSTATUS Status;
+
+    // Windows does this in SeRmInitPhase0, but it should not matter
+    KeInitializeGuardedMutex(&SepRmDbLock);
+
+    Status = SepRmCreateLogonSession(&SeSystemAuthenticationId);
+    if (!NT_VERIFY(NT_SUCCESS(Status)))
+    {
+        return FALSE;
+    }
+
+    Status = SepRmCreateLogonSession(&SeAnonymousAuthenticationId);
+    if (!NT_VERIFY(NT_SUCCESS(Status)))
+    {
+        return FALSE;
+    }
+
+    /* Create the SeRm command port */
+    RtlInitUnicodeString(&Name, L"\\SeRmCommandPort");
+    InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
+    Status = ZwCreatePort(&SeRmCommandPort,
+                          &ObjectAttributes,
+                          sizeof(ULONG),
+                          PORT_MAXIMUM_MESSAGE_LENGTH,
+                          2 * PAGE_SIZE);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security: Rm Create Command Port failed 0x%lx\n", Status);
+        return FALSE;
+    }
+
+    /* Create SeLsaInitEvent */
+    RtlInitUnicodeString(&Name, L"\\SeLsaInitEvent");
+    InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
+    Status = ZwCreateEvent(&SeLsaInitEvent,
+                           GENERIC_WRITE,
+                           &ObjectAttributes,
+                           NotificationEvent,
+                           FALSE);
+    if (!NT_VERIFY((NT_SUCCESS(Status))))
+    {
+        DPRINT1("Security: LSA init event creation failed.0x%xl\n", Status);
+        return FALSE;
+    }
+
+    /* Create the SeRm server thread */
+    Status = PsCreateSystemThread(&ThreadHandle,
+                                  THREAD_ALL_ACCESS,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  SepRmCommandServerThread,
+                                  NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security: Rm Server Thread creation failed 0x%lx\n", Status);
+        return FALSE;
+    }
+
+    ObCloseHandle(ThreadHandle, KernelMode);
+
+    return TRUE;
+}
+
+static
+VOID
+SepAdtInitializeBounds(VOID)
+{
+    struct
+    {
+        ULONG MaxLength;
+        ULONG MinLength;
+    } ListBounds;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    Status = SepRegQueryHelper(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa",
+                               L"Bounds",
+                               REG_BINARY,
+                               sizeof(ListBounds),
+                               &ListBounds);
+    if (!NT_SUCCESS(Status))
+    {
+        /* No registry values, so keep hardcoded defaults */
+        return;
+    }
+
+    /* Check if the bounds are valid */
+    if ((ListBounds.MaxLength < ListBounds.MinLength) ||
+        (ListBounds.MinLength < 16) ||
+        (ListBounds.MaxLength - ListBounds.MinLength < 16))
+    {
+        DPRINT1("ListBounds are invalid: %u, %u\n",
+                ListBounds.MinLength, ListBounds.MaxLength);
+        return;
+    }
+
+    /* Set the new bounds globally */
+    SepAdtMinListLength = ListBounds.MinLength;
+    SepAdtMaxListLength = ListBounds.MaxLength;
+}
+
+
+static
+NTSTATUS
+SepRmSetAuditEvent(
+    PSEP_RM_API_MESSAGE Message)
+{
+    ULONG i;
+    PAGED_CODE();
+
+    /* First re-initialize the bounds from the registry */
+    SepAdtInitializeBounds();
+
+    /* Make sure we have the right message and clear */
+    ASSERT(Message->ApiNumber == RmAuditSetCommand);
+    Message->ApiNumber = 0;
+
+    /* Store the enable flag in the global variable */
+    SepAdtAuditingEnabled = Message->u.SetAuditEvent.Enabled;
+
+    /* Loop all audit event types */
+    for (i = 0; i < POLICY_AUDIT_EVENT_TYPE_COUNT; i++)
+    {
+        /* Save the provided flags in the global array */
+        SeAuditingState[i] = (UCHAR)Message->u.SetAuditEvent.Flags[i];
+    }
+
+    return STATUS_SUCCESS;
+}
+
+
+static
+NTSTATUS
+SepRmCreateLogonSession(
+    PLUID LogonLuid)
+{
+    PSEP_LOGON_SESSION_REFERENCES CurrentSession, NewSession;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    DPRINT1("SepRmCreateLogonSession(<0x%lx,0x%lx>)\n",
+            LogonLuid->HighPart, LogonLuid->LowPart);
+
+    /* Allocate a new session structure */
+    NewSession = ExAllocatePoolWithTag(PagedPool,
+                                       sizeof(SEP_LOGON_SESSION_REFERENCES),
+                                       SEP_LOGON_SESSION_TAG);
+    if (NewSession == NULL)
+    {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Initialize it */
+    NewSession->LogonId = *LogonLuid;
+    NewSession->ReferenceCount = 0;
+    NewSession->Flags = 0;
+    NewSession->pDeviceMap = NULL;
+    InitializeListHead(&NewSession->TokenList);
+
+    /* Acquire the database lock */
+    KeAcquireGuardedMutex(&SepRmDbLock);
+
+    /* Loop all existing sessions */
+    for (CurrentSession = SepLogonSessions;
+         CurrentSession != NULL;
+         CurrentSession = CurrentSession->Next)
+    {
+        /* Check if the LUID matches the new one */
+        if (RtlEqualLuid(&CurrentSession->LogonId, LogonLuid))
+        {
+            Status = STATUS_LOGON_SESSION_EXISTS;
+            goto Leave;
+        }
+    }
+
+    /* Insert the new session */
+    NewSession->Next = SepLogonSessions;
+    SepLogonSessions = NewSession;
+
+    Status = STATUS_SUCCESS;
+
+Leave:
+    /* Release the database lock */
+    KeReleaseGuardedMutex(&SepRmDbLock);
+
+    if (!NT_SUCCESS(Status))
+    {
+        ExFreePoolWithTag(NewSession, SEP_LOGON_SESSION_TAG);
+    }
+
+    return Status;
+}
+
+static
+NTSTATUS
+SepRmDeleteLogonSession(
+    PLUID LogonLuid)
+{
+    DPRINT1("SepRmDeleteLogonSession(<0x%lx,0x%lx>)\n",
+            LogonLuid->HighPart, LogonLuid->LowPart);
+
+    UNIMPLEMENTED;
+    NT_ASSERT(FALSE);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+BOOLEAN
+NTAPI
+SepRmCommandServerThreadInit(VOID)
+{
+    SECURITY_QUALITY_OF_SERVICE SecurityQos;
+    SEP_RM_API_MESSAGE Message;
+    UNICODE_STRING PortName;
+    REMOTE_PORT_VIEW RemotePortView;
+    PORT_VIEW PortView;
+    LARGE_INTEGER SectionSize;
+    HANDLE SectionHandle;
+    HANDLE PortHandle;
+    NTSTATUS Status;
+    BOOLEAN Result;
+
+    SectionHandle = NULL;
+    PortHandle = NULL;
+
+    /* Assume success */
+    Result = TRUE;
+
+    /* Wait until LSASS is ready */
+    Status = ZwWaitForSingleObject(SeLsaInitEvent, FALSE, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Waiting for LSA Init Event failed 0x%lx\n", Status);
+        goto Cleanup;
+    }
+
+    /* We don't need this event anymore */
+    ObCloseHandle(SeLsaInitEvent, KernelMode);
+
+    /* Initialize the connection message */
+    Message.Header.u1.s1.TotalLength = sizeof(Message);
+    Message.Header.u1.s1.DataLength = 0;
+
+    /* Only LSASS can connect, so handle the connection right now */
+    Status = ZwListenPort(SeRmCommandPort, &Message.Header);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Listen to Command Port failed 0x%lx\n", Status);
+        goto Cleanup;
+    }
+
+    /* Set the Port View structure length */
+    RemotePortView.Length = sizeof(RemotePortView);
+
+    /* Accept the connection */
+    Status = ZwAcceptConnectPort(&SepRmCommandMessagePort,
+                                 NULL,
+                                 &Message.Header,
+                                 TRUE,
+                                 NULL,
+                                 &RemotePortView);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Accept Connect to Command Port failed 0x%lx\n", Status);
+        goto Cleanup;
+    }
+
+    /* Complete the connection */
+    Status = ZwCompleteConnectPort(SepRmCommandMessagePort);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Complete Connect to Command Port failed 0x%lx\n", Status);
+        goto Cleanup;
+    }
+
+    /* Create a section for messages */
+    SectionSize.QuadPart = PAGE_SIZE;
+    Status = ZwCreateSection(&SectionHandle,
+                             SECTION_ALL_ACCESS,
+                             NULL,
+                             &SectionSize,
+                             PAGE_READWRITE,
+                             SEC_COMMIT,
+                             NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Create Memory Section for LSA port failed: %X\n", Status);
+        goto Cleanup;
+    }
+
+    /* Setup the PORT_VIEW structure */
+    PortView.Length = sizeof(PortView);
+    PortView.SectionHandle = SectionHandle;
+    PortView.SectionOffset = 0;
+    PortView.ViewSize = SectionSize.LowPart;
+    PortView.ViewBase = NULL;
+    PortView.ViewRemoteBase = NULL;
+
+    /* Setup security QOS */
+    SecurityQos.Length = sizeof(SecurityQos);
+    SecurityQos.ImpersonationLevel = SecurityImpersonation;
+    SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
+    SecurityQos.EffectiveOnly = TRUE;
+
+    /* Connect to LSASS */
+    RtlInitUnicodeString(&PortName, L"\\SeLsaCommandPort");
+    Status = ZwConnectPort(&PortHandle,
+                           &PortName,
+                           &SecurityQos,
+                           &PortView,
+                           NULL,
+                           0,
+                           0,
+                           0);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Security Rm Init: Connect to LSA Port failed 0x%lx\n", Status);
+        goto Cleanup;
+    }
+
+    /* Remember section base and view offset */
+    SepCommandPortViewBase = PortView.ViewBase;
+    SepCommandPortViewRemoteBase = PortView.ViewRemoteBase;
+    SepCommandPortViewBaseOffset = (ULONG_PTR)SepCommandPortViewRemoteBase -
+                                   (ULONG_PTR)SepCommandPortViewBase;
+
+    DPRINT("SepRmCommandServerThreadInit: done\n");
+
+Cleanup:
+    /* Check for failure */
+    if (!NT_SUCCESS(Status))
+    {
+        if (PortHandle != NULL)
+        {
+            ObCloseHandle(PortHandle, KernelMode);
+        }
+
+        Result = FALSE;
+    }
+
+    /* Did we create a section? */
+    if (SectionHandle != NULL)
+    {
+        ObCloseHandle(SectionHandle, KernelMode);
+    }
+
+    return Result;
+}
+
+VOID
+NTAPI
+SepRmCommandServerThread(
+    PVOID StartContext)
+{
+    SEP_RM_API_MESSAGE Message;
+    PPORT_MESSAGE ReplyMessage;
+    HANDLE DummyPortHandle;
+    NTSTATUS Status;
+
+    /* Initialize the server thread */
+    if (!SepRmCommandServerThreadInit())
+    {
+        DPRINT1("Security: Terminating Rm Command Server Thread\n");
+        return;
+    }
+
+    /* No reply yet */
+    ReplyMessage = NULL;
+
+    /* Start looping */
+    while (TRUE)
+    {
+        /* Wait for a message */
+        Status = ZwReplyWaitReceivePort(SepRmCommandMessagePort,
+                                        NULL,
+                                        ReplyMessage,
+                                        &Message.Header);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("Failed to get message: 0x%lx", Status);
+            ReplyMessage = NULL;
+            continue;
+        }
+
+        /* Check if this is a connection request */
+        if (Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
+        {
+            /* Reject connection request */
+            ZwAcceptConnectPort(&DummyPortHandle,
+                                NULL,
+                                &Message.Header,
+                                FALSE,
+                                NULL,
+                                NULL);
+
+            /* Start over */
+            ReplyMessage = NULL;
+            continue;
+        }
+
+        /* Check if the port died */
+        if ((Message.Header.u2.s2.Type == LPC_PORT_CLOSED) ||
+            (Message.Header.u2.s2.Type == LPC_CLIENT_DIED))
+        {
+            /* LSASS is dead, so let's quit as well */
+            break;
+        }
+
+        /* Check if this is an actual request */
+        if (Message.Header.u2.s2.Type != LPC_REQUEST)
+        {
+            DPRINT1("SepRmCommandServerThread: unexpected message type: 0x%lx\n",
+                    Message.Header.u2.s2.Type);
+
+            /* Restart without replying */
+            ReplyMessage = NULL;
+            continue;
+        }
+
+        ReplyMessage = &Message.Header;
+
+        switch (Message.ApiNumber)
+        {
+            case RmAuditSetCommand:
+                Status = SepRmSetAuditEvent(&Message);
+                break;
+
+            case RmCreateLogonSession:
+                Status = SepRmCreateLogonSession(&Message.u.LogonLuid);
+                break;
+
+            case RmDeleteLogonSession:
+                Status = SepRmDeleteLogonSession(&Message.u.LogonLuid);
+                break;
+
+            default:
+                DPRINT1("SepRmDispatchRequest: invalid API number: 0x%lx\n",
+                        Message.ApiNumber);
+                ReplyMessage = NULL;
+        }
+
+        Message.u.ResultStatus = Status;
+    }
+
+    /* Close the port handles */
+    ObCloseHandle(SepRmCommandMessagePort, KernelMode);
+    ObCloseHandle(SeRmCommandPort, KernelMode);
+}