ReactOS 0.4.17-dev-684-ga6524ef
srm.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for srm.c:

Go to the source code of this file.

Classes

struct  _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION
 

Macros

#define NDEBUG
 
#define POLICY_AUDIT_EVENT_TYPE_COUNT   9
 
#define MAX_LOGON_SESSION_LISTS_IN_ARRAY   16
 

Typedefs

typedef struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION SEP_LOGON_SESSION_TERMINATED_NOTIFICATION
 
typedef struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATIONPSEP_LOGON_SESSION_TERMINATED_NOTIFICATION
 

Functions

VOID NTAPI SepRmCommandServerThread (_In_ PVOID StartContext)
 Manages the SRM server API commands, that is, receiving such API command messages from the user mode side of the security standpoint, the LSASS.
 
static NTSTATUS SepCleanupLUIDDeviceMapDirectory (_In_ PLUID LogonLuid)
 Cleans the DOS device map directory of a logon session.
 
static NTSTATUS SepRmCreateLogonSession (_In_ PLUID LogonLuid)
 Creates a logon session. The security reference monitoring (SRM) module of Executive uses this as an internal kernel data for respective logon sessions management within the kernel, as in form of a SEP_LOGON_SESSION_REFERENCES data structure.
 
NTSTATUS NTAPI SepRegQueryHelper (_In_ PCWSTR KeyName, _In_ PCWSTR ValueName, _In_ ULONG ValueType, _In_ ULONG DataLength, _Out_ PVOID ValueData)
 A private registry helper that returns the desired value data based on the specifics requested by the caller.
 
BOOLEAN NTAPI SeRmInitPhase0 (VOID)
 Manages the phase 0 initialization of the security reference monitoring module of the kernel.
 
BOOLEAN NTAPI SeRmInitPhase1 (VOID)
 Manages the phase 1 initialization of the security reference monitoring module of the kernel.
 
static VOID SepAdtInitializeBounds (VOID)
 Initializes the local security authority audit bounds.
 
static NTSTATUS SepRmSetAuditEvent (_Inout_ PSEP_RM_API_MESSAGE Message)
 Sets an audit event for future security auditing monitoring.
 
NTSTATUS NTAPI SepRmInsertLogonSessionIntoToken (_Inout_ PTOKEN Token)
 Inserts a logon session into an access token specified by the caller.
 
NTSTATUS NTAPI SepRmRemoveLogonSessionFromToken (_Inout_ PTOKEN Token)
 Removes a logon session from an access token.
 
static NTSTATUS SepRmDeleteLogonSession (_In_ PLUID LogonLuid)
 Deletes a logon session from the logon sessions database.
 
NTSTATUS SepRmReferenceLogonSession (_In_ PLUID LogonLuid)
 References a logon session.
 
NTSTATUS SepRmDereferenceLogonSession (_In_ PLUID LogonLuid)
 De-references a logon session. If the session has a reference count of 0 by the time the function has de-referenced the logon, that means the session is no longer used and can be safely deleted from the logon sessions database.
 
BOOLEAN NTAPI SepRmCommandServerThreadInit (VOID)
 Main SRM server thread initialization function. It deals with security manager and LSASS port connection, thus thereby allowing communication between the kernel side (the SRM) and user mode side (the LSASS) of the security world of the operating system.
 
NTSTATUS NTAPI SeGetLogonIdDeviceMap (_In_ PLUID LogonId, _Out_ PDEVICE_MAP *DeviceMap)
 Retrieves the DOS device map from a logon session.
 
NTSTATUS NTAPI SeMarkLogonSessionForTerminationNotification (_In_ PLUID LogonId)
 Marks a logon session for future termination, given its logon ID. This triggers a callout (the registered callback) when the logon is no longer used by anyone, that is, no token is still referencing the speciffied logon session.
 
NTSTATUS NTAPI SeRegisterLogonSessionTerminatedRoutine (_In_ PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine)
 Registers a callback that will be called once a logon session terminates.
 
NTSTATUS NTAPI SeUnregisterLogonSessionTerminatedRoutine (_In_ PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine)
 Un-registers a callback routine, previously registered by SeRegisterLogonSessionTerminatedRoutine function.
 

Variables

LUID SeSystemAuthenticationId
 
LUID SeAnonymousAuthenticationId
 
HANDLE SeRmCommandPort
 
HANDLE SeLsaInitEvent
 
PVOID SepCommandPortViewBase
 
PVOID SepCommandPortViewRemoteBase
 
ULONG_PTR SepCommandPortViewBaseOffset
 
static HANDLE SepRmCommandMessagePort
 
BOOLEAN SepAdtAuditingEnabled
 
ULONG SepAdtMinListLength = 0x2000
 
ULONG SepAdtMaxListLength = 0x3000
 
UCHAR SeAuditingState [POLICY_AUDIT_EVENT_TYPE_COUNT]
 
KGUARDED_MUTEX SepRmDbLock
 
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION SepLogonNotifications = NULL
 
static PSEP_LOGON_SESSION_REFERENCES _SepLogonSessions [MAX_LOGON_SESSION_LISTS_IN_ARRAY] = {NULL}
 
PSEP_LOGON_SESSION_REFERENCES *const SepLogonSessions = _SepLogonSessions
 

Macro Definition Documentation

◆ MAX_LOGON_SESSION_LISTS_IN_ARRAY

#define MAX_LOGON_SESSION_LISTS_IN_ARRAY   16

Definition at line 73 of file srm.c.

◆ NDEBUG

#define NDEBUG

Definition at line 14 of file srm.c.

◆ POLICY_AUDIT_EVENT_TYPE_COUNT

#define POLICY_AUDIT_EVENT_TYPE_COUNT   9

Definition at line 59 of file srm.c.

Typedef Documentation

◆ PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION

◆ SEP_LOGON_SESSION_TERMINATED_NOTIFICATION

Function Documentation

◆ SeGetLogonIdDeviceMap()

NTSTATUS NTAPI SeGetLogonIdDeviceMap ( _In_ PLUID  LogonId,
_Out_ PDEVICE_MAP DeviceMap 
)

Retrieves the DOS device map from a logon session.

Parameters
[in]LogonIdA valid logon session ID.
[out]DeviceMapThe returned device map buffer from the logon session.
Returns
Returns STATUS_SUCCESS if the device map could be gathered from the logon session. STATUS_INVALID_PARAMETER is returned if one of the parameters aren't initialized (that is, the caller has submitted a NULL pointer variable). STATUS_NO_SUCH_LOGON_SESSION is returned if no such session could be found. A failure NTSTATUS code is returned otherwise.

Definition at line 1373 of file srm.c.

