https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5e51f8dad27aff23dfde8…
commit 5e51f8dad27aff23dfde80d4abdfb4c961593063
Author:     George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sun Jul 25 11:34:45 2021 +0200
Commit:     George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Sat Jul 31 16:11:03 2021 +0200
    [NTOS:SE] Implement logon reference insertion/removal to tokens
---
 ntoskrnl/include/internal/se.h |  12 ++++
 ntoskrnl/se/srm.c              | 152 +++++++++++++++++++++++++++++++++++++++--
 2 files changed, 158 insertions(+), 6 deletions(-)
diff --git a/ntoskrnl/include/internal/se.h b/ntoskrnl/include/internal/se.h
index aa01ef58088..98c1b9e1057 100644
--- a/ntoskrnl/include/internal/se.h
+++ b/ntoskrnl/include/internal/se.h
@@ -353,6 +353,18 @@ SepCreateImpersonationTokenDacl(
     _Out_ PACL* Dacl
 );
+NTSTATUS
+NTAPI
+SepRmInsertLogonSessionIntoToken(
+    _Inout_ PTOKEN Token
+);
+
+NTSTATUS
+NTAPI
+SepRmRemoveLogonSessionFromToken(
+    _Inout_ PTOKEN Token
+);
+
 CODE_SEG("INIT")
 VOID
 NTAPI
diff --git a/ntoskrnl/se/srm.c b/ntoskrnl/se/srm.c
index 23fa3b02120..90809a907e1 100644
--- a/ntoskrnl/se/srm.c
+++ b/ntoskrnl/se/srm.c
@@ -1,11 +1,10 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/se/srm.c
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL-2.0-or-later (
https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:         Security Reference Monitor Server
- *
- * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer(a)reactos.org)
- *                  Pierre Schweitzer (pierre(a)reactos.org)
+ * COPYRIGHT:       Copyright Timo Kreuzer <timo.kreuzer(a)reactos.org>
+ *                  Copyright Pierre Schweitzer <pierre(a)reactos.org>
+ *                  Copyright 2021 George Bișoc <george.bisoc(a)reactos.org>
  */
 /* INCLUDES *******************************************************************/
@@ -315,6 +314,147 @@ SepRmSetAuditEvent(
     return STATUS_SUCCESS;
 }
+/**
+ * @brief
+ * Inserts a logon session into an access token specified by the
+ * caller.
+ *
+ * @param[in,out] Token
+ * An access token where the logon session is about to be inserted
+ * in.
+ *
+ * @return
+ * STATUS_SUCCESS is returned if the logon session has been inserted into
+ * the token successfully. STATUS_NO_SUCH_LOGON_SESSION is returned when no logon
+ * session has been found with the matching ID of the token and as such
+ * we've failed to add the logon session to the token. STATUS_INSUFFICIENT_RESOURCES
+ * is returned if memory pool allocation for the new session has failed.
+ */
+NTSTATUS
+NTAPI
+SepRmInsertLogonSessionIntoToken(
+    _Inout_ PTOKEN Token)
+{
+    PSEP_LOGON_SESSION_REFERENCES LogonSession;
+    PAGED_CODE();
+
+    /* Ensure that our token is not some plain garbage */
+    ASSERT(Token);
+
+    /* Acquire the database lock */
+    KeAcquireGuardedMutex(&SepRmDbLock);
+
+    for (LogonSession = SepLogonSessions;
+         LogonSession != NULL;
+         LogonSession = LogonSession->Next)
+    {
+        /*
+         * The insertion of a logon session into the token has to be done
+         * only IF the authentication ID of the token matches with the ID
+         * of the logon itself.
+         */
+        if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
+        {
+            break;
+        }
+    }
+
+    /* If we reach this then we cannot proceed further */
+    if (LogonSession == NULL)
+    {
+        DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't insert the logon
session into the specific access token!\n");
+        KeReleaseGuardedMutex(&SepRmDbLock);
+        return STATUS_NO_SUCH_LOGON_SESSION;
+    }
+
+    /*
+     * Allocate the session that we are going
+     * to insert it to the token.
+     */
+    Token->LogonSession = ExAllocatePoolWithTag(PagedPool,
+                                                sizeof(SEP_LOGON_SESSION_REFERENCES),
+                                                TAG_LOGON_SESSION);
+    if (Token->LogonSession == NULL)
+    {
+        DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't allocate new logon
session into the memory pool!\n");
+        KeReleaseGuardedMutex(&SepRmDbLock);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /*
+     * Begin copying the logon session references data from the
+     * session whose ID matches with the token authentication ID to
+     * the new session we've allocated blocks of pool memory for it.
+     */
+    Token->LogonSession->Next = LogonSession->Next;
+    Token->LogonSession->LogonId = LogonSession->LogonId;
+    Token->LogonSession->ReferenceCount = LogonSession->ReferenceCount;
+    Token->LogonSession->Flags = LogonSession->Flags;
+    Token->LogonSession->pDeviceMap = LogonSession->pDeviceMap;
+    InsertHeadList(&LogonSession->TokenList,
&Token->LogonSession->TokenList);
+
+    /* Release the database lock and we're done */
+    KeReleaseGuardedMutex(&SepRmDbLock);
+    return STATUS_SUCCESS;
+}
+
+/**
+ * @brief
+ * Removes a logon session from an access token.
+ *
+ * @param[in,out] Token
+ * An access token whose logon session is to be removed from it.
+ *
+ * @return
+ * STATUS_SUCCESS is returned if the logon session has been removed from
+ * the token successfully. STATUS_NO_SUCH_LOGON_SESSION is returned when no logon
+ * session has been found with the matching ID of the token and as such
+ * we've failed to remove the logon session from the token.
+ */
+NTSTATUS
+NTAPI
+SepRmRemoveLogonSessionFromToken(
+    _Inout_ PTOKEN Token)
+{
+    PSEP_LOGON_SESSION_REFERENCES LogonSession;
+    PAGED_CODE();
+
+    /* Ensure that our token is not some plain garbage */
+    ASSERT(Token);
+
+    /* Acquire the database lock */
+    KeAcquireGuardedMutex(&SepRmDbLock);
+
+    for (LogonSession = SepLogonSessions;
+         LogonSession != NULL;
+         LogonSession = LogonSession->Next)
+    {
+        /*
+         * Remove the logon session only when the IDs of the token and the
+         * logon match.
+         */
+        if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
+        {
+            break;
+        }
+    }
+
+    /* They don't match */
+    if (LogonSession == NULL)
+    {
+        DPRINT1("SepRmRemoveLogonSessionFromToken(): Couldn't remove the logon
session from the access token!\n");
+        KeReleaseGuardedMutex(&SepRmDbLock);
+        return STATUS_NO_SUCH_LOGON_SESSION;
+    }
+
+    /* Now it's time to delete the logon session from the token */
+    RemoveEntryList(&Token->LogonSession->TokenList);
+    ExFreePoolWithTag(Token->LogonSession, TAG_LOGON_SESSION);
+
+    /* Release the database lock and we're done */
+    KeReleaseGuardedMutex(&SepRmDbLock);
+    return STATUS_SUCCESS;
+}
 static
 NTSTATUS