1138 lines
25 KiB
C
1138 lines
25 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rmlogon.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the kernel mode logon tracking performed by the
|
|||
|
reference monitor. Logon tracking is performed by keeping a count of
|
|||
|
how many tokens exist for each active logon in a system. When a logon
|
|||
|
session's reference count drops to zero, the LSA is notified so that
|
|||
|
authentication packages can clean up any related context data.
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jim Kelly (JimK) 21-April-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
//#define SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
|
|||
|
#include "rmp.h"
|
|||
|
#include <bugcodes.h>
|
|||
|
|
|||
|
|
|||
|
SEP_LOGON_SESSION_TERMINATED_NOTIFICATION
|
|||
|
SeFileSystemNotifyRoutinesHead = {0};
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Internally defined data types //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
typedef struct _SEP_FILE_SYSTEM_NOTIFY_CONTEXT {
|
|||
|
WORK_QUEUE_ITEM WorkItem;
|
|||
|
LUID LogonId;
|
|||
|
} SEP_FILE_SYSTEM_NOTIFY_CONTEXT, *PSEP_FILE_SYSTEM_NOTIFY_CONTEXT;
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Internally defined routines //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SepGetLogonSessionTrack(
|
|||
|
IN PLUID LogonId
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepInformLsaOfDeletedLogon(
|
|||
|
IN PLUID LogonId
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
SepInformFileSystemsOfDeletedLogon(
|
|||
|
IN PLUID LogonId
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
SepNotifyFileSystems(
|
|||
|
IN PVOID Context
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE,SeRegisterLogonSessionTerminatedRoutine)
|
|||
|
#pragma alloc_text(PAGE,SeUnregisterLogonSessionTerminatedRoutine)
|
|||
|
#pragma alloc_text(PAGE,SeMarkLogonSessionForTerminationNotification)
|
|||
|
#pragma alloc_text(PAGE,SepRmCreateLogonSessionWrkr)
|
|||
|
#pragma alloc_text(PAGE,SepRmDeleteLogonSessionWrkr)
|
|||
|
#pragma alloc_text(PAGE,SepReferenceLogonSession)
|
|||
|
#pragma alloc_text(PAGE,SepDeReferenceLogonSession)
|
|||
|
#pragma alloc_text(PAGE,SepCreateLogonSessionTrack)
|
|||
|
#pragma alloc_text(PAGE,SepDeleteLogonSessionTrack)
|
|||
|
#pragma alloc_text(PAGE,SepInformLsaOfDeletedLogon)
|
|||
|
#pragma alloc_text(PAGE,SepInformFileSystemsOfDeletedLogon)
|
|||
|
#pragma alloc_text(PAGE,SepNotifyFileSystems)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Local macros //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// This macro is used to obtain an index into the logon session tracking
|
|||
|
// array given a logon session ID (a LUID).
|
|||
|
//
|
|||
|
|
|||
|
#define SepLogonSessionIndex( PLogonId ) ( \
|
|||
|
(PLogonId)->LowPart & SEP_LOGON_TRACK_INDEX_MASK \
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Exported Services //
|
|||
|
// //
|
|||
|
////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
VOID
|
|||
|
SepRmCreateLogonSessionWrkr(
|
|||
|
IN PRM_COMMAND_MESSAGE CommandMessage,
|
|||
|
OUT PRM_REPLY_MESSAGE ReplyMessage
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is the dispatch routine for the LSA --> RM
|
|||
|
"CreateLogonSession" call.
|
|||
|
|
|||
|
The arguments passed to this routine are defined by the
|
|||
|
type SEP_RM_COMMAND_WORKER.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CommandMessage - Points to structure containing RM command message
|
|||
|
information consisting of an LPC PORT_MESSAGE structure followed
|
|||
|
by the command number (RmComponentTestCommand) and a command-specific
|
|||
|
body. The command-specific body of this parameter is a LUID of the
|
|||
|
logon session to be created.
|
|||
|
|
|||
|
ReplyMessage - Pointer to structure containing LSA reply message
|
|||
|
information consisting of an LPC PORT_MESSAGE structure followed
|
|||
|
by the command ReturnedStatus field in which a status code from the
|
|||
|
command will be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS Status;
|
|||
|
LUID LogonId;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Check that command is expected type
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( CommandMessage->CommandNumber == RmCreateLogonSession );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Typecast the command parameter to what we expect.
|
|||
|
//
|
|||
|
|
|||
|
LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Try to create the logon session tracking record
|
|||
|
//
|
|||
|
|
|||
|
Status = SepCreateLogonSessionTrack( &LogonId );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the reply status
|
|||
|
//
|
|||
|
|
|||
|
ReplyMessage->ReturnedStatus = Status;
|
|||
|
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepRmDeleteLogonSessionWrkr(
|
|||
|
IN PRM_COMMAND_MESSAGE CommandMessage,
|
|||
|
OUT PRM_REPLY_MESSAGE ReplyMessage
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is the dispatch routine for the LSA --> RM
|
|||
|
"DeleteLogonSession" call.
|
|||
|
|
|||
|
The arguments passed to this routine are defined by the
|
|||
|
type SEP_RM_COMMAND_WORKER.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CommandMessage - Points to structure containing RM command message
|
|||
|
information consisting of an LPC PORT_MESSAGE structure followed
|
|||
|
by the command number (RmComponentTestCommand) and a command-specific
|
|||
|
body. The command-specific body of this parameter is a LUID of the
|
|||
|
logon session to be created.
|
|||
|
|
|||
|
ReplyMessage - Pointer to structure containing LSA reply message
|
|||
|
information consisting of an LPC PORT_MESSAGE structure followed
|
|||
|
by the command ReturnedStatus field in which a status code from the
|
|||
|
command will be returned.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
VOID
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS Status;
|
|||
|
LUID LogonId;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Check that command is expected type
|
|||
|
//
|
|||
|
|
|||
|
ASSERT( CommandMessage->CommandNumber == RmDeleteLogonSession );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Typecast the command parameter to what we expect.
|
|||
|
//
|
|||
|
|
|||
|
LogonId = *((LUID UNALIGNED *) CommandMessage->CommandParams);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Try to create the logon session tracking record
|
|||
|
//
|
|||
|
|
|||
|
Status = SepDeleteLogonSessionTrack( &LogonId );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the reply status
|
|||
|
//
|
|||
|
|
|||
|
ReplyMessage->ReturnedStatus = Status;
|
|||
|
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SepReferenceLogonSession(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine increments the reference count of a logon session
|
|||
|
tracking record.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID whose logon track is
|
|||
|
to be incremented.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - The reference count was successfully incremented.
|
|||
|
|
|||
|
STATUS_NO_SUCH_LOGON_SESSION - The specified logon session doesn't
|
|||
|
exist in the reference monitor's database.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SessionArrayIndex;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES Previous, Current;
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
ULONG Refs;
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
SessionArrayIndex = SepLogonSessionIndex( LogonId );
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of reference monitor database
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Now walk the list for our logon session array hash index.
|
|||
|
//
|
|||
|
|
|||
|
Previous = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
|
|||
|
Current = Previous->Next;
|
|||
|
|
|||
|
while (Current != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// If we found it, increment the reference count and return
|
|||
|
//
|
|||
|
|
|||
|
if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
ULONG Refs;
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
Current->ReferenceCount += 1;
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
Refs = Current->ReferenceCount;
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
DbgPrint("SE (rm): ++ logon session: (%d, %d) to %d by (%d, %d)\n",
|
|||
|
LogonId->HighPart, LogonId->LowPart, Refs,
|
|||
|
PsGetCurrentThread()->Cid.UniqueProcess,
|
|||
|
PsGetCurrentThread()->Cid.UniqueThread);
|
|||
|
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
Previous = Current;
|
|||
|
Current = Current->Next;
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
//
|
|||
|
// Bad news, someone asked us to increment the reference count of
|
|||
|
// a logon session we didn't know existed. This might be a new
|
|||
|
// token being created, so return an error status and let the caller
|
|||
|
// decide if it warrants a bug check or not.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
return STATUS_NO_SUCH_LOGON_SESSION;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepDeReferenceLogonSession(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine decrements the reference count of a logon session
|
|||
|
tracking record.
|
|||
|
|
|||
|
If the reference count is decremented to zero, then there is no
|
|||
|
possibility for any more tokens to exist for the logon session.
|
|||
|
In this case, the LSA is notified that a logon session has
|
|||
|
terminated.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID whose logon track is
|
|||
|
to be decremented.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SessionArrayIndex;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES Previous, Current;
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
ULONG Refs;
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
SessionArrayIndex = SepLogonSessionIndex( LogonId );
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of reference monitor database
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Now walk the list for our logon session array hash index.
|
|||
|
//
|
|||
|
|
|||
|
Previous = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
|
|||
|
Current = Previous->Next;
|
|||
|
|
|||
|
while (Current != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// If we found it, decrement the reference count and return
|
|||
|
//
|
|||
|
|
|||
|
if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
|
|||
|
Current->ReferenceCount -= 1;
|
|||
|
if (Current->ReferenceCount == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Pull it from the list
|
|||
|
//
|
|||
|
|
|||
|
Previous->Next = Current->Next;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// No longer need to protect our pointer to this
|
|||
|
// record.
|
|||
|
//
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
//
|
|||
|
// Asynchronoously inform file systems that this logon session
|
|||
|
// is going away, if atleast one FS expressed interest in this
|
|||
|
// logon session.
|
|||
|
//
|
|||
|
|
|||
|
if (Current->Flags & SEP_TERMINATION_NOTIFY) {
|
|||
|
SepInformFileSystemsOfDeletedLogon( LogonId );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Deallocate the logon session track record.
|
|||
|
//
|
|||
|
|
|||
|
ExFreePool( (PVOID)Current );
|
|||
|
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
DbgPrint("SE (rm): -- ** logon session: (%d, %d) to ZERO by (%d, %d)\n",
|
|||
|
LogonId->HighPart, LogonId->LowPart,
|
|||
|
PsGetCurrentThread()->Cid.UniqueProcess,
|
|||
|
PsGetCurrentThread()->Cid.UniqueThread);
|
|||
|
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
//
|
|||
|
// Inform the LSA about the deletion of this logon session.
|
|||
|
//
|
|||
|
|
|||
|
SepInformLsaOfDeletedLogon( LogonId );
|
|||
|
|
|||
|
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// reference count was incremented, but not to zero.
|
|||
|
//
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
Refs = Current->ReferenceCount;
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
#ifdef SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
DbgPrint("SE (rm): -- logon session: (%d, %d) to %d by (%d, %d)\n",
|
|||
|
LogonId->HighPart, LogonId->LowPart, Refs,
|
|||
|
PsGetCurrentThread()->Cid.UniqueProcess,
|
|||
|
PsGetCurrentThread()->Cid.UniqueThread);
|
|||
|
#endif //SEP_TRACK_LOGON_SESSION_REFS
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Previous = Current;
|
|||
|
Current = Current->Next;
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
//
|
|||
|
// Bad news, someone asked us to decrement the reference count of
|
|||
|
// a logon session we didn't know existed.
|
|||
|
//
|
|||
|
|
|||
|
KeBugCheck( DEREF_UNKNOWN_LOGON_SESSION );
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SepCreateLogonSessionTrack(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a new logon session tracking record.
|
|||
|
|
|||
|
This should only be called as a dispatch routine for a LSA->RM
|
|||
|
call (and once during system initialization).
|
|||
|
|
|||
|
If the specified logon session already exists, then an error is returned.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID for which a new logon track is
|
|||
|
to be created.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - The logon session track was created successfully.
|
|||
|
|
|||
|
STATUS_LOGON_SESSION_EXISTS - The logon session already exists.
|
|||
|
A new one has not been created.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SessionArrayIndex;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES Previous, Current;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES LogonSessionTrack;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Make sure we can allocate a new logon session track record
|
|||
|
//
|
|||
|
|
|||
|
LogonSessionTrack = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
sizeof(SEP_LOGON_SESSION_REFERENCES),
|
|||
|
'sLeS'
|
|||
|
);
|
|||
|
|
|||
|
if (LogonSessionTrack == NULL) {
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
LogonSessionTrack->LogonId = (*LogonId);
|
|||
|
LogonSessionTrack->ReferenceCount = 0;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SessionArrayIndex = SepLogonSessionIndex( LogonId );
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of reference monitor database
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Now walk the list for our logon session array hash index
|
|||
|
// looking for a duplicate logon session ID.
|
|||
|
//
|
|||
|
|
|||
|
Previous = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
|
|||
|
Current = Previous->Next;
|
|||
|
|
|||
|
while (Current != NULL) {
|
|||
|
|
|||
|
if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
|
|||
|
|
|||
|
//
|
|||
|
// One already exists. Hmmm.
|
|||
|
//
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
ExFreePool(LogonSessionTrack);
|
|||
|
return STATUS_LOGON_SESSION_EXISTS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Previous = Current;
|
|||
|
Current = Current->Next;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Reached the end of the list without finding a duplicate.
|
|||
|
// Add the new one.
|
|||
|
//
|
|||
|
|
|||
|
LogonSessionTrack->Next = SepLogonSessions[ SessionArrayIndex ];
|
|||
|
SepLogonSessions[ SessionArrayIndex ] = LogonSessionTrack;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SepDeleteLogonSessionTrack(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine creates a new logon session tracking record.
|
|||
|
|
|||
|
This should only be called as a dispatch routine for a LSA->RM
|
|||
|
call (and once during system initialization).
|
|||
|
|
|||
|
If the specified logon session already exists, then an error is returned.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID whose logon track is
|
|||
|
to be deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - The logon session track was deleted successfully.
|
|||
|
|
|||
|
STATUS_BAD_LOGON_SESSION_STATE - The logon session has a non-zero
|
|||
|
reference count and can not be deleted.
|
|||
|
|
|||
|
STATUS_NO_SUCH_LOGON_SESSION - The specified logon session does not
|
|||
|
exist.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SessionArrayIndex;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES Previous, Current;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
SessionArrayIndex = SepLogonSessionIndex( LogonId );
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of reference monitor database
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Now walk the list for our logon session array hash index.
|
|||
|
//
|
|||
|
|
|||
|
Previous = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
|
|||
|
Current = Previous->Next;
|
|||
|
|
|||
|
while (Current != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// If we found it, make sure reference count is zero
|
|||
|
//
|
|||
|
|
|||
|
if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
|
|||
|
|
|||
|
if (Current->ReferenceCount == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Pull it from the list
|
|||
|
//
|
|||
|
|
|||
|
Previous->Next = Current->Next;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// No longer need to protect our pointer to this
|
|||
|
// record.
|
|||
|
//
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Deallocate the logon session track record.
|
|||
|
//
|
|||
|
|
|||
|
ExFreePool( (PVOID)Current );
|
|||
|
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// reference count was not zero. This is not considered
|
|||
|
// a healthy situation. Return an error and let someone
|
|||
|
// else declare the bug check.
|
|||
|
//
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
return STATUS_BAD_LOGON_SESSION_STATE;
|
|||
|
}
|
|||
|
|
|||
|
Previous = Current;
|
|||
|
Current = Current->Next;
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
//
|
|||
|
// Someone asked us to delete a logon session that isn't
|
|||
|
// in the database.
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_NO_SUCH_LOGON_SESSION;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepInformLsaOfDeletedLogon(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine informs the LSA about the deletion of a logon session.
|
|||
|
|
|||
|
Note that we can not be guaranteed that we are in a whole (or wholesome)
|
|||
|
thread, since we may be in the middle of process deletion and object
|
|||
|
rundown. Therefore, we must queue the work off to a worker thread which
|
|||
|
can then make an LPC call to the LSA.
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID which has been deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSEP_LSA_WORK_ITEM DeleteLogonItem;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Pass the LUID value along with the work queue item.
|
|||
|
// Note that the worker thread is responsible for freeing the WorkItem data
|
|||
|
// structure.
|
|||
|
//
|
|||
|
|
|||
|
DeleteLogonItem = ExAllocatePoolWithTag( PagedPool, sizeof(SEP_LSA_WORK_ITEM), 'wLeS' );
|
|||
|
if (DeleteLogonItem == NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// I don't know what to do here... we loose track of a logon session,
|
|||
|
// but the system isn't really harmed in any way.
|
|||
|
//
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
DeleteLogonItem->CommandParams.LogonId = (*LogonId);
|
|||
|
DeleteLogonItem->CommandNumber = LsapLogonSessionDeletedCommand;
|
|||
|
DeleteLogonItem->CommandParamsLength = sizeof( LUID );
|
|||
|
DeleteLogonItem->ReplyBuffer = NULL;
|
|||
|
DeleteLogonItem->ReplyBufferLength = 0;
|
|||
|
DeleteLogonItem->CleanupFunction = NULL;
|
|||
|
DeleteLogonItem->CleanupParameter = 0;
|
|||
|
DeleteLogonItem->Tag = SepDeleteLogon;
|
|||
|
DeleteLogonItem->CommandParamsMemoryType = SepRmImmediateMemory;
|
|||
|
|
|||
|
if (!SepQueueWorkItem( DeleteLogonItem, TRUE )) {
|
|||
|
|
|||
|
ExFreePool( DeleteLogonItem );
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SeRegisterLogonSessionTerminatedRoutine(
|
|||
|
IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called by file systems that are interested in being
|
|||
|
notified when a logon session is being deleted.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CallbackRoutine - Address of routine to call back when a logon session
|
|||
|
is being deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - Successfully registered routine
|
|||
|
|
|||
|
STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
|
|||
|
|
|||
|
STATUS_INSUFFICIENT_RESOURCE - Unable to allocate list entry.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NewCallback;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (CallbackRoutine == NULL) {
|
|||
|
return( STATUS_INVALID_PARAMETER );
|
|||
|
}
|
|||
|
|
|||
|
NewCallback = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
sizeof(SEP_LOGON_SESSION_TERMINATED_NOTIFICATION),
|
|||
|
'SFeS');
|
|||
|
|
|||
|
if (NewCallback == NULL) {
|
|||
|
return( STATUS_INSUFFICIENT_RESOURCES );
|
|||
|
}
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
NewCallback->Next = SeFileSystemNotifyRoutinesHead.Next;
|
|||
|
|
|||
|
NewCallback->CallbackRoutine = CallbackRoutine;
|
|||
|
|
|||
|
SeFileSystemNotifyRoutinesHead.Next = NewCallback;
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
return( STATUS_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SeUnregisterLogonSessionTerminatedRoutine(
|
|||
|
IN PSE_LOGON_SESSION_TERMINATED_ROUTINE CallbackRoutine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the dual of SeRegisterLogonSessionTerminatedRoutine. A File System
|
|||
|
*MUST* call this before it is unloaded.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CallbackRoutine - Address of routine that was originally passed in to
|
|||
|
SeRegisterLogonSessionTerminatedRoutine.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS - Successfully removed callback routine
|
|||
|
|
|||
|
STATUS_INVALID_PARAMETER - CallbackRoutine is NULL
|
|||
|
|
|||
|
STATUS_NOT_FOUND - Didn't find and entry for CallbackRoutine
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION PreviousEntry;
|
|||
|
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NotifyEntry;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (CallbackRoutine == NULL) {
|
|||
|
return( STATUS_INVALID_PARAMETER );
|
|||
|
}
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
for (PreviousEntry = &SeFileSystemNotifyRoutinesHead,
|
|||
|
NotifyEntry = SeFileSystemNotifyRoutinesHead.Next;
|
|||
|
NotifyEntry != NULL;
|
|||
|
PreviousEntry = NotifyEntry,
|
|||
|
NotifyEntry = NotifyEntry->Next) {
|
|||
|
|
|||
|
if (NotifyEntry->CallbackRoutine == CallbackRoutine)
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (NotifyEntry != NULL) {
|
|||
|
|
|||
|
PreviousEntry->Next = NotifyEntry->Next;
|
|||
|
|
|||
|
ExFreePool( NotifyEntry );
|
|||
|
|
|||
|
Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Status = STATUS_NOT_FOUND;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
return( Status );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
SeMarkLogonSessionForTerminationNotification(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
File systems that have registered for logon-termination notification
|
|||
|
can mark logon sessions they are interested in for callback by calling
|
|||
|
this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - The logon id for which the file system should be notified
|
|||
|
when the logon session is terminated.
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Nothing.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
ULONG SessionArrayIndex;
|
|||
|
PSEP_LOGON_SESSION_REFERENCES Previous, Current;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
SessionArrayIndex = SepLogonSessionIndex( LogonId );
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of reference monitor database
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbWriteLock();
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Now walk the list for our logon session array hash index.
|
|||
|
//
|
|||
|
|
|||
|
Previous = (PSEP_LOGON_SESSION_REFERENCES)
|
|||
|
((PVOID)&SepLogonSessions[ SessionArrayIndex ]);
|
|||
|
Current = Previous->Next;
|
|||
|
|
|||
|
while (Current != NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// If we found it, decrement the reference count and return
|
|||
|
//
|
|||
|
|
|||
|
if (RtlEqualLuid( LogonId, &Current->LogonId) ) {
|
|||
|
Current->Flags |= SEP_TERMINATION_NOTIFY;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
Previous = Current;
|
|||
|
Current = Current->Next;
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbWriteLock();
|
|||
|
|
|||
|
return( (Current != NULL) ? STATUS_SUCCESS : STATUS_NOT_FOUND );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepInformFileSystemsOfDeletedLogon(
|
|||
|
IN PLUID LogonId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine informs interested file systems of a deleted logon.
|
|||
|
|
|||
|
Note that we can not be guaranteed that we are in a whole (or wholesome)
|
|||
|
thread, since we may be in the middle of process deletion and object
|
|||
|
rundown. Therefore, we must queue the work off to a worker thread.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
LogonId - Pointer to the logon session ID which has been deleted.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
FSNotifyContext = ExAllocatePoolWithTag(
|
|||
|
NonPagedPool,
|
|||
|
sizeof(SEP_FILE_SYSTEM_NOTIFY_CONTEXT),
|
|||
|
'SFeS');
|
|||
|
|
|||
|
if (FSNotifyContext == NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// I don't know what to do here... file systems will loose track of a
|
|||
|
// logon session, but the system isn't really harmed in any way.
|
|||
|
//
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
FSNotifyContext->LogonId = *LogonId;
|
|||
|
|
|||
|
ExInitializeWorkItem( &FSNotifyContext->WorkItem,
|
|||
|
(PWORKER_THREAD_ROUTINE) SepNotifyFileSystems,
|
|||
|
(PVOID) FSNotifyContext);
|
|||
|
|
|||
|
ExQueueWorkItem( &FSNotifyContext->WorkItem, DelayedWorkQueue );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SepNotifyFileSystems(
|
|||
|
IN PVOID Context
|
|||
|
)
|
|||
|
{
|
|||
|
PSEP_FILE_SYSTEM_NOTIFY_CONTEXT FSNotifyContext =
|
|||
|
(PSEP_FILE_SYSTEM_NOTIFY_CONTEXT) Context;
|
|||
|
|
|||
|
PSEP_LOGON_SESSION_TERMINATED_NOTIFICATION NextCallback;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Protect modification of the list of FS callbacks.
|
|||
|
//
|
|||
|
|
|||
|
SepRmAcquireDbReadLock();
|
|||
|
|
|||
|
NextCallback = SeFileSystemNotifyRoutinesHead.Next;
|
|||
|
|
|||
|
while (NextCallback != NULL) {
|
|||
|
|
|||
|
NextCallback->CallbackRoutine( &FSNotifyContext->LogonId );
|
|||
|
|
|||
|
NextCallback = NextCallback->Next;
|
|||
|
}
|
|||
|
|
|||
|
SepRmReleaseDbReadLock();
|
|||
|
|
|||
|
ExFreePool( FSNotifyContext );
|
|||
|
}
|
|||
|
|