1376{
1378 WCHAR Buffer[63];
1379 PDEVICE_MAP LocalMap;
1380 HANDLE DirectoryHandle, LinkHandle;
1382 PSEP_LOGON_SESSION_REFERENCES CurrentSession;
1383 UNICODE_STRING DirectoryName, LinkName, TargetName;
1384
1385 PAGED_CODE();
1386
1387 if (LogonId == NULL ||
1388 DeviceMap == NULL)
1389 {
1391 }
1392
1393 /* Acquire the database lock */
1395
1396 /* Retrieve the hash bucket and loop over it */
1397 for (CurrentSession = SepLogonSessions[LogonId->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
1398 CurrentSession != NULL;
1399 CurrentSession = CurrentSession->Next)
1400 {
1401 /* Check if the LUID matches the provided one */
1402 if (RtlEqualLuid(&CurrentSession->LogonId, LogonId))
1403 {
1404 break;
1405 }
1406 }
1407
1408 /* No session found, fail */
1409 if (CurrentSession == NULL)
1410 {
1411 /* Release the database lock */
1413
1415 }
1416
1417 /* The found session has a device map, return it! */
1418 if (CurrentSession->pDeviceMap != NULL)
1419 {
1420 *DeviceMap = CurrentSession->pDeviceMap;
1421
1422 /* Release the database lock */
1424
1425 return STATUS_SUCCESS;
1426 }
1427
1428 /* At that point, we'll setup a new device map for the session */
1429 LocalMap = NULL;
1430
1431 /* Reference the session so that it doesn't go away */
1432 CurrentSession->ReferenceCount += 1;
1433
1434 /* Release the database lock */
1436
1437 /* Create our object directory given the LUID */
1439 sizeof(Buffer) / sizeof(WCHAR),
1440 L"\\Sessions\\0\\DosDevices\\%08x-%08x",
1441 LogonId->HighPart,
1442 LogonId->LowPart);
1443 RtlInitUnicodeString(&DirectoryName, Buffer);
1444
1446 &DirectoryName,
1448 NULL,
1449 NULL);
1453 if (NT_SUCCESS(Status))
1454 {
1455 /* Create the associated device map */
1457 if (NT_SUCCESS(Status))
1458 {
1459 /* Make Global point to \Global?? in the directory */
1460 RtlInitUnicodeString(&LinkName, L"Global");
1461 RtlInitUnicodeString(&TargetName, L"\\Global??");
1462
1464 &LinkName,
1467 NULL);
1468 Status = ZwCreateSymbolicLinkObject(&LinkHandle,
1471 &TargetName);
1472 if (!NT_SUCCESS(Status))
1473 {
1474 ObfDereferenceDeviceMap(LocalMap);
1475 }
1476 else
1477 {
1478 ZwClose(LinkHandle);
1479 }
1480 }
1481
1483 }
1484
1485 /* Acquire the database lock */
1487
1488 /* If we succeed... */
1489 if (NT_SUCCESS(Status))
1490 {
1491 /* The session now has a device map? We raced with someone else */
1492 if (CurrentSession->pDeviceMap != NULL)
1493 {
1494 /* Give up on our new device map */
1495 ObfDereferenceDeviceMap(LocalMap);
1496 }
1497 /* Otherwise use our newly allocated device map */
1498 else
1499 {
1500 CurrentSession->pDeviceMap = LocalMap;
1501 }
1502
1503 /* Return the device map */
1504 *DeviceMap = CurrentSession->pDeviceMap;
1505 }
1506 /* Zero output */
1507 else
1508 {
1509 *DeviceMap = NULL;
1510 }
1511
1512 /* Release the database lock */
1514
1515 /* We're done with the session */
1516 SepRmDereferenceLogonSession(&CurrentSession->LogonId);
1517
1518 return Status;
1519}
#define PAGED_CODE()
static HANDLE DirectoryHandle
Definition: ObType.cpp:48
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_ACRTIMP int __cdecl _snwprintf(wchar_t *, size_t, const wchar_t *,...)
Definition: wcs.c:1498
#define L(x)
Definition: resources.c:13
Status
Definition: gdiplustypes.h:24
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI NTSTATUS NTAPI ZwCreateSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ PUNICODE_STRING Name)
NTSYSAPI NTSTATUS NTAPI ZwCreateDirectoryObject(_Out_ PHANDLE DirectoryHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
#define SYMBOLIC_LINK_ALL_ACCESS
Definition: nt_native.h:1270
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define DIRECTORY_ALL_ACCESS
Definition: nt_native.h:1262
_IRQL_requires_same_ _In_ PLSA_STRING _In_ SECURITY_LOGON_TYPE _In_ ULONG _In_ ULONG _In_opt_ PTOKEN_GROUPS _In_ PTOKEN_SOURCE _Out_ PVOID _Out_ PULONG _Inout_ PLUID LogonId
PSEP_LOGON_SESSION_REFERENCES *const SepLogonSessions
Definition: srm.c:75
NTSTATUS SepRmDereferenceLogonSession(_In_ PLUID LogonLuid)
De-references a logon session. If the session has a reference count of 0 by the time the function has...
Definition: srm.c:1034
KGUARDED_MUTEX SepRmDbLock
Definition: srm.c:62
#define MAX_LOGON_SESSION_LISTS_IN_ARRAY
Definition: srm.c:73
#define STATUS_NO_SUCH_LOGON_SESSION
Definition: ntstatus.h:425
NTSTATUS NTAPI ObSetDirectoryDeviceMap(OUT PDEVICE_MAP *DeviceMap, IN HANDLE DirectoryHandle)
Definition: devicemap.c:149
VOID FASTCALL ObfDereferenceDeviceMap(IN PDEVICE_MAP DeviceMap)
Definition: devicemap.c:477
short WCHAR
Definition: pedump.c:58
static PCWSTR TargetName
Definition: ping.c:67
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_PERMANENT
Definition: winternl.h:226
#define STATUS_SUCCESS
Definition: shellext.h:65
struct _SEP_LOGON_SESSION_REFERENCES * Next
Definition: setypes.h:169
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:304

Referenced by ObpReferenceDeviceMap(), and ObpSetCurrentProcessDeviceMap().

◆ SeMarkLogonSessionForTerminationNotification()

NTSTATUS NTAPI SeMarkLogonSessionForTerminationNotification ( _In_ PLUID  LogonId)

Marks a logon session for future termination, given its logon ID. This triggers a callout (the registered callback) when the logon is no longer used by anyone, that is, no token is still referencing the speciffied logon session.

Parameters
[in]LogonIdThe ID of the logon session.
Returns
STATUS_SUCCESS if the logon session is marked for termination notification successfully, STATUS_NOT_FOUND if the logon session couldn't be found otherwise.

Definition at line 1536 of file srm.c.

1538{
1539 PSEP_LOGON_SESSION_REFERENCES SessionToMark;
1540 PAGED_CODE();
1541
1542 DPRINT("SeMarkLogonSessionForTerminationNotification(%08lx:%08lx)\n",
1543 LogonId->HighPart, LogonId->LowPart);
1544
1545 /* Acquire the database lock */
1547
1548 /* Retrieve the hash bucket and loop over it */
1549 for (SessionToMark = SepLogonSessions[LogonId->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
1550 SessionToMark != NULL;
1551 SessionToMark = SessionToMark->Next)
1552 {
1553 /* Does the logon with the given ID exist? */
1554 if (RtlEqualLuid(&SessionToMark->LogonId, LogonId))
1555 {
1556 /* We found it */
1557 break;
1558 }
1559 }
1560
1561 /*
1562 * We've exhausted all the remaining logon sessions and
1563 * couldn't find one with the provided ID.
1564 */
1565 if (SessionToMark == NULL)
1566 {
1567 DPRINT1("SeMarkLogonSessionForTerminationNotification(): Logon session couldn't be found!\n");
1569 return STATUS_NOT_FOUND;
1570 }
1571
1572 /* Mark the logon session for termination */
1574 DPRINT("SeMarkLogonSessionForTerminationNotification(): Logon session marked for termination with success!\n");
1575
1576 /* Release the database lock */
1578 return STATUS_SUCCESS;
1579}
#define DPRINT1
Definition: precomp.h:8
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:73
#define SEP_LOGON_SESSION_TERMINATION_NOTIFY
Definition: setypes.h:708

Referenced by LogonMarkTermination().

◆ SepAdtInitializeBounds()

static VOID SepAdtInitializeBounds ( VOID  )
static

Initializes the local security authority audit bounds.

Returns
Nothing.

Definition at line 286 of file srm.c.

287{
288 struct
289 {
290 ULONG MaxLength;
291 ULONG MinLength;
292 } ListBounds;
294 PAGED_CODE();
295
296 Status = SepRegQueryHelper(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa",
297 L"Bounds",
299 sizeof(ListBounds),
300 &ListBounds);
301 if (!NT_SUCCESS(Status))
302 {
303 /* No registry values, so keep hardcoded defaults */
304 return;
305 }
306
307 /* Check if the bounds are valid */
308 if ((ListBounds.MaxLength < ListBounds.MinLength) ||
309 (ListBounds.MinLength < 16) ||
310 (ListBounds.MaxLength - ListBounds.MinLength < 16))
311 {
312 DPRINT1("ListBounds invalid: %lu, %lu\n", ListBounds.MinLength, ListBounds.MaxLength);
313 return;
314 }
315
316 /* Set the new bounds globally */
317 SepAdtMinListLength = ListBounds.MinLength;
318 SepAdtMaxListLength = ListBounds.MaxLength;
319}
#define REG_BINARY
Definition: nt_native.h:1499
NTSTATUS NTAPI SepRegQueryHelper(_In_ PCWSTR KeyName, _In_ PCWSTR ValueName, _In_ ULONG ValueType, _In_ ULONG DataLength, _Out_ PVOID ValueData)
A private registry helper that returns the desired value data based on the specifics requested by the...
Definition: srm.c:105
ULONG SepAdtMinListLength
Definition: srm.c:56
ULONG SepAdtMaxListLength
Definition: srm.c:57
uint32_t ULONG
Definition: typedefs.h:59

Referenced by SepRmSetAuditEvent().

◆ SepCleanupLUIDDeviceMapDirectory()

static NTSTATUS SepCleanupLUIDDeviceMapDirectory ( _In_ PLUID  LogonLuid)
static

Cleans the DOS device map directory of a logon session.

Parameters
[in]LogonLuidA logon session ID where its DOS device map directory is to be cleaned.
Returns
Returns STATUS_SUCCESS if the device map directory has been successfully cleaned from the logon session. STATUS_INVALID_PARAMETER is returned if the caller hasn't submitted any logon ID. STATUS_NO_MEMORY is returned if buffer allocation for links has failed. A failure NTSTATUS code is returned otherwise.

Definition at line 777 of file srm.c.

779{
780 BOOLEAN UseCurrentProc;
782 WCHAR Buffer[63];
783 UNICODE_STRING DirectoryName;
786 HANDLE DirectoryHandle, LinkHandle;
787 PHANDLE LinksBuffer;
788 POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
789 ULONG LinksCount, LinksSize, DirInfoLength, ReturnLength, Context, CurrentLinks, i;
791
792 PAGED_CODE();
793
794 /* We need a logon LUID */
795 if (LogonLuid == NULL)
796 {
798 }
799
800 /* Use current process */
801 UseCurrentProc = ObReferenceObjectSafe(PsGetCurrentProcess());
802 if (UseCurrentProc)
803 {
805 }
806 /* Unless it's gone, then use system process */
807 else
808 {
810 }
811
812 /* Initialize our directory name */
814 sizeof(Buffer) / sizeof(WCHAR),
815 L"\\Sessions\\0\\DosDevices\\%08x-%08x",
816 LogonLuid->HighPart,
817 LogonLuid->LowPart);
818 RtlInitUnicodeString(&DirectoryName, Buffer);
819
820 /* And open it */
822 &DirectoryName,
824 NULL,
825 NULL);
829 if (!NT_SUCCESS(Status))
830 {
831 if (!UseCurrentProc)
832 {
834 }
835
836 return Status;
837 }
838
839 /* Some initialization needed for browsing all our links... */
840 Context = 0;
841 DirectoryInfo = NULL;
842 DirInfoLength = 0;
843 /* In our buffer, we'll store at max 100 HANDLE */
844 LinksCount = 100;
845 CurrentLinks = 0;
846 /* Which gives a certain size */
847 LinksSize = LinksCount * sizeof(HANDLE);
848
849 /*
850 * This label is hit if we need to store more than a hundred
851 * of links. In that case, we jump here after having cleaned
852 * and deleted previous buffer.
853 * All handles have been already closed
854 */
855AllocateLinksAgain:
856 LinksBuffer = ExAllocatePoolWithTag(PagedPool,
857 LinksSize,
859 if (LinksBuffer == NULL)
860 {
861 /*
862 * Failure path: no need to clear handles:
863 * already closed and the buffer is already gone
864 */
866
867 /*
868 * On the first round, DirectoryInfo is NULL,
869 * if we grow LinksBuffer, it has been allocated
870 */
871 if (DirectoryInfo != NULL)
872 {
873 ExFreePoolWithTag(DirectoryInfo, TAG_SE_DIR_BUFFER);
874 }
875
876 if (!UseCurrentProc)
877 {
879 }
880
881 return STATUS_NO_MEMORY;
882 }
883
884 /*
885 * We always restart scan, but on the first loop
886 * if we couldn't fit everything in our buffer,
887 * then, we continue scan.
888 * But we restart if link buffer was too small
889 */
890 for (RestartScan = TRUE; ; RestartScan = FALSE)
891 {
892 /*
893 * Loop until our buffer is big enough to store
894 * one entry
895 */
896 while (TRUE)
897 {
898 Status = ZwQueryDirectoryObject(DirectoryHandle,
899 DirectoryInfo,
900 DirInfoLength,
901 TRUE,
903 &Context,
904 &ReturnLength);
905 /* Only handle buffer growth in that loop */
907 {
908 break;
909 }
910
911 /* Get output length as new length */
912 DirInfoLength = ReturnLength;
913 /* Delete old buffer if any */
914 if (DirectoryInfo != NULL)
915 {
916 ExFreePoolWithTag(DirectoryInfo, 'bDeS');
917 }
918
919 /* And reallocate a bigger one */
920 DirectoryInfo = ExAllocatePoolWithTag(PagedPool,
921 DirInfoLength,
923 /* Fail if we cannot allocate */
924 if (DirectoryInfo == NULL)
925 {
927 break;
928 }
929 }
930
931 /* If querying the entry failed, quit */
932 if (!NT_SUCCESS(Status))
933 {
934 break;
935 }
936
937 /* We only look for symbolic links, the rest, we ignore */
938 if (wcscmp(DirectoryInfo->TypeName.Buffer, L"SymbolicLink"))
939 {
940 continue;
941 }
942
943 /* If our link buffer is out of space, reallocate */
944 if (CurrentLinks >= LinksCount)
945 {
946 /* First, close the links */
947 for (i = 0; i < CurrentLinks; ++i)
948 {
949 ZwClose(LinksBuffer[i]);
950 }
951
952 /* Allow 20 more HANDLEs */
953 LinksCount += 20;
954 CurrentLinks = 0;
956 LinksSize = LinksCount * sizeof(HANDLE);
957
958 /* And reloop again */
959 goto AllocateLinksAgain;
960 }
961
962 /* Open the found link */
964 &DirectoryInfo->Name,
967 NULL);
968 if (NT_SUCCESS(ZwOpenSymbolicLinkObject(&LinkHandle,
971 {
972 /* If we cannot make it temporary, just close the link handle */
973 if (!NT_SUCCESS(ZwMakeTemporaryObject(LinkHandle)))
974 {
975 ZwClose(LinkHandle);
976 }
977 /* Otherwise, store it to defer deletion */
978 else
979 {
980 LinksBuffer[CurrentLinks] = LinkHandle;
981 ++CurrentLinks;
982 }
983 }
984 }
985
986 /* No more entries means we handled all links, that's not a failure */
988 {
990 }
991
992 /* Close all the links we stored, this will like cause their deletion */
993 for (i = 0; i < CurrentLinks; ++i)
994 {
995 ZwClose(LinksBuffer[i]);
996 }
997 /* And free our links buffer */
999
1000 /* Free our directory info buffer - it might be NULL if we failed realloc */
1001 if (DirectoryInfo != NULL)
1002 {
1003 ExFreePoolWithTag(DirectoryInfo, TAG_SE_DIR_BUFFER);
1004 }
1005
1006 /* Close our session directory */
1008
1009 /* And detach from system */
1010 if (!UseCurrentProc)
1011 {
1013 }
1014
1015 return Status;
1016}
_In_ PVOID _In_ ULONG _Out_ PVOID _In_ ULONG _Inout_ PULONG ReturnLength
unsigned char BOOLEAN
Definition: actypes.h:127
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ BOOLEAN _In_ ULONG _In_opt_ PULONG _In_ BOOLEAN RestartScan
Definition: fltkernel.h:2299
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSYSAPI NTSTATUS NTAPI ZwOpenSymbolicLinkObject(_Out_ PHANDLE SymbolicLinkHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwOpenDirectoryObject(_Out_ PHANDLE FileHandle, _In_ ACCESS_MASK DesiredAccess, _In_ POBJECT_ATTRIBUTES ObjectAttributes)
NTSYSAPI NTSTATUS NTAPI ZwMakeTemporaryObject(_In_ HANDLE Handle)
#define DIRECTORY_QUERY
Definition: nt_native.h:1257
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1769
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:285
BOOLEAN FASTCALL ObReferenceObjectSafe(IN PVOID Object)
Definition: obref.c:22
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_In_ PVOID Context
Definition: storport.h:2269
KPROCESS Pcb
Definition: pstypes.h:1369
UNICODE_STRING TypeName
Definition: obtypes.h:254
#define TAG_SE_DIR_BUFFER
Definition: tag.h:162
#define TAG_SE_HANDLES_TAB
Definition: tag.h:161
PVOID HANDLE
Definition: typedefs.h:73
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
KAPC_STATE
Definition: ketypes.h:1727
#define ObDereferenceObject
Definition: obfuncs.h:203
#define PsGetCurrentProcess
Definition: psfuncs.h:17

Referenced by SepRmDeleteLogonSession(), and SepRmDereferenceLogonSession().

◆ SepRegQueryHelper()

NTSTATUS NTAPI SepRegQueryHelper ( _In_ PCWSTR  KeyName,
_In_ PCWSTR  ValueName,
_In_ ULONG  ValueType,
_In_ ULONG  DataLength,
_Out_ PVOID  ValueData 
)

A private registry helper that returns the desired value data based on the specifics requested by the caller.

Parameters
[in]KeyNameName of the key.
[in]ValueNameName of the registry value.
[in]ValueTypeThe type of the registry value.
[in]DataLengthThe data length, in bytes, representing the size of the registry value.
[out]ValueDataThe requested value data provided by the function.
Returns
Returns STATUS_SUCCESS if the operations have completed successfully, otherwise a failure NTSTATUS code is returned.

Definition at line 105 of file srm.c.

111{
112 UNICODE_STRING ValueNameString;
113 UNICODE_STRING KeyNameString;
117 struct
118 {
120 UCHAR Buffer[64];
121 } KeyValueInformation;
122 NTSTATUS Status, CloseStatus;
123 PAGED_CODE();
124
125 RtlInitUnicodeString(&KeyNameString, KeyName);
127 &KeyNameString,
129 NULL,
130 NULL);
131
133 if (!NT_SUCCESS(Status))
134 {
135 return Status;
136 }
137
138 RtlInitUnicodeString(&ValueNameString, ValueName);
139 Status = ZwQueryValueKey(KeyHandle,
140 &ValueNameString,
142 &KeyValueInformation.Partial,
143 sizeof(KeyValueInformation),
144 &ResultLength);
145 if (!NT_SUCCESS(Status))
146 {
147 goto Cleanup;
148 }
149
150 if ((KeyValueInformation.Partial.Type != ValueType) ||
151 (KeyValueInformation.Partial.DataLength != DataLength))
152 {
154 goto Cleanup;
155 }
156
157 if (ValueType == REG_BINARY)
158 {
159 RtlCopyMemory(ValueData, KeyValueInformation.Partial.Data, DataLength);
160 }
161 else if (ValueType == REG_DWORD)
162 {
163 *(PULONG)ValueData = *(PULONG)KeyValueInformation.Partial.Data;
164 }
165 else
166 {
168 }
169
170Cleanup:
171 CloseStatus = ZwClose(KeyHandle);
172 ASSERT(NT_SUCCESS( CloseStatus ));
173
174 return Status;
175}
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: d3dkmdt.h:46
static const WCHAR Cleanup[]
Definition: register.c:80
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define ASSERT(a)
Definition: mode.c:44
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
@ KeyValuePartialInformation
Definition: nt_native.h:1185
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
#define REG_DWORD
Definition: sdbapi.c:615
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3782
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243

Referenced by SepAdtInitializeBounds(), and SepImpersonateAnonymousToken().

◆ SepRmCommandServerThread()

VOID NTAPI SepRmCommandServerThread ( _In_ PVOID  StartContext)

Manages the SRM server API commands, that is, receiving such API command messages from the user mode side of the security standpoint, the LSASS.

Returns
Nothing.

Definition at line 1252 of file srm.c.

1254{
1257 HANDLE DummyPortHandle;
1259
1260 /* Initialize the server thread */
1262 {
1263 DPRINT1("Security: Terminating Rm Command Server Thread\n");
1264 return;
1265 }
1266
1267 /* No reply yet */
1269
1270 /* Start looping */
1271 while (TRUE)
1272 {
1273 /* Wait for a message */
1275 NULL,
1277 &Message.Header);
1278 if (!NT_SUCCESS(Status))
1279 {
1280 DPRINT1("Failed to get message: 0x%lx\n", Status);
1282 continue;
1283 }
1284
1285 /* Check if this is a connection request */
1286 if (Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST)
1287 {
1288 /* Reject connection request */
1289 ZwAcceptConnectPort(&DummyPortHandle,
1290 NULL,
1291 &Message.Header,
1292 FALSE,
1293 NULL,
1294 NULL);
1295
1296 /* Start over */
1298 continue;
1299 }
1300
1301 /* Check if the port died */
1302 if ((Message.Header.u2.s2.Type == LPC_PORT_CLOSED) ||
1303 (Message.Header.u2.s2.Type == LPC_CLIENT_DIED))
1304 {
1305 /* LSASS is dead, so let's quit as well */
1306 break;
1307 }
1308
1309 /* Check if this is an actual request */
1310 if (Message.Header.u2.s2.Type != LPC_REQUEST)
1311 {
1312 DPRINT1("SepRmCommandServerThread: unexpected message type: 0x%x\n",
1313 Message.Header.u2.s2.Type);
1314
1315 /* Restart without replying */
1317 continue;
1318 }
1319
1320 ReplyMessage = &Message.Header;
1321
1322 switch (Message.ApiNumber)
1323 {
1324 case RmAuditSetCommand:
1326 break;
1327
1329 Status = SepRmCreateLogonSession(&Message.u.LogonLuid);
1330 break;
1331
1333 Status = SepRmDeleteLogonSession(&Message.u.LogonLuid);
1334 break;
1335
1336 default:
1337 DPRINT1("SepRmDispatchRequest: invalid API number: 0x%lx\n",
1338 Message.ApiNumber);
1340 }
1341
1342 Message.u.ResultStatus = Status;
1343 }
1344
1345 /* Close the port handles */
1348}
HANDLE SeRmCommandPort
Definition: srm.c:18
static const WCHAR Message[]
Definition: register.c:74
NTSYSAPI NTSTATUS NTAPI ZwReplyWaitReceivePort(_In_ HANDLE PortHandle, _Out_opt_ PVOID *PortContext, _In_opt_ PPORT_MESSAGE ReplyMessage, _Out_ PPORT_MESSAGE ReceiveMessage)
NTSYSAPI NTSTATUS NTAPI ZwAcceptConnectPort(_Out_ PHANDLE PortHandle, _In_opt_ PVOID PortContext, _In_ PPORT_MESSAGE ConnectionRequest, _In_ BOOLEAN AcceptConnection, _In_opt_ PPORT_VIEW ServerView, _In_opt_ PREMOTE_PORT_VIEW ClientView)
#define LPC_CLIENT_DIED
Definition: port.c:98
#define LPC_REQUEST
Definition: port.c:93
#define LPC_CONNECTION_REQUEST
Definition: port.c:102
#define LPC_PORT_CLOSED
Definition: port.c:97
#define KernelMode
Definition: asm.h:38
static NTSTATUS SepRmDeleteLogonSession(_In_ PLUID LogonLuid)
Deletes a logon session from the logon sessions database.
Definition: srm.c:610
static HANDLE SepRmCommandMessagePort
Definition: srm.c:53
static NTSTATUS SepRmCreateLogonSession(_In_ PLUID LogonLuid)
Creates a logon session. The security reference monitoring (SRM) module of Executive uses this as an ...
Definition: srm.c:525
BOOLEAN NTAPI SepRmCommandServerThreadInit(VOID)
Main SRM server thread initialization function. It deals with security manager and LSASS port connect...
Definition: srm.c:1101
static NTSTATUS SepRmSetAuditEvent(_Inout_ PSEP_RM_API_MESSAGE Message)
Sets an audit event for future security auditing monitoring.
Definition: srm.c:335
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3406
@ RmDeleteLogonSession
Definition: srmp.h:8
@ RmAuditSetCommand
Definition: srmp.h:6
@ RmCreateLogonSession
Definition: srmp.h:7
BOOL WINAPI ReplyMessage(_In_ LRESULT)

Referenced by SeRmInitPhase1().

◆ SepRmCommandServerThreadInit()

BOOLEAN NTAPI SepRmCommandServerThreadInit ( VOID  )

Main SRM server thread initialization function. It deals with security manager and LSASS port connection, thus thereby allowing communication between the kernel side (the SRM) and user mode side (the LSASS) of the security world of the operating system.

Returns
Returns TRUE if command server connection between SRM and LSASS has succeeded, FALSE otherwise.

Definition at line 1101 of file srm.c.

1102{
1103 SECURITY_QUALITY_OF_SERVICE SecurityQos;
1106 REMOTE_PORT_VIEW RemotePortView;
1107 PORT_VIEW PortView;
1108 LARGE_INTEGER SectionSize;
1109 HANDLE SectionHandle;
1110 HANDLE PortHandle;
1113
1114 SectionHandle = NULL;
1115 PortHandle = NULL;
1116
1117 /* Assume success */
1118 Result = TRUE;
1119
1120 /* Wait until LSASS is ready */
1122 if (!NT_SUCCESS(Status))
1123 {
1124 DPRINT1("Security Rm Init: Waiting for LSA Init Event failed 0x%lx\n", Status);
1125 goto Cleanup;
1126 }
1127
1128 /* We don't need this event anymore */
1130
1131 /* Initialize the connection message */
1132 Message.Header.u1.s1.TotalLength = sizeof(Message);
1133 Message.Header.u1.s1.DataLength = 0;
1134
1135 /* Only LSASS can connect, so handle the connection right now */
1137 if (!NT_SUCCESS(Status))
1138 {
1139 DPRINT1("Security Rm Init: Listen to Command Port failed 0x%lx\n", Status);
1140 goto Cleanup;
1141 }
1142
1143 /* Set the Port View structure length */
1144 RemotePortView.Length = sizeof(RemotePortView);
1145
1146 /* Accept the connection */
1148 NULL,
1149 &Message.Header,
1150 TRUE,
1151 NULL,
1152 &RemotePortView);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 DPRINT1("Security Rm Init: Accept Connect to Command Port failed 0x%lx\n", Status);
1156 goto Cleanup;
1157 }
1158
1159 /* Complete the connection */
1161 if (!NT_SUCCESS(Status))
1162 {
1163 DPRINT1("Security Rm Init: Complete Connect to Command Port failed 0x%lx\n", Status);
1164 goto Cleanup;
1165 }
1166
1167 /* Create a section for messages */
1168 SectionSize.QuadPart = PAGE_SIZE;
1169 Status = ZwCreateSection(&SectionHandle,
1171 NULL,
1172 &SectionSize,
1174 SEC_COMMIT,
1175 NULL);
1176 if (!NT_SUCCESS(Status))
1177 {
1178 DPRINT1("Security Rm Init: Create Memory Section for LSA port failed: 0x%lx\n", Status);
1179 goto Cleanup;
1180 }
1181
1182 /* Setup the PORT_VIEW structure */
1183 PortView.Length = sizeof(PortView);
1184 PortView.SectionHandle = SectionHandle;
1185 PortView.SectionOffset = 0;
1186 PortView.ViewSize = SectionSize.LowPart;
1187 PortView.ViewBase = NULL;
1188 PortView.ViewRemoteBase = NULL;
1189
1190 /* Setup security QOS */
1191 SecurityQos.Length = sizeof(SecurityQos);
1194 SecurityQos.EffectiveOnly = TRUE;
1195
1196 /* Connect to LSASS */
1197 RtlInitUnicodeString(&PortName, L"\\SeLsaCommandPort");
1198 Status = ZwConnectPort(&PortHandle,
1199 &PortName,
1200 &SecurityQos,
1201 &PortView,
1202 NULL,
1203 0,
1204 0,
1205 0);
1206 if (!NT_SUCCESS(Status))
1207 {
1208 DPRINT1("Security Rm Init: Connect to LSA Port failed 0x%lx\n", Status);
1209 goto Cleanup;
1210 }
1211
1212 /* Remember section base and view offset */
1217
1218 DPRINT("SepRmCommandServerThreadInit: done\n");
1219
1220Cleanup:
1221 /* Check for failure */
1222 if (!NT_SUCCESS(Status))
1223 {
1224 if (PortHandle != NULL)
1225 {
1226 ObCloseHandle(PortHandle, KernelMode);
1227 }
1228
1229 Result = FALSE;
1230 }
1231
1232 /* Did we create a section? */
1233 if (SectionHandle != NULL)
1234 {
1235 ObCloseHandle(SectionHandle, KernelMode);
1236 }
1237
1238 return Result;
1239}
static UNICODE_STRING PortName
#define ULONG_PTR
Definition: config.h:101
#define PAGE_SIZE
Definition: env_spec_w32.h:49
NTSYSAPI NTSTATUS NTAPI ZwWaitForSingleObject(_In_ HANDLE Handle, _In_ BOOLEAN Alertable, _In_opt_ PLARGE_INTEGER Timeout)
NTSYSAPI NTSTATUS NTAPI ZwListenPort(_In_ HANDLE PortHandle, _In_ PPORT_MESSAGE ConnectionRequest)
NTSYSAPI NTSTATUS NTAPI ZwConnectPort(_Out_ PHANDLE PortHandle, _In_ PUNICODE_STRING PortName, _In_ PSECURITY_QUALITY_OF_SERVICE SecurityQos, _In_opt_ PPORT_VIEW ClientView, _In_opt_ PREMOTE_PORT_VIEW ServerView, _In_opt_ PULONG MaxMessageLength, _In_opt_ PVOID ConnectionInformation, _In_opt_ PULONG ConnectionInformationLength)
NTSYSAPI NTSTATUS NTAPI ZwCompleteConnectPort(_In_ HANDLE PortHandle)
@ SecurityImpersonation
Definition: lsa.idl:57
#define SEC_COMMIT
Definition: mmtypes.h:100
#define PAGE_READWRITE
Definition: nt_native.h:1307
#define SECTION_ALL_ACCESS
Definition: nt_native.h:1296
HANDLE SeLsaInitEvent
Definition: srm.c:47
PVOID SepCommandPortViewBase
Definition: srm.c:49
PVOID SepCommandPortViewRemoteBase
Definition: srm.c:50
ULONG_PTR SepCommandPortViewBaseOffset
Definition: srm.c:51
LPC_PVOID ViewBase
LPC_HANDLE SectionHandle
LPC_PVOID ViewRemoteBase
ULONG SectionOffset
LPC_SIZE_T ViewSize
SECURITY_CONTEXT_TRACKING_MODE ContextTrackingMode
Definition: lsa.idl:66
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
Definition: lsa.idl:65
uint32_t ULONG_PTR
Definition: typedefs.h:65
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define SECURITY_DYNAMIC_TRACKING
Definition: setypes.h:103

Referenced by SepRmCommandServerThread().

◆ SepRmCreateLogonSession()

static NTSTATUS SepRmCreateLogonSession ( _In_ PLUID  LogonLuid)
static

Creates a logon session. The security reference monitoring (SRM) module of Executive uses this as an internal kernel data for respective logon sessions management within the kernel, as in form of a SEP_LOGON_SESSION_REFERENCES data structure.

Parameters
[in]LogonLuidA logon ID represented as a LUID. This LUID is used to create our logon session and add it to the sessions database.
Returns
Returns STATUS_SUCCESS if the logon has been created successfully. STATUS_LOGON_SESSION_EXISTS is returned if a logon session with the pointed logon ID in the call already exists. STATUS_INSUFFICIENT_RESOURCES is returned if logon session allocation has failed because of lack of memory pool resources.

Definition at line 525 of file srm.c.

527{
528 PSEP_LOGON_SESSION_REFERENCES *LogonSession, CurrentSession, NewSession;
530 PAGED_CODE();
531
532 DPRINT("SepRmCreateLogonSession(%08lx:%08lx)\n",
533 LogonLuid->HighPart, LogonLuid->LowPart);
534
535 /* Allocate a new session structure */
536 NewSession = ExAllocatePoolWithTag(PagedPool,
539 if (NewSession == NULL)
540 {
542 }
543
544 /* Initialize it */
545 NewSession->LogonId = *LogonLuid;
546 NewSession->ReferenceCount = 0;
547 NewSession->Flags = 0;
548 NewSession->pDeviceMap = NULL;
549 InitializeListHead(&NewSession->TokenList);
550
551 /* Acquire the database lock */
553
554 /*
555 * Cache the previous session from the hash bucket, the newly created
556 * session will keep hold of the previous session and the hash bucket
557 * gets a new assigned session.
558 */
559 LogonSession = &SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
560
561 /* Loop all existing sessions */
562 for (CurrentSession = *LogonSession;
563 CurrentSession != NULL;
564 CurrentSession = CurrentSession->Next)
565 {
566 /* Check if the LUID matches the new one */
567 if (RtlEqualLuid(&CurrentSession->LogonId, LogonLuid))
568 {
570 goto Leave;
571 }
572 }
573
574 /* Insert the new session */
575 NewSession->Next = *LogonSession;
576 *LogonSession = NewSession;
577
579
580Leave:
581 /* Release the database lock */
583
584 if (!NT_SUCCESS(Status))
585 {
587 }
588
589 return Status;
590}
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define STATUS_LOGON_SESSION_EXISTS
Definition: ntstatus.h:568
#define TAG_LOGON_SESSION
Definition: tag.h:165

Referenced by SepRmCommandServerThread(), and SeRmInitPhase0().

◆ SepRmDeleteLogonSession()

static NTSTATUS SepRmDeleteLogonSession ( _In_ PLUID  LogonLuid)
static

Deletes a logon session from the logon sessions database.

Parameters
[in]LogonLuidA logon ID represented as a LUID. This LUID is used to point the exact logon session saved within the database.
Returns
STATUS_SUCCESS is returned if the logon session has been deleted successfully. STATUS_NO_SUCH_LOGON_SESSION is returned if the logon session with the submitted LUID doesn't exist. STATUS_BAD_LOGON_SESSION_STATE is returned if the logon session is still in use and we're not allowed to delete it, or if a system or anonymous session is submitted and we're not allowed to delete them as they're internal parts of the system. Otherwise a failure NTSTATUS code is returned.

Definition at line 610 of file srm.c.

612{
613 PSEP_LOGON_SESSION_REFERENCES SessionToDelete, *LogonSession;
615 PAGED_CODE();
616
617 DPRINT("SepRmDeleteLogonSession(%08lx:%08lx)\n",
618 LogonLuid->HighPart, LogonLuid->LowPart);
619
620 /* Acquire the database lock */
622
623 /* Retrieve the hash bucket, the database will have this session pulled away down below */
624 LogonSession = &SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
625
626 /* Loop over the existing logon sessions */
627 for (SessionToDelete = *LogonSession;
628 SessionToDelete != NULL;
629 SessionToDelete = SessionToDelete->Next)
630 {
631 /*
632 * Does the actual logon session exist in the
633 * saved logon sessions database with the LUID
634 * provided?
635 */
636 if (RtlEqualLuid(&SessionToDelete->LogonId, LogonLuid))
637 {
638 /* Did the caller supply one of these internal sessions? */
639 if (RtlEqualLuid(&SessionToDelete->LogonId, &SeSystemAuthenticationId) ||
641 {
642 /* These logons are critical stuff, we can't delete them */
643 DPRINT1("SepRmDeleteLogonSession(): We're not allowed to delete anonymous/system sessions!\n");
645 goto Leave;
646 }
647 else
648 {
649 /* We found the logon as exactly as we wanted, break the loop */
650 break;
651 }
652 }
653 }
654
655 /*
656 * If we reach this then that means we've exhausted all the logon
657 * sessions and couldn't find one with the desired LUID.
658 */
659 if (SessionToDelete == NULL)
660 {
661 DPRINT1("SepRmDeleteLogonSession(): The logon session with this LUID doesn't exist!\n");
663 goto Leave;
664 }
665
666 /* Is somebody still using this logon session? */
667 if (SessionToDelete->ReferenceCount != 0)
668 {
669 /* The logon session is still in use, we cannot delete it... */
670 DPRINT1("SepRmDeleteLogonSession(): The logon session is still in use!\n");
672 goto Leave;
673 }
674
675 /* If we have a LUID device map, clean it */
676 if (SessionToDelete->pDeviceMap != NULL)
677 {
679 if (!NT_SUCCESS(Status))
680 {
681 /*
682 * We had one job on cleaning the device map directory
683 * of the logon session but we failed, quit...
684 */
685 DPRINT1("SepRmDeleteLogonSession(): Failed to clean the LUID device map directory of the logon (Status: 0x%lx)\n", Status);
686 goto Leave;
687 }
688
689 /* And dereference the device map of the logon */
690 ObfDereferenceDeviceMap(SessionToDelete->pDeviceMap);
691 }
692
693 /* Unlink the session from the bucket list */
694 *LogonSession = SessionToDelete->Next;
695
696 /* If we're here then we've deleted the logon session successfully */
697 DPRINT("SepRmDeleteLogonSession(): Logon session deleted with success!\n");
699 ExFreePoolWithTag(SessionToDelete, TAG_LOGON_SESSION);
700
701Leave:
702 /* Release the database lock */
704 return Status;
705}
LUID SeSystemAuthenticationId
Definition: token.c:20
static NTSTATUS SepCleanupLUIDDeviceMapDirectory(_In_ PLUID LogonLuid)
Cleans the DOS device map directory of a logon session.
Definition: srm.c:777
LUID SeAnonymousAuthenticationId
Definition: token.c:21
#define STATUS_BAD_LOGON_SESSION_STATE
Definition: ntstatus.h:590

Referenced by SepRmCommandServerThread().

◆ SepRmDereferenceLogonSession()

NTSTATUS SepRmDereferenceLogonSession ( _In_ PLUID  LogonLuid)

De-references a logon session. If the session has a reference count of 0 by the time the function has de-referenced the logon, that means the session is no longer used and can be safely deleted from the logon sessions database.

Parameters
[in]LogonLuidA logon session ID to de-reference.
Returns
Returns STATUS_SUCCESS if the logon session has been de-referenced without issues. STATUS_NO_SUCH_LOGON_SESSION is returned if no such logon exists otherwise.

Definition at line 1034 of file srm.c.

1036{
1037 ULONG RefCount;
1038 PDEVICE_MAP DeviceMap;
1039 PSEP_LOGON_SESSION_REFERENCES CurrentSession;
1040
1041 DPRINT("SepRmDereferenceLogonSession(%08lx:%08lx)\n",
1042 LogonLuid->HighPart, LogonLuid->LowPart);
1043
1044 /* Acquire the database lock */
1046
1047 /* Retrieve the hash bucket and walk over it */
1048 for (CurrentSession = SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
1049 CurrentSession != NULL;
1050 CurrentSession = CurrentSession->Next)
1051 {
1052 /* Check if the LUID matches the new one */
1053 if (RtlEqualLuid(&CurrentSession->LogonId, LogonLuid))
1054 {
1055 /* Dereference the session */
1056 RefCount = --CurrentSession->ReferenceCount;
1057 DPRINT("ReferenceCount: %lu\n", CurrentSession->ReferenceCount);
1058
1059 /* Release the database lock */
1061
1062 /* We're done with the session */
1063 if (RefCount == 0)
1064 {
1065 /* Get rid of the LUID device map */
1066 DeviceMap = CurrentSession->pDeviceMap;
1067 if (DeviceMap != NULL)
1068 {
1069 CurrentSession->pDeviceMap = NULL;
1071 ObfDereferenceDeviceMap(DeviceMap);
1072 }
1073
1074 /* FIXME: Alert LSA and filesystems that a logon is about to be deleted */
1075 }
1076
1077 return STATUS_SUCCESS;
1078 }
1079 }
1080
1081 /* Release the database lock */
1083
1085}

Referenced by SeGetLogonIdDeviceMap().

◆ SepRmInsertLogonSessionIntoToken()

NTSTATUS NTAPI SepRmInsertLogonSessionIntoToken ( _Inout_ PTOKEN  Token)

Inserts a logon session into an access token specified by the caller.

Parameters
[in,out]TokenAn access token where the logon session is about to be inserted in.
Returns
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.

Definition at line 379 of file srm.c.

381{
383 PAGED_CODE();
384
385 /* Ensure that our token is not some plain garbage */
386 ASSERT(Token);
387
388 /* Acquire the database lock */
390
391 /* Retrieve the hash bucket and loop over it */
392 for (LogonSession = SepLogonSessions[Token->AuthenticationId.LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
393 LogonSession != NULL;
394 LogonSession = LogonSession->Next)
395 {
396 /*
397 * The insertion of a logon session into the token has to be done
398 * only IF the authentication ID of the token matches with the ID
399 * of the logon itself.
400 */
401 if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
402 {
403 break;
404 }
405 }
406
407 /* If we reach this then we cannot proceed further */
408 if (LogonSession == NULL)
409 {
410 DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't insert the logon session into the specific access token!\n");
413 }
414
415 /*
416 * Allocate the session that we are going
417 * to insert it to the token.
418 */
419 Token->LogonSession = ExAllocatePoolWithTag(PagedPool,
422 if (Token->LogonSession == NULL)
423 {
424 DPRINT1("SepRmInsertLogonSessionIntoToken(): Couldn't allocate new logon session into the memory pool!\n");
427 }
428
429 /*
430 * Begin copying the logon session references data from the
431 * session whose ID matches with the token authentication ID to
432 * the new session we've allocated blocks of pool memory for it.
433 */
434 Token->LogonSession->Next = LogonSession->Next;
435 Token->LogonSession->LogonId = LogonSession->LogonId;
436 Token->LogonSession->ReferenceCount = LogonSession->ReferenceCount;
437 Token->LogonSession->Flags = LogonSession->Flags;
438 Token->LogonSession->pDeviceMap = LogonSession->pDeviceMap;
439 InsertHeadList(&LogonSession->TokenList, &Token->LogonSession->TokenList);
440
441 /* Release the database lock and we're done */
443 return STATUS_SUCCESS;
444}
#define InsertHeadList(ListHead, Entry)

Referenced by SepCreateToken(), SepDuplicateToken(), and SepPerformTokenFiltering().

◆ SepRmReferenceLogonSession()

NTSTATUS SepRmReferenceLogonSession ( _In_ PLUID  LogonLuid)

References a logon session.

Parameters
[in]LogonLuidA valid LUID that points to the logon session in the database that we're going to reference it.
Returns
Returns STATUS_SUCCESS if the logon has been referenced. STATUS_NO_SUCH_LOGON_SESSION is returned if the session couldn't be found otherwise.

Definition at line 721 of file srm.c.

723{
724 PSEP_LOGON_SESSION_REFERENCES CurrentSession;
725
726 PAGED_CODE();
727
728 DPRINT("SepRmReferenceLogonSession(%08lx:%08lx)\n",
729 LogonLuid->HighPart, LogonLuid->LowPart);
730
731 /* Acquire the database lock */
733
734 /* Retrieve the hash bucket and loop over it */
735 for (CurrentSession = SepLogonSessions[LogonLuid->LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
736 CurrentSession != NULL;
737 CurrentSession = CurrentSession->Next)
738 {
739 /* Check if the LUID matches the new one */
740 if (RtlEqualLuid(&CurrentSession->LogonId, LogonLuid))
741 {
742 /* Reference the session */
743 ++CurrentSession->ReferenceCount;
744 DPRINT("ReferenceCount: %lu\n", CurrentSession->ReferenceCount);
745
746 /* Release the database lock */
748
749 return STATUS_SUCCESS;
750 }
751 }
752
753 /* Release the database lock */
755
757}

◆ SepRmRemoveLogonSessionFromToken()

NTSTATUS NTAPI SepRmRemoveLogonSessionFromToken ( _Inout_ PTOKEN  Token)

Removes a logon session from an access token.

Parameters
[in,out]TokenAn access token whose logon session is to be removed from it.
Returns
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.

Definition at line 461 of file srm.c.

463{
465 PAGED_CODE();
466
467 /* Ensure that our token is not some plain garbage */
468 ASSERT(Token);
469
470 /* Acquire the database lock */
472
473 /* Retrieve the hash bucket and loop over it */
474 for (LogonSession = SepLogonSessions[Token->AuthenticationId.LowPart % MAX_LOGON_SESSION_LISTS_IN_ARRAY];
475 LogonSession != NULL;
476 LogonSession = LogonSession->Next)
477 {
478 /*
479 * Remove the logon session only when the IDs of the token and the
480 * logon match.
481 */
482 if (RtlEqualLuid(&LogonSession->LogonId, &Token->AuthenticationId))
483 {
484 break;
485 }
486 }
487
488 /* They don't match */
489 if (LogonSession == NULL)
490 {
491 DPRINT1("SepRmRemoveLogonSessionFromToken(): Couldn't remove the logon session from the access token!\n");
494 }
495
496 /* Now it's time to delete the logon session from the token */
497 RemoveEntryList(&Token->LogonSession->TokenList);
499
500 /* Release the database lock and we're done */
502 return STATUS_SUCCESS;
503}
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986

Referenced by NtSetInformationToken(), and SepDeleteToken().

◆ SepRmSetAuditEvent()

static NTSTATUS SepRmSetAuditEvent ( _Inout_ PSEP_RM_API_MESSAGE  Message)
static

Sets an audit event for future security auditing monitoring.

Parameters
[in,out]MessageThe reference monitoring API message. It is used to determine if the right API message number is provided, RmAuditSetCommand in this case.
Returns
Returns STATUS_SUCCESS.

Definition at line 335 of file srm.c.

337{
338 ULONG i;
339 PAGED_CODE();
340
341 /* First re-initialize the bounds from the registry */
343
344 /* Make sure we have the right message and clear */
345 ASSERT(Message->ApiNumber == RmAuditSetCommand);
346 Message->ApiNumber = 0;
347
348 /* Store the enable flag in the global variable */
349 SepAdtAuditingEnabled = Message->u.SetAuditEvent.Enabled;
350
351 /* Loop all audit event types */
352 for (i = 0; i < POLICY_AUDIT_EVENT_TYPE_COUNT; i++)
353 {
354 /* Save the provided flags in the global array */
355 SeAuditingState[i] = (UCHAR)Message->u.SetAuditEvent.Flags[i];
356 }
357
358 return STATUS_SUCCESS;
359}
UCHAR SeAuditingState[POLICY_AUDIT_EVENT_TYPE_COUNT]
Definition: srm.c:60
BOOLEAN SepAdtAuditingEnabled
Definition: srm.c:55
#define POLICY_AUDIT_EVENT_TYPE_COUNT
Definition: srm.c:59
static VOID SepAdtInitializeBounds(VOID)
Initializes the local security authority audit bounds.
Definition: srm.c:286

Referenced by SepRmCommandServerThread().

◆ SeRegisterLogonSessionTerminatedRoutine()

NTSTATUS NTAPI SeRegisterLogonSessionTerminatedRoutine ( _In_ PSE_LOGON_SESSION_TERMINATED_ROUTINE  CallbackRoutine)

Registers a callback that will be called once a logon session terminates.

Parameters
[in]CallbackRoutineCallback routine address.
Returns
Returns STATUS_SUCCESS if the callback routine was registered successfully. STATUS_INVALID_PARAMETER is returned if the caller did not provide a callback routine. STATUS_INSUFFICIENT_RESOURCES is returned if the callback notification data couldn't be allocated because of lack of memory pool resources.

Definition at line 1598 of file srm.c.

1600{
1602 PAGED_CODE();
1603
1604 /* Fail, if we don not have a callback routine */
1605 if (CallbackRoutine == NULL)
1607
1608 /* Allocate a new notification item */
1612 if (Notification == NULL)
1614
1615 /* Acquire the database lock */
1617
1618 /* Set the callback routine */
1619 Notification->CallbackRoutine = CallbackRoutine;
1620
1621 /* Insert the new notification item into the list */
1624
1625 /* Release the database lock */
1627
1628 return STATUS_SUCCESS;
1629}
_Must_inspect_result_ _In_ PFLT_GET_OPERATION_STATUS_CALLBACK CallbackRoutine
Definition: fltkernel.h:1035
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION SepLogonNotifications
Definition: srm.c:63
#define TAG_LOGON_NOTIFICATION
Definition: tag.h:166
_In_ PWDFDEVICE_INIT _In_ PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION Notification
Definition: wdfcontrol.h:115

◆ SeRmInitPhase0()

BOOLEAN NTAPI SeRmInitPhase0 ( VOID  )

Manages the phase 0 initialization of the security reference monitoring module of the kernel.

Returns
Returns TRUE when phase 0 initialization has completed without problems, FALSE otherwise.

Definition at line 188 of file srm.c.

189{
191
192 /* Initialize the database lock */
194
195 /* Create the system logon session */
198 {
199 return FALSE;
200 }
201
202 /* Create the anonymous logon session */
205 {
206 return FALSE;
207 }
208
209 return TRUE;
210}
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304

Referenced by SepInitializationPhase0().

◆ SeRmInitPhase1()

BOOLEAN NTAPI SeRmInitPhase1 ( VOID  )

Manages the phase 1 initialization of the security reference monitoring module of the kernel.

Returns
Returns TRUE when phase 1 initialization has completed without problems, FALSE otherwise.

Definition at line 223 of file srm.c.

224{
227 HANDLE ThreadHandle;
229
230 /* Create the SeRm command port */
231 RtlInitUnicodeString(&Name, L"\\SeRmCommandPort");
235 sizeof(ULONG),
237 2 * PAGE_SIZE);
238 if (!NT_SUCCESS(Status))
239 {
240 DPRINT1("Security: Rm Command Port creation failed: 0x%lx\n", Status);
241 return FALSE;
242 }
243
244 /* Create SeLsaInitEvent */
245 RtlInitUnicodeString(&Name, L"\\SeLsaInitEvent");
247 Status = ZwCreateEvent(&SeLsaInitEvent,
251 FALSE);
252 if (!NT_VERIFY((NT_SUCCESS(Status))))
253 {
254 DPRINT1("Security: LSA Init Event creation failed: 0x%lx\n", Status);
255 return FALSE;
256 }
257
258 /* Create the SeRm server thread */
259 Status = PsCreateSystemThread(&ThreadHandle,
261 NULL,
262 NULL,
263 NULL,
265 NULL);
266 if (!NT_SUCCESS(Status))
267 {
268 DPRINT1("Security: Rm Command Server Thread creation failed: 0x%lx\n", Status);
269 return FALSE;
270 }
271
272 ObCloseHandle(ThreadHandle, KernelMode);
273
274 return TRUE;
275}
LPWSTR Name
Definition: desk.c:124
NTSYSAPI NTSTATUS NTAPI ZwCreatePort(_Out_ PHANDLE PortHandle, _In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_ ULONG MaxConnectionInfoLength, _In_ ULONG MaxMessageLength, _In_ ULONG MaxPoolUsage)
#define THREAD_ALL_ACCESS
Definition: nt_native.h:1342
#define GENERIC_WRITE
Definition: nt_native.h:90
@ NotificationEvent
NTSTATUS NTAPI PsCreateSystemThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE ProcessHandle, IN PCLIENT_ID ClientId, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext)
Definition: thread.c:602
VOID NTAPI SepRmCommandServerThread(_In_ PVOID StartContext)
Manages the SRM server API commands, that is, receiving such API command messages from the user mode ...
Definition: srm.c:1252
#define PORT_MAXIMUM_MESSAGE_LENGTH
Definition: iotypes.h:2029

Referenced by Phase1InitializationDiscard().

◆ SeUnregisterLogonSessionTerminatedRoutine()

NTSTATUS NTAPI SeUnregisterLogonSessionTerminatedRoutine ( _In_ PSE_LOGON_SESSION_TERMINATED_ROUTINE  CallbackRoutine)

Un-registers a callback routine, previously registered by SeRegisterLogonSessionTerminatedRoutine function.

Parameters
[in]CallbackRoutineCallback routine address to un-register.
Returns
Returns STATUS_SUCCESS if the callback routine was un-registered successfully. STATUS_INVALID_PARAMETER is returned if the caller did not provide a callback routine. STATUS_NOT_FOUND is returned if the callback notification item couldn't be found.

Definition at line 1647 of file srm.c.

1649{
1652 PAGED_CODE();
1653
1654 /* Fail, if we don not have a callback routine */
1655 if (CallbackRoutine == NULL)
1657
1658 /* Acquire the database lock */
1660
1661 /* Loop all registered notification items */
1662 for (Current = SepLogonNotifications;
1663 Current != NULL;
1664 Current = Current->Next)
1665 {
1666 /* Check if the callback routine matches the provided one */
1667 if (Current->CallbackRoutine == CallbackRoutine)
1668 break;
1669
1670 Previous = Current;
1671 }
1672
1673 if (Current == NULL)
1674 {
1676 }
1677 else
1678 {
1679 /* Remove the current notification item from the list */
1680 if (Previous == NULL)
1681 SepLogonNotifications = Current->Next;
1682 else
1683 Previous->Next = Current->Next;
1684
1685 /* Free the current notification item */
1686 ExFreePoolWithTag(Current,
1688
1690 }
1691
1692 /* Release the database lock */
1694
1695 return Status;
1696}
struct _SEP_LOGON_SESSION_TERMINATED_NOTIFICATION * Next
Definition: srm.c:21
PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
Definition: srm.c:22

Variable Documentation

◆ _SepLogonSessions

Definition at line 74 of file srm.c.

◆ SeAnonymousAuthenticationId

◆ SeAuditingState

Definition at line 60 of file srm.c.

Referenced by SepRmSetAuditEvent().

◆ SeLsaInitEvent

HANDLE SeLsaInitEvent

Definition at line 47 of file srm.c.

Referenced by SepRmCommandServerThreadInit(), and SeRmInitPhase1().

◆ SepAdtAuditingEnabled

BOOLEAN SepAdtAuditingEnabled

Definition at line 55 of file srm.c.

Referenced by SepRmSetAuditEvent().

◆ SepAdtMaxListLength

ULONG SepAdtMaxListLength = 0x3000

Definition at line 57 of file srm.c.

Referenced by SepAdtInitializeBounds().

◆ SepAdtMinListLength

ULONG SepAdtMinListLength = 0x2000

Definition at line 56 of file srm.c.

Referenced by SepAdtInitializeBounds().

◆ SepCommandPortViewBase

PVOID SepCommandPortViewBase

Definition at line 49 of file srm.c.

Referenced by SepRmCommandServerThreadInit().

◆ SepCommandPortViewBaseOffset

ULONG_PTR SepCommandPortViewBaseOffset

Definition at line 51 of file srm.c.

Referenced by SepRmCommandServerThreadInit().

◆ SepCommandPortViewRemoteBase

PVOID SepCommandPortViewRemoteBase

Definition at line 50 of file srm.c.

Referenced by SepRmCommandServerThreadInit().

◆ SepLogonNotifications

◆ SepLogonSessions

◆ SepRmCommandMessagePort

HANDLE SepRmCommandMessagePort
static

Definition at line 53 of file srm.c.

Referenced by SepRmCommandServerThread(), and SepRmCommandServerThreadInit().

◆ SepRmDbLock

◆ SeRmCommandPort

HANDLE SeRmCommandPort

Definition at line 46 of file srm.c.

◆ SeSystemAuthenticationId

LUID SeSystemAuthenticationId
extern

Definition at line 20 of file token.c.

Referenced by SepCreateSystemProcessToken(), SepRmDeleteLogonSession(), and SeRmInitPhase0().