2036 lines
46 KiB
C++
2036 lines
46 KiB
C++
//+-----------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (c) Microsoft Corporation 1991 - 1992
|
||
//
|
||
// File: SesMgr.c
|
||
//
|
||
// Contents: "Session" manager implementation
|
||
//
|
||
// Functions: InitSessionManager -- Sets up the session manager
|
||
// CreateSession -- Create a session
|
||
// DeleteSession -- Delete a session
|
||
// LocateSession -- Locates a session based on CallerContext
|
||
// GetAndSetSession -- Sticks session in TLS
|
||
// FreeSession -- Frees a session from a thread
|
||
// AddCredHandle -- Adds a cred handle to session
|
||
// DelCredHandle -- Deletes a cred handle from a session
|
||
//
|
||
// History:
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
|
||
#include <lsapch.hxx>
|
||
extern "C"
|
||
{
|
||
#include <adtp.h>
|
||
}
|
||
|
||
NTSTATUS
|
||
LsapCleanUpHandles(
|
||
PSession pSession,
|
||
PVOID Ignored
|
||
);
|
||
|
||
NTSTATUS
|
||
I_DeleteSession(PSession pSession);
|
||
|
||
RTL_CRITICAL_SECTION csSessionMgr;
|
||
|
||
#if DBG
|
||
|
||
ULONG SessionLock;
|
||
|
||
#define LockSessions(x) RtlEnterCriticalSection(&csSessionMgr); SessionLock = x
|
||
#define UnlockSessions() SessionLock = 0; RtlLeaveCriticalSection(&csSessionMgr)
|
||
|
||
#else
|
||
|
||
#define LockSessions(x) RtlEnterCriticalSection(&csSessionMgr)
|
||
#define UnlockSessions() RtlLeaveCriticalSection(&csSessionMgr)
|
||
|
||
#endif
|
||
|
||
#define SM_ICREATE 1
|
||
#define SM_DELETE 2
|
||
#define SM_ADDRUNDOWN 3
|
||
#define SM_DELRUNDOWN 4
|
||
#define SM_ADDHANDLE 5
|
||
#define SM_DELHANDLE 6
|
||
#define SM_VALIDHANDLE 7
|
||
#define SM_CLONE 9
|
||
#define SM_CLEANUP 10
|
||
#define SM_FINDEFS 11
|
||
#define SM_UPDATEEFS 12
|
||
#define SM_ADDCONNECT 13
|
||
|
||
|
||
PSession pDefaultSession;
|
||
PSession pEfsSession ;
|
||
|
||
LIST_ENTRY SessionList ;
|
||
LIST_ENTRY SessionConnectList ;
|
||
|
||
|
||
VOID
|
||
LsapContextRundown(
|
||
PSecHandle phContext,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
);
|
||
|
||
VOID
|
||
LsapCredentialRundown(
|
||
PSecHandle phCreds,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
);
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: InitSessionManager()
|
||
//
|
||
// Synopsis: Initializes whatever is needed to track sessions
|
||
//
|
||
// Effects: csSessionMgr, psSessionList;
|
||
//
|
||
// Arguments: void
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns: TRUE if success, FALSE otherwise.
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
BOOL
|
||
InitSessionManager(void)
|
||
{
|
||
NTSTATUS scRet = STATUS_SUCCESS;
|
||
PSession pSession;
|
||
Session sSess;
|
||
|
||
//
|
||
// Fake a session during init:
|
||
//
|
||
|
||
|
||
SetCurrentPackageId( SPMGR_ID );
|
||
|
||
SetCurrentSession( &sSess );
|
||
|
||
scRet = RtlInitializeCriticalSection(&csSessionMgr);
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
SmallHandlePackage.Initialize();
|
||
LargeHandlePackage.Initialize();
|
||
|
||
InitializeListHead( &SessionList );
|
||
|
||
InitializeListHead( &SessionConnectList );
|
||
|
||
scRet = CreateSession(
|
||
&NtCurrentTeb()->ClientId,
|
||
FALSE,
|
||
LSA_PROCESS_NAME,
|
||
0, // no flags
|
||
&pSession
|
||
);
|
||
|
||
if (FAILED(scRet))
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
pSession->fSession |= SESFLAG_DEFAULT | SESFLAG_TCB_PRIV ;
|
||
|
||
pDefaultSession = pSession;
|
||
|
||
SetCurrentSession( pSession );
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
VOID
|
||
LsapFindEfsSession(
|
||
VOID
|
||
)
|
||
{
|
||
PLIST_ENTRY Scan ;
|
||
PSession pSession ;
|
||
|
||
LockSessions( SM_FINDEFS );
|
||
|
||
Scan = SessionList.Flink ;
|
||
|
||
while ( Scan != &SessionList )
|
||
{
|
||
pSession = CONTAINING_RECORD( Scan, Session, List );
|
||
|
||
if ( (pSession->dwProcessID == pDefaultSession->dwProcessID) &&
|
||
((pSession->fSession & SESFLAG_KERNEL) != 0 ) )
|
||
{
|
||
pEfsSession = pSession ;
|
||
break;
|
||
}
|
||
|
||
Scan = Scan->Flink ;
|
||
}
|
||
|
||
UnlockSessions();
|
||
|
||
if ( !pEfsSession )
|
||
{
|
||
DebugLog(( DEB_ERROR, "EFS Session not found\n" ));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
LsapUpdateEfsSession(
|
||
PSession pSession
|
||
)
|
||
{
|
||
if ( !pEfsSession )
|
||
{
|
||
return ;
|
||
}
|
||
|
||
LockSessions( SM_UPDATEEFS );
|
||
LockSession( pSession );
|
||
LockSession( pEfsSession );
|
||
|
||
pEfsSession->SharedData = pSession->SharedData ;
|
||
pSession->SharedData->cRefs++ ;
|
||
pEfsSession->fSession |= SESFLAG_EFS ;
|
||
|
||
UnlockSession( pEfsSession );
|
||
UnlockSession( pSession );
|
||
UnlockSessions();
|
||
|
||
}
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: CreateSession()
|
||
//
|
||
// Synopsis: Creates a new session.
|
||
//
|
||
// Effects: Session list.
|
||
//
|
||
// Arguments: fOpenImmediate - TRUE indicates the process should be opened
|
||
//
|
||
// ppSession - receives a pointer to the session.
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
CreateSession( CLIENT_ID * pClientId,
|
||
BOOL fOpenImmediate,
|
||
PWCHAR ClientProcessName,
|
||
ULONG Flags,
|
||
PSession * ppSession)
|
||
{
|
||
NTSTATUS scRet = STATUS_SUCCESS;
|
||
PSession pSession;
|
||
LPWSTR ClientName;
|
||
PLIST_ENTRY Scan ;
|
||
PLSAP_SESSION_CONNECT Connect ;
|
||
ULONG ConnectType = 0 ;
|
||
|
||
DebugLog(( DEB_TRACE, "Creating session for [%x.%x]\n",
|
||
pClientId->UniqueProcess, pClientId->UniqueThread ));
|
||
|
||
*ppSession = NULL;
|
||
|
||
if ( *ClientProcessName )
|
||
{
|
||
ConnectType |= SESSION_CONNECT_TRUSTED ;
|
||
|
||
ClientName = (LPWSTR) LsapAllocatePrivateHeap(
|
||
(wcslen(ClientProcessName)+1) * sizeof(WCHAR));
|
||
|
||
if (ClientName == NULL)
|
||
{
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
|
||
wcscpy(ClientName,ClientProcessName);
|
||
}
|
||
else
|
||
{
|
||
ConnectType |= SESSION_CONNECT_UNTRUSTED ;
|
||
|
||
ClientName = NULL;
|
||
}
|
||
|
||
|
||
pSession = (PSession) LsapAllocatePrivateHeap( sizeof( Session ) );
|
||
if (!pSession)
|
||
{
|
||
*ppSession = NULL;
|
||
if( ClientName != NULL )
|
||
{
|
||
LsapFreePrivateHeap( ClientName );
|
||
}
|
||
|
||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||
}
|
||
RtlZeroMemory(pSession, sizeof(Session));
|
||
|
||
//
|
||
// Initialize stuff:
|
||
//
|
||
|
||
pSession->fSession = Flags;
|
||
|
||
//
|
||
// we check for this much later, after some same initializing
|
||
// steps, so we can use the common cleanup
|
||
//
|
||
|
||
scRet = RtlInitializeCriticalSection( &pSession->SessionLock );
|
||
|
||
InitializeListHead( &pSession->SectionList );
|
||
InitializeListHead( &pSession->RundownList );
|
||
|
||
pSession->ClientProcessName = ClientName;
|
||
pSession->dwProcessID = HandleToUlong(pClientId->UniqueProcess);
|
||
|
||
//
|
||
// Store the handle cleanup as a rundown function
|
||
//
|
||
|
||
if ( NT_SUCCESS( scRet ) )
|
||
{
|
||
if ( !AddRundown( pSession,
|
||
LsapCleanUpHandles,
|
||
NULL ) )
|
||
{
|
||
scRet = STATUS_NO_MEMORY ;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Lock the sessions now so we know that no new kernel sessions
|
||
// will be created
|
||
//
|
||
|
||
LockSessions(SM_ICREATE);
|
||
|
||
//
|
||
// Add the session to the list
|
||
//
|
||
|
||
InsertTailList( &SessionList, &pSession->List );
|
||
|
||
//
|
||
// *Now* check if we're doing ok:
|
||
//
|
||
|
||
if ( !NT_SUCCESS( scRet ))
|
||
{
|
||
UnlockSessions();
|
||
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// If the caller is from kernel mode, look for an existing kernel
|
||
// session to use the handle list from.
|
||
//
|
||
|
||
if ((Flags & SESFLAG_MAYBEKERNEL) != 0)
|
||
{
|
||
PSession pTrace = NULL;
|
||
|
||
//
|
||
// Find a kernel-mode session and use its handle list. Make sure
|
||
// it's not the default LSA session, although it is ok to use the
|
||
// session tagged as the EFS one. This will keep the EFS session
|
||
// and the (primary) rdr session in sync.
|
||
//
|
||
|
||
Scan = SessionList.Flink ;
|
||
|
||
while ( Scan != &SessionList )
|
||
{
|
||
pTrace = CONTAINING_RECORD( Scan, Session, List );
|
||
|
||
if ( pTrace != pSession )
|
||
{
|
||
if ( ( (pTrace->fSession & SESFLAG_KERNEL) != 0 ) &&
|
||
( ( (pTrace->fSession & SESFLAG_EFS) != 0 ) ||
|
||
( pTrace->dwProcessID != pDefaultSession->dwProcessID ) ) )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
pTrace = NULL ;
|
||
|
||
Scan = Scan->Flink ;
|
||
|
||
}
|
||
|
||
//
|
||
// If we found a session, use its handle list and queue
|
||
//
|
||
|
||
if (pTrace != NULL)
|
||
{
|
||
pTrace->SharedData->cRefs++;
|
||
pSession->SharedData = pTrace->SharedData;
|
||
DebugLog(( DEB_TRACE, "Linking session %p to %p\n",
|
||
pSession, pTrace ));
|
||
}
|
||
|
||
//
|
||
// ConnectType is not definite, it is a hint to others
|
||
// watching for new sessions
|
||
//
|
||
|
||
ConnectType |= SESSION_CONNECT_KERNEL ;
|
||
}
|
||
|
||
//
|
||
// If we don't have a handle list yet, create one and set it to NULL
|
||
//
|
||
|
||
if (pSession->SharedData == NULL)
|
||
{
|
||
if ( pSession->fSession & SESFLAG_MAYBEKERNEL )
|
||
{
|
||
pSession->SharedData = (PLSAP_SHARED_SESSION_DATA) LsapAllocatePrivateHeap(
|
||
sizeof( LSAP_SHARED_SESSION_DATA ) );
|
||
}
|
||
else
|
||
{
|
||
pSession->SharedData = &pSession->DefaultData ;
|
||
}
|
||
|
||
if ( pSession->SharedData )
|
||
{
|
||
|
||
RtlZeroMemory(
|
||
pSession->SharedData,
|
||
sizeof( LSAP_SHARED_SESSION_DATA ) );
|
||
|
||
//
|
||
// Create Handle Tables:
|
||
//
|
||
|
||
pSession->SharedData->CredHandlePackage = &SmallHandlePackage ;
|
||
pSession->SharedData->ContextHandlePackage = &LargeHandlePackage ;
|
||
|
||
pSession->SharedData->CredTable = pSession->SharedData->CredHandlePackage->Create(
|
||
HANDLE_PACKAGE_CALLBACK_ON_DELETE,
|
||
NULL,
|
||
LsapCredentialRundown );
|
||
|
||
pSession->SharedData->ContextTable = pSession->SharedData->ContextHandlePackage->Create(
|
||
HANDLE_PACKAGE_CALLBACK_ON_DELETE,
|
||
NULL,
|
||
LsapContextRundown );
|
||
|
||
if ((pSession->SharedData->CredTable == NULL) || (pSession->SharedData->ContextTable == NULL))
|
||
{
|
||
scRet = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
pSession->SharedData->cRefs = 1;
|
||
}
|
||
else
|
||
{
|
||
scRet = STATUS_INSUFFICIENT_RESOURCES ;
|
||
}
|
||
|
||
}
|
||
|
||
UnlockSessions();
|
||
|
||
//
|
||
// Check for callbacks when a client connects. Note, this does
|
||
// not need to be under the session list lock, because it is
|
||
// sufficient that no client is using the session until the
|
||
// callbacks are complete. Since the connection attempt is
|
||
// stalled until this returns, that requirement is met.
|
||
//
|
||
|
||
Scan = SessionConnectList.Flink ;
|
||
while ( Scan != &SessionConnectList )
|
||
{
|
||
Connect = CONTAINING_RECORD( Scan, LSAP_SESSION_CONNECT, List );
|
||
|
||
if ( Connect->ConnectFilter & ConnectType )
|
||
{
|
||
Connect->Callback( pSession, Connect->Parameter );
|
||
}
|
||
|
||
Scan = Scan->Flink ;
|
||
}
|
||
|
||
|
||
*ppSession = pSession ;
|
||
|
||
if (fOpenImmediate & (NT_SUCCESS(scRet)))
|
||
{
|
||
scRet = LsapOpenCaller(pSession);
|
||
}
|
||
|
||
//
|
||
// If we failed somewhere, cleanup now.
|
||
//
|
||
|
||
Cleanup:
|
||
|
||
if (!NT_SUCCESS(scRet))
|
||
{
|
||
I_DeleteSession(pSession);
|
||
*ppSession = NULL;
|
||
}
|
||
return(scRet);
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: CloneSession
|
||
//
|
||
// Synopsis: Temporary copy of a session for scavenger threads
|
||
//
|
||
// Arguments: [pOriginalSession] --
|
||
// [ppSession] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
CloneSession(
|
||
PSession pOriginalSession,
|
||
PSession * ppSession,
|
||
ULONG Flags )
|
||
{
|
||
PSession pSession;
|
||
NTSTATUS Status ;
|
||
BOOL LockInitialized = FALSE ;
|
||
|
||
pSession = (PSession) LsapAllocatePrivateHeap( sizeof( Session ) );
|
||
|
||
if ( !pSession )
|
||
{
|
||
*ppSession = NULL ;
|
||
|
||
return STATUS_NO_MEMORY ;
|
||
}
|
||
|
||
//
|
||
// Make sure there is no one else mucking with general session stuff
|
||
//
|
||
|
||
LockSessions(SM_CLONE);
|
||
|
||
Status = STATUS_SUCCESS ;
|
||
|
||
//
|
||
// Copy all the interesting bits
|
||
//
|
||
|
||
CopyMemory(pSession, pOriginalSession, sizeof(Session));
|
||
|
||
//
|
||
// Make sure it has its own critical section
|
||
//
|
||
|
||
Status = RtlInitializeCriticalSection( &pSession->SessionLock );
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
LockInitialized = TRUE ;
|
||
}
|
||
|
||
//
|
||
// note that it is a clone
|
||
//
|
||
|
||
pSession->fSession |= ( SESFLAG_CLONE | Flags );
|
||
|
||
//
|
||
// Initialize our own rundown list.
|
||
//
|
||
|
||
InitializeListHead( &pSession->RundownList );
|
||
|
||
//
|
||
// Use our own rundown
|
||
//
|
||
|
||
if ( AddRundown( pSession, LsapCleanUpHandles, NULL ) )
|
||
{
|
||
pOriginalSession->SharedData->cRefs++;
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_NO_MEMORY ;
|
||
}
|
||
|
||
UnlockSessions();
|
||
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
|
||
if ( LockInitialized )
|
||
{
|
||
RtlDeleteCriticalSection( &pSession->SessionLock );
|
||
}
|
||
LsapFreePrivateHeap( pSession );
|
||
|
||
*ppSession = NULL ;
|
||
|
||
return Status ;
|
||
}
|
||
|
||
//
|
||
// Set the reference count of the clone to -1, so that the a single
|
||
// ref/deref will kill it.
|
||
//
|
||
|
||
pSession->RefCount = -1;
|
||
|
||
//
|
||
// Clones do *NOT* get added to the session list.
|
||
//
|
||
|
||
*ppSession = pSession;
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
NTSTATUS
|
||
CreateShadowSession(
|
||
DWORD ProcessId,
|
||
PSession * NewSession
|
||
)
|
||
{
|
||
NTSTATUS Status ;
|
||
CLIENT_ID ClientId;
|
||
PSession Session ;
|
||
|
||
|
||
ClientId.UniqueProcess = (HANDLE) LongToHandle(ProcessId) ;
|
||
ClientId.UniqueThread = NULL ;
|
||
|
||
Status = CreateSession(
|
||
&ClientId,
|
||
FALSE,
|
||
L"",
|
||
SESFLAG_SHADOW,
|
||
&Session );
|
||
|
||
*NewSession = Session ;
|
||
|
||
return Status ;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
WINAPI
|
||
LsapDeleteContextWrap(
|
||
PSecHandle Handle,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
)
|
||
{
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
CallInfo->CallInfo.CallCount = RefCount ;
|
||
|
||
WLsaDeleteContext( Handle );
|
||
|
||
CallInfo->CallInfo.CallCount = 0 ;
|
||
}
|
||
|
||
VOID
|
||
WINAPI
|
||
LsapFreeCredWrap(
|
||
PSecHandle Handle,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
)
|
||
{
|
||
PLSA_CALL_INFO CallInfo ;
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
|
||
CallInfo->CallInfo.CallCount = RefCount ;
|
||
|
||
WLsaFreeCredHandle( Handle );
|
||
|
||
CallInfo->CallInfo.CallCount = 0;
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapCleanUpHandles
|
||
//
|
||
// Synopsis: Closes all context and credential handles for a session
|
||
//
|
||
// Arguments: [pSession] --
|
||
// [Ignored] --
|
||
//
|
||
// History: 5-15-97 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapCleanUpHandles(
|
||
PSession pSession,
|
||
PVOID Ignored
|
||
)
|
||
{
|
||
NTSTATUS scRet = STATUS_SUCCESS;
|
||
PSession pSave;
|
||
ULONG HandleRefs;
|
||
PLIST_ENTRY ListEntry;
|
||
LSA_CALL_INFO CallInfo ;
|
||
HANDLE hImp ;
|
||
|
||
|
||
//
|
||
// If this is the last user of the handle lists, cleanup
|
||
//
|
||
|
||
if ( pSession->SharedData == NULL )
|
||
{
|
||
return STATUS_SUCCESS ;
|
||
}
|
||
|
||
LockSessions(SM_CLEANUP);
|
||
|
||
pSession->SharedData->cRefs--;
|
||
HandleRefs = pSession->SharedData->cRefs;
|
||
|
||
UnlockSessions();
|
||
|
||
if (HandleRefs == 0)
|
||
{
|
||
|
||
LsapInitializeCallInfo( &CallInfo,
|
||
FALSE );
|
||
|
||
CallInfo.CallInfo.Attributes |= SECPKG_CALL_CLEANUP ;
|
||
|
||
LsapSetCurrentCall( &CallInfo );
|
||
|
||
pSave = GetCurrentSession();
|
||
|
||
SetCurrentSession( pSession );
|
||
|
||
|
||
if (pSession->SharedData->ContextTable != NULL)
|
||
{
|
||
pSession->SharedData->ContextHandlePackage->Delete( pSession->SharedData->ContextTable,
|
||
LsapDeleteContextWrap );
|
||
}
|
||
|
||
if (pSession->SharedData->CredTable != NULL)
|
||
{
|
||
pSession->SharedData->CredHandlePackage->Delete( pSession->SharedData->CredTable,
|
||
LsapFreeCredWrap );
|
||
}
|
||
|
||
if ( pSession->fSession & SESFLAG_KERNEL )
|
||
{
|
||
LsapFreePrivateHeap( pSession->SharedData );
|
||
}
|
||
|
||
SetCurrentSession( pSave );
|
||
|
||
LsapSetCurrentCall( NULL );
|
||
}
|
||
|
||
pSession->SharedData = NULL;
|
||
|
||
return(scRet);
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: I_DeleteSession()
|
||
//
|
||
// Synopsis: Deletes the session indicated
|
||
//
|
||
// Effects: Frees memory
|
||
//
|
||
// Arguments: pSession Session to delete
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
NTSTATUS
|
||
I_DeleteSession(PSession pSession)
|
||
{
|
||
PSession pTrace;
|
||
PLIST_ENTRY List ;
|
||
PLSAP_SESSION_RUNDOWN Rundown ;
|
||
int i;
|
||
|
||
DebugLog(( DEB_TRACE, "DeleteSession( %x )\n", pSession ));
|
||
|
||
DsysAssertMsg(pSession, "DeleteSession passed null pointer");
|
||
|
||
pSession->fSession |= SESFLAG_CLEANUP;
|
||
|
||
|
||
//
|
||
// Clones aren't in the list, so don't try to unlink it
|
||
//
|
||
|
||
if ( ( pSession->fSession & SESFLAG_CLONE ) == 0 )
|
||
{
|
||
LockSessions(SM_DELETE);
|
||
|
||
RemoveEntryList( &pSession->List );
|
||
|
||
UnlockSessions();
|
||
}
|
||
|
||
//
|
||
// Execute the rundown functions
|
||
//
|
||
|
||
LockSession( pSession );
|
||
|
||
while ( !IsListEmpty( &pSession->RundownList ) )
|
||
{
|
||
List = RemoveHeadList( &pSession->RundownList );
|
||
|
||
Rundown = CONTAINING_RECORD( List, LSAP_SESSION_RUNDOWN, List );
|
||
|
||
Rundown->Rundown( pSession, Rundown->Parameter );
|
||
|
||
LsapFreePrivateHeap( Rundown );
|
||
}
|
||
|
||
UnlockSession( pSession );
|
||
|
||
RtlDeleteCriticalSection( &pSession->SessionLock );
|
||
|
||
if (pSession->fSession & SESFLAG_CLONE)
|
||
{
|
||
//
|
||
// Clones are not part of the global list, and are
|
||
// around just for bookkeepping for scavenger threads
|
||
//
|
||
|
||
pSession->dwProcessID = 0xFFFFFFFF;
|
||
|
||
LsapFreePrivateHeap( pSession );
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
//
|
||
// Close our handles
|
||
//
|
||
|
||
if (pSession->hProcess)
|
||
NtClose(pSession->hProcess);
|
||
|
||
if (pSession->hPort)
|
||
{
|
||
NtClose(pSession->hPort);
|
||
}
|
||
|
||
pSession->dwProcessID = 0xFFFFFFFF;
|
||
|
||
|
||
if( pSession->ClientProcessName )
|
||
{
|
||
LsapFreePrivateHeap( pSession->ClientProcessName );
|
||
}
|
||
|
||
LsapFreePrivateHeap( pSession );
|
||
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
HRESULT
|
||
LsapDeleteWorkQueue(
|
||
PSession pSession,
|
||
PVOID Parameter
|
||
)
|
||
{
|
||
if ( pSession->SharedData->pQueue )
|
||
{
|
||
DeleteSubordinateQueue( pSession->SharedData->pQueue, 0 );
|
||
|
||
pSession->SharedData->pQueue = NULL ;
|
||
}
|
||
|
||
return STATUS_SUCCESS ;
|
||
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: SpmpReferenceSession
|
||
//
|
||
// Synopsis: Ups the ref count on a session
|
||
//
|
||
// Arguments: [pSession] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
VOID
|
||
SpmpReferenceSession(
|
||
PSession pSession)
|
||
{
|
||
InterlockedIncrement(&pSession->RefCount);
|
||
}
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: SpmpDereferenceSession
|
||
//
|
||
// Synopsis: Derefs a session. If the session goes negative, it gets
|
||
// deleted.
|
||
//
|
||
// Arguments: [pSession] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
VOID
|
||
SpmpDereferenceSession(
|
||
PSession pSession)
|
||
{
|
||
LONG RefCount = InterlockedDecrement(&pSession->RefCount);
|
||
|
||
if( RefCount < 0 )
|
||
{
|
||
if ( pSession == pDefaultSession )
|
||
{
|
||
pSession->RefCount = 1 ;
|
||
}
|
||
else
|
||
{
|
||
DsysAssert( (pSession->RefCount == -1) && (RefCount == -1) );
|
||
I_DeleteSession(pSession);
|
||
}
|
||
}
|
||
}
|
||
|
||
VOID
|
||
LsapSessionDisconnect(
|
||
PSession pSession
|
||
)
|
||
{
|
||
if ( pSession->SharedData->cRefs == 1 )
|
||
{
|
||
LsapDeleteWorkQueue( pSession, NULL );
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: FreeSession
|
||
//
|
||
// Synopsis: Frees a session
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
void
|
||
FreeSession(PSession pSession)
|
||
{
|
||
if (pSession == NULL)
|
||
{
|
||
pSession = GetCurrentSession();
|
||
}
|
||
|
||
if (!pSession)
|
||
{
|
||
DebugLog((DEB_ERROR, "FreeSession: No Session?\n"));
|
||
return;
|
||
}
|
||
|
||
TlsSetValue(dwSession, pDefaultSession);
|
||
}
|
||
|
||
|
||
//
|
||
// Rundown Semantics:
|
||
//
|
||
// Rundowns allow other functions to be called when a session is closed. This
|
||
// is useful if you need to keep something around as long as a client is
|
||
// connected, but need to clean up afterwards.
|
||
//
|
||
// Rules: You cannot call back into or reference the client process. This is
|
||
// because the process has already terminated.
|
||
//
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: AddRundown
|
||
//
|
||
// Synopsis: Adds a function to be called when the session is terminated
|
||
//
|
||
// Arguments: [pSession] --
|
||
// [RundownFn] --
|
||
// [pvParameter] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
BOOL
|
||
AddRundown(
|
||
PSession pSession,
|
||
PLSAP_SESSION_RUNDOWN_FN RundownFn,
|
||
PVOID pvParameter)
|
||
{
|
||
PLSAP_SESSION_RUNDOWN Rundown ;
|
||
|
||
Rundown = (PLSAP_SESSION_RUNDOWN) LsapAllocatePrivateHeap(
|
||
sizeof( LSAP_SESSION_RUNDOWN ) );
|
||
|
||
if ( Rundown )
|
||
{
|
||
Rundown->Rundown = RundownFn ;
|
||
Rundown->Parameter = pvParameter ;
|
||
|
||
LockSession( pSession );
|
||
|
||
InsertTailList( &pSession->RundownList, &Rundown->List );
|
||
|
||
UnlockSession( pSession );
|
||
|
||
return TRUE ;
|
||
}
|
||
|
||
return FALSE ;
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: DelRundown
|
||
//
|
||
// Synopsis: Removes a rundown function from a session
|
||
//
|
||
// Arguments: [pSession] --
|
||
// [RundownFn] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
BOOL
|
||
DelRundown(
|
||
PSession pSession,
|
||
PLSAP_SESSION_RUNDOWN_FN RundownFn
|
||
)
|
||
{
|
||
PLIST_ENTRY Scan;
|
||
PLSAP_SESSION_RUNDOWN Rundown ;
|
||
|
||
LockSession( pSession );
|
||
|
||
Scan = pSession->RundownList.Flink ;
|
||
|
||
Rundown = NULL ;
|
||
|
||
while ( Scan != &pSession->RundownList )
|
||
{
|
||
Rundown = (PLSAP_SESSION_RUNDOWN) Scan ;
|
||
|
||
if ( Rundown->Rundown == RundownFn )
|
||
{
|
||
RemoveEntryList( &Rundown->List );
|
||
|
||
break;
|
||
}
|
||
|
||
Rundown = NULL ;
|
||
|
||
Scan = Scan->Flink ;
|
||
}
|
||
|
||
UnlockSession( pSession );
|
||
|
||
if ( Rundown )
|
||
{
|
||
LsapFreePrivateHeap( Rundown );
|
||
|
||
return TRUE ;
|
||
}
|
||
|
||
return FALSE ;
|
||
|
||
}
|
||
|
||
BOOL
|
||
AddConnectionHook(
|
||
PLSAP_SESSION_CONNECT_FN ConnectFn,
|
||
PVOID Parameter,
|
||
ULONG Filter
|
||
)
|
||
{
|
||
PLSAP_SESSION_CONNECT Connect ;
|
||
|
||
Connect = (PLSAP_SESSION_CONNECT) LsapAllocatePrivateHeap( sizeof( LSAP_SESSION_CONNECT ) );
|
||
|
||
if ( Connect )
|
||
{
|
||
Connect->Callback = ConnectFn ;
|
||
Connect->ConnectFilter = Filter ;
|
||
Connect->Parameter = Parameter ;
|
||
|
||
LockSessions( SM_ADDCONNECT );
|
||
|
||
InsertTailList( &SessionConnectList, &Connect->List );
|
||
|
||
UnlockSessions();
|
||
}
|
||
|
||
return (Connect != NULL) ;
|
||
}
|
||
|
||
|
||
VOID
|
||
LsapCredentialRundown(
|
||
PSecHandle phCreds,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
)
|
||
{
|
||
PSession pSession = (PSession) Context ;
|
||
NTSTATUS scRet;
|
||
PLSAP_SECURITY_PACKAGE pPackage;
|
||
PSession Previous ;
|
||
|
||
|
||
Previous = GetCurrentSession();
|
||
|
||
if ( ( ( pSession->fSession & SESFLAG_KERNEL ) != 0 ) &&
|
||
( ( Previous->fSession & SESFLAG_KERNEL ) != 0 ) )
|
||
{
|
||
NOTHING ;
|
||
}
|
||
else
|
||
{
|
||
SetCurrentSession( pSession );
|
||
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "[%x] CredentialRundown (%p:%p) RefCount=%lu\n",
|
||
pSession->dwProcessID, phCreds->dwUpper, phCreds->dwLower, RefCount));
|
||
|
||
pPackage = SpmpValidRequest(phCreds->dwLower,
|
||
SP_ORDINAL_FREECREDHANDLE );
|
||
|
||
if (pPackage)
|
||
{
|
||
PLSA_CALL_INFO CallInfo;
|
||
ULONG OldRefCount;
|
||
|
||
SetCurrentPackageId(phCreds->dwLower);
|
||
|
||
StartCallToPackage( pPackage );
|
||
|
||
ASSERT( RefCount );
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
OldRefCount = CallInfo->CallInfo.CallCount;
|
||
CallInfo->CallInfo.CallCount = RefCount;
|
||
|
||
__try
|
||
{
|
||
scRet = pPackage->FunctionTable.FreeCredentialsHandle(
|
||
phCreds->dwUpper);
|
||
}
|
||
__except (SP_EXCEPTION)
|
||
{
|
||
scRet = GetExceptionCode();
|
||
scRet = SPException(scRet, phCreds->dwLower);
|
||
}
|
||
|
||
CallInfo->CallInfo.CallCount = OldRefCount;
|
||
|
||
EndCallToPackage( pPackage );
|
||
|
||
LsapDelPackageHandle( pPackage, FALSE );
|
||
}
|
||
|
||
SetCurrentSession( Previous );
|
||
}
|
||
|
||
|
||
VOID
|
||
LsapContextRundown(
|
||
PSecHandle phContext,
|
||
PVOID Context,
|
||
ULONG RefCount
|
||
)
|
||
{
|
||
PSession Session = (PSession) Context;
|
||
PSession Previous ;
|
||
PLSAP_SECURITY_PACKAGE pspPackage;
|
||
PLSA_CALL_INFO CallInfo;
|
||
ULONG OldRefCount;
|
||
|
||
NTSTATUS scRet ;
|
||
|
||
|
||
Previous = GetCurrentSession();
|
||
|
||
if ( ( ( Session->fSession & SESFLAG_KERNEL ) != 0 ) &&
|
||
( ( Previous->fSession & SESFLAG_KERNEL ) != 0 ) )
|
||
{
|
||
NOTHING ;
|
||
}
|
||
else
|
||
{
|
||
SetCurrentSession( Session );
|
||
|
||
}
|
||
|
||
|
||
pspPackage = SpmpValidRequest( phContext->dwLower,
|
||
SP_ORDINAL_DELETECTXT);
|
||
|
||
if (! pspPackage )
|
||
{
|
||
DebugLog((DEB_ERROR,"[%x] Invalid request for DeleteContext, package: %d\n",
|
||
Session->dwProcessID, phContext->dwLower));
|
||
return ;
|
||
}
|
||
|
||
DebugLog(( DEB_TRACE, "[%x] ContextRundown(%p:%p)\n",
|
||
Session->dwProcessID, phContext->dwUpper,
|
||
phContext->dwLower ));
|
||
|
||
SetCurrentPackageId(phContext->dwLower);
|
||
|
||
StartCallToPackage( pspPackage );
|
||
|
||
|
||
//
|
||
// RefCount should ALWAYS be 1 currently, as, the context handle code
|
||
// assumes context handle issue count never exceeds 1.
|
||
//
|
||
|
||
ASSERT( RefCount == 1 );
|
||
|
||
CallInfo = LsapGetCurrentCall();
|
||
OldRefCount = CallInfo->CallInfo.CallCount;
|
||
CallInfo->CallInfo.CallCount = RefCount;
|
||
|
||
__try
|
||
{
|
||
scRet = pspPackage->FunctionTable.DeleteContext( phContext->dwUpper );
|
||
}
|
||
__except (SP_EXCEPTION)
|
||
{
|
||
scRet = GetExceptionCode();
|
||
scRet = SPException( scRet, pspPackage->dwPackageID);
|
||
}
|
||
|
||
CallInfo->CallInfo.CallCount = OldRefCount;
|
||
EndCallToPackage( pspPackage );
|
||
|
||
#if DBG
|
||
if ( !NT_SUCCESS( scRet ) )
|
||
{
|
||
DebugLog((DEB_ERROR, "[%x] package %ws failed DeleteContext with %x\n",
|
||
Session->dwProcessID,
|
||
pspPackage->Name.Buffer,
|
||
scRet ));
|
||
|
||
}
|
||
#endif
|
||
|
||
DebugLog(( DEB_TRACE_WAPI, "[%x] return code %x\n", Session->dwProcessID,
|
||
scRet ));
|
||
|
||
|
||
SetCurrentPackageId( SPMGR_ID );
|
||
|
||
SetCurrentSession( Previous );
|
||
|
||
LsapDelPackageHandle( pspPackage, TRUE );
|
||
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------------
|
||
//
|
||
// Function: AddCredHandle
|
||
//
|
||
// Synopsis: Adds an obtained cred handle to the list for this session
|
||
//
|
||
// Effects:
|
||
//
|
||
// Arguments:
|
||
//
|
||
// Requires:
|
||
//
|
||
// Returns:
|
||
//
|
||
// Notes:
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
BOOLEAN
|
||
AddCredHandle( PSession pSession,
|
||
PCredHandle phCred,
|
||
ULONG Flags)
|
||
{
|
||
|
||
if (pSession->fSession & SESFLAG_CLONE)
|
||
{
|
||
DebugLog((DEB_ERROR, "Attempt to add a credhandle to a clone session\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
if ( pSession->fSession & SESFLAG_KERNEL )
|
||
{
|
||
pSession = pEfsSession ;
|
||
}
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Adding Cred %p : %p to %p\n",
|
||
phCred->dwUpper, phCred->dwLower, pSession ));
|
||
|
||
|
||
if(pSession->SharedData->CredHandlePackage->AddHandle(
|
||
pSession->SharedData->CredTable,
|
||
phCred,
|
||
pSession,
|
||
Flags))
|
||
{
|
||
|
||
LsapAddPackageHandle( phCred->dwLower, FALSE );
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: AddContextHandle
|
||
//
|
||
// Synopsis: Adds a context handle to this session
|
||
//
|
||
// Arguments: [phContext] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
BOOLEAN
|
||
AddContextHandle( PSession pSession,
|
||
PCtxtHandle phContext,
|
||
ULONG Flags)
|
||
{
|
||
if (pSession->fSession & SESFLAG_CLONE)
|
||
{
|
||
DebugLog((DEB_ERROR, "Attempt to add a ctxthandle to a clone session\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
if ( pSession->fSession & SESFLAG_KERNEL )
|
||
{
|
||
pSession = pEfsSession ;
|
||
}
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Adding Context %p : %p to %p\n",
|
||
phContext->dwUpper, phContext->dwLower, pSession ));
|
||
|
||
|
||
//
|
||
// Find out where this 0:0 handle is coming from:
|
||
//
|
||
|
||
DsysAssertMsg( (phContext->dwLower | phContext->dwUpper), "Null context handle added\n");
|
||
|
||
if(pSession->SharedData->ContextHandlePackage->AddHandle(
|
||
pSession->SharedData->ContextTable,
|
||
phContext,
|
||
pSession,
|
||
Flags
|
||
))
|
||
{
|
||
LsapAddPackageHandle( phContext->dwLower, TRUE );
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: ValidateContextHandle
|
||
//
|
||
// Synopsis: Validate the context handle against the session list
|
||
//
|
||
// Arguments: [pSession] --
|
||
// [phContext] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
ValidateContextHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phContext,
|
||
PVOID * pKey
|
||
)
|
||
{
|
||
|
||
*pKey = pSession->SharedData->ContextHandlePackage->RefHandle(
|
||
pSession->SharedData->ContextTable,
|
||
phContext );
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Validate context (%p : %p) for %p returned %p\n",
|
||
phContext->dwUpper, phContext->dwLower,
|
||
pSession, *pKey ));
|
||
|
||
if ( *pKey )
|
||
{
|
||
return SEC_E_OK ;
|
||
}
|
||
else
|
||
{
|
||
return SEC_E_INVALID_HANDLE ;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
DerefContextHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phContext,
|
||
PVOID Key OPTIONAL
|
||
)
|
||
{
|
||
if ( Key )
|
||
{
|
||
#if DBG
|
||
PSEC_HANDLE_ENTRY Entry = (PSEC_HANDLE_ENTRY) Key ;
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Deref context handle by key ( %p : %p ) for %p \n",
|
||
Entry->Handle.dwUpper, Entry->Handle.dwLower,
|
||
pSession ));
|
||
#endif
|
||
pSession->SharedData->ContextHandlePackage->DerefHandleKey(
|
||
pSession->SharedData->ContextTable,
|
||
Key );
|
||
|
||
}
|
||
else
|
||
{
|
||
pSession->SharedData->ContextHandlePackage->DeleteHandle(
|
||
pSession->SharedData->ContextTable,
|
||
phContext,
|
||
0 );
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Deref context handle by handle (%p : %p) for %p\n",
|
||
phContext->dwUpper, phContext->dwLower,
|
||
pSession ));
|
||
}
|
||
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ValidateAndDerefContextHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phContext
|
||
)
|
||
{
|
||
DebugLog(( DEB_TRACE_HANDLES, "ValidateAndDeref Context (%p : %p)\n",
|
||
phContext->dwUpper, phContext->dwLower ));
|
||
|
||
if ( pSession->SharedData->ContextHandlePackage->ValidateHandle(
|
||
pSession->SharedData->ContextTable,
|
||
phContext,
|
||
TRUE ) )
|
||
{
|
||
return SEC_E_OK ;
|
||
}
|
||
|
||
return SEC_E_INVALID_HANDLE ;
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: ValidateCredHandle
|
||
//
|
||
// Synopsis: Validate the context handle against the session list
|
||
//
|
||
// Arguments: [pSession] --
|
||
// [phCred] --
|
||
//
|
||
// History: 5-18-95 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
ValidateCredHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phCred,
|
||
PVOID * pKey
|
||
)
|
||
{
|
||
|
||
*pKey = pSession->SharedData->CredHandlePackage->RefHandle(
|
||
pSession->SharedData->CredTable,
|
||
phCred );
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Validate cred (%p : %p) for %p returned %p\n",
|
||
phCred->dwUpper, phCred->dwLower,
|
||
pSession, *pKey ));
|
||
|
||
if ( *pKey )
|
||
{
|
||
return SEC_E_OK ;
|
||
}
|
||
else
|
||
{
|
||
return SEC_E_INVALID_HANDLE ;
|
||
}
|
||
}
|
||
|
||
VOID
|
||
DerefCredHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phCred,
|
||
PVOID Key OPTIONAL
|
||
)
|
||
{
|
||
if ( Key )
|
||
{
|
||
#if DBG
|
||
PSEC_HANDLE_ENTRY Entry = (PSEC_HANDLE_ENTRY) Key ;
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Deref cred ( %p : %p ) for %p \n",
|
||
Entry->Handle.dwUpper, Entry->Handle.dwLower,
|
||
pSession ));
|
||
#endif
|
||
pSession->SharedData->CredHandlePackage->DerefHandleKey(
|
||
pSession->SharedData->CredTable,
|
||
Key );
|
||
}
|
||
else
|
||
{
|
||
pSession->SharedData->CredHandlePackage->DeleteHandle(
|
||
pSession->SharedData->CredTable,
|
||
phCred,
|
||
0 );
|
||
|
||
DebugLog(( DEB_TRACE_HANDLES, "Deref cred (%p : %p) for %p\n",
|
||
phCred->dwUpper, phCred->dwLower,
|
||
pSession ));
|
||
}
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
ValidateAndDerefCredHandle(
|
||
PSession pSession,
|
||
PCtxtHandle phCred
|
||
)
|
||
{
|
||
DebugLog(( DEB_TRACE_HANDLES, "ValidateAndDeref Cred (%p : %p)\n",
|
||
phCred->dwUpper, phCred->dwLower ));
|
||
|
||
if ( pSession->SharedData->CredHandlePackage->ValidateHandle(
|
||
pSession->SharedData->CredTable,
|
||
phCred,
|
||
TRUE ) )
|
||
{
|
||
return SEC_E_OK ;
|
||
}
|
||
|
||
return SEC_E_INVALID_HANDLE ;
|
||
}
|
||
|
||
BOOL
|
||
LsapMoveContextHandle(
|
||
PSecHandle Handle,
|
||
PSession OriginatingSession,
|
||
PSession DestinationSession
|
||
)
|
||
{
|
||
BOOL Ret ;
|
||
|
||
if ( OriginatingSession->SharedData->ContextHandlePackage->DeleteHandle(
|
||
OriginatingSession->SharedData->ContextTable,
|
||
Handle,
|
||
DELHANDLE_FORCE | DELHANDLE_NO_CALLBACK ) )
|
||
{
|
||
Ret = DestinationSession->SharedData->ContextHandlePackage->AddHandle(
|
||
DestinationSession->SharedData->ContextTable,
|
||
Handle,
|
||
DestinationSession,
|
||
0 );
|
||
|
||
|
||
} else {
|
||
Ret = FALSE ;
|
||
}
|
||
|
||
return Ret ;
|
||
}
|
||
|
||
BOOL
|
||
LsapMoveCredHandle(
|
||
PSecHandle Handle,
|
||
PSession OriginatingSession,
|
||
PSession DestinationSession
|
||
)
|
||
{
|
||
BOOL Ret ;
|
||
|
||
if ( OriginatingSession->SharedData->CredHandlePackage->DeleteHandle(
|
||
OriginatingSession->SharedData->CredTable,
|
||
Handle,
|
||
DELHANDLE_FORCE | DELHANDLE_NO_CALLBACK ) )
|
||
{
|
||
Ret = DestinationSession->SharedData->CredHandlePackage->AddHandle(
|
||
DestinationSession->SharedData->CredTable,
|
||
Handle,
|
||
DestinationSession,
|
||
0 );
|
||
|
||
|
||
} else {
|
||
Ret = FALSE ;
|
||
}
|
||
|
||
return Ret ;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
LsapValidLogonProcess(
|
||
IN PVOID Request,
|
||
IN ULONG RequestSize,
|
||
IN PCLIENT_ID ClientId,
|
||
OUT PLUID LogonId,
|
||
OUT PULONG Flags
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function checks to see if a calling process qualifies as a logon
|
||
process. If so, a logon process context is created for the caller and
|
||
returned.
|
||
|
||
A logon process must hold the SeTcbPrivilege privilege. Since there
|
||
is no way to impersonate a connection requestor (that would be way
|
||
too easy), we have to open the client thread and then open that thread's
|
||
token.
|
||
|
||
|
||
Arguments:
|
||
|
||
ClientId - Pointer to the client Id of the sender of the logon
|
||
message. This is used to locate and open the calling thread or
|
||
process.
|
||
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Indicates the caller is a legitimate logon process
|
||
and a logon process context block is being returned.
|
||
|
||
any other value - Indicates the caller is NOT a legitimate logon
|
||
process and a logon process context block is NOT being returned.
|
||
The value returned indicates the reason why the client is not
|
||
acceptable.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status, TempStatus;
|
||
BOOLEAN PrivilegeHeld;
|
||
HANDLE ClientThread, ClientProcess, ClientToken;
|
||
PRIVILEGE_SET Privilege;
|
||
OBJECT_ATTRIBUTES NullAttributes;
|
||
UNICODE_STRING Unicode;
|
||
STRING Ansi;
|
||
BOOLEAN Untrusted = FALSE;
|
||
TOKEN_STATISTICS TokenStats;
|
||
PLSAP_AU_REGISTER_CONNECT_INFO_EX ConnectionRequest = (PLSAP_AU_REGISTER_CONNECT_INFO_EX) Request;
|
||
ULONG TokenStatsSize = sizeof(TokenStats);
|
||
LSAP_AU_REGISTER_CONNECT_INFO NullConnectInfo;
|
||
|
||
*Flags = 0;
|
||
|
||
|
||
RtlZeroMemory(
|
||
&NullConnectInfo,
|
||
sizeof(NullConnectInfo)
|
||
);
|
||
|
||
|
||
|
||
|
||
//
|
||
// If the connect message is all zeros, setup an untrusted connection.
|
||
//
|
||
|
||
if (RtlEqualMemory(
|
||
&NullConnectInfo,
|
||
ConnectionRequest,
|
||
sizeof(NullConnectInfo))) {
|
||
|
||
Untrusted = TRUE;
|
||
*Flags |= SESFLAG_UNTRUSTED;
|
||
}
|
||
|
||
|
||
|
||
InitializeObjectAttributes( &NullAttributes, NULL, 0, NULL, NULL );
|
||
|
||
|
||
//
|
||
// Open the client thread and that thread's token
|
||
//
|
||
|
||
|
||
Status = NtOpenThread(
|
||
&ClientThread,
|
||
THREAD_QUERY_INFORMATION,
|
||
&NullAttributes,
|
||
ClientId
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
return Status;
|
||
}
|
||
|
||
Status = NtOpenThreadToken(
|
||
ClientThread,
|
||
TOKEN_QUERY,
|
||
TRUE,
|
||
&ClientToken
|
||
);
|
||
|
||
TempStatus = NtClose( ClientThread );
|
||
DsysAssert( NT_SUCCESS(TempStatus) );
|
||
|
||
//
|
||
// Make sure we succeeded in opening the token
|
||
//
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
if ( Status != STATUS_NO_TOKEN ) {
|
||
return Status;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Open the client process. This is needed to:
|
||
//
|
||
// 1) Access the client's virtual memory (to copy arguments),
|
||
// 2) Duplicate token handles into the process,
|
||
// 3) Open the process's token to see if it qualifies as
|
||
// a logon process.
|
||
//
|
||
|
||
Status = NtOpenProcess(
|
||
&ClientProcess,
|
||
PROCESS_QUERY_INFORMATION | // To open primary token
|
||
PROCESS_VM_OPERATION | // To allocate memory
|
||
PROCESS_VM_READ | // To read memory
|
||
PROCESS_VM_WRITE | // To write memory
|
||
PROCESS_DUP_HANDLE, // To duplicate a handle into
|
||
&NullAttributes,
|
||
ClientId
|
||
);
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// The thread isn't impersonating...open the process's token.
|
||
//
|
||
|
||
Status = NtOpenProcessToken(
|
||
ClientProcess,
|
||
TOKEN_QUERY,
|
||
&ClientToken
|
||
);
|
||
|
||
|
||
TempStatus = NtClose( ClientProcess );
|
||
DsysAssert( NT_SUCCESS(TempStatus) );
|
||
|
||
//
|
||
// Make sure we succeeded in opening the token
|
||
//
|
||
|
||
if ( !NT_SUCCESS(Status) ) {
|
||
return Status;
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
*Flags |= SESFLAG_IMPERSONATE;
|
||
}
|
||
|
||
//
|
||
// If the caller has the kernel flag set in the LPC message, this is
|
||
// probably a kernel session, but we can't be sure until the first
|
||
// request is made and the LPC_KERNELMODE_MESSAGE flag is set. The
|
||
// handlers will check that, but until then, set the maybe-flag.
|
||
//
|
||
|
||
if (!Untrusted &&
|
||
RequestSize == sizeof( LSAP_AU_REGISTER_CONNECT_INFO_EX) &&
|
||
((ConnectionRequest->ClientMode & LSAP_AU_KERNEL_CLIENT) != 0) )
|
||
{
|
||
*Flags |= SESFLAG_MAYBEKERNEL;
|
||
}
|
||
|
||
|
||
//
|
||
// OK, we have a token open
|
||
//
|
||
|
||
//
|
||
// Get the logon id.
|
||
//
|
||
|
||
Status = NtQueryInformationToken(
|
||
ClientToken,
|
||
TokenStatistics,
|
||
(PVOID) &TokenStats,
|
||
TokenStatsSize,
|
||
&TokenStatsSize
|
||
);
|
||
if (!NT_SUCCESS(Status)) {
|
||
TempStatus = NtClose( ClientToken );
|
||
DsysAssert(NT_SUCCESS(TempStatus));
|
||
return(Status);
|
||
}
|
||
|
||
*LogonId = TokenStats.AuthenticationId;
|
||
|
||
Status = STATUS_SUCCESS ;
|
||
|
||
if (((*Flags) & SESFLAG_MAYBEKERNEL) == 0) {
|
||
//
|
||
// Check for the privilege to execute this service.
|
||
//
|
||
|
||
Privilege.PrivilegeCount = 1;
|
||
Privilege.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||
Privilege.Privilege[0].Luid = LsapTcbPrivilege;
|
||
Privilege.Privilege[0].Attributes = 0;
|
||
|
||
Status = NtPrivilegeCheck(
|
||
ClientToken,
|
||
&Privilege,
|
||
&PrivilegeHeld
|
||
);
|
||
DsysAssert( NT_SUCCESS(Status) );
|
||
|
||
//
|
||
// For untrusted clients who didn't really need TCB anyway don't
|
||
// bother with an audit. If they do have the privilege, by all
|
||
// means audit it.
|
||
//
|
||
|
||
if (!Untrusted || PrivilegeHeld) {
|
||
|
||
//
|
||
// Generate any necessary audits
|
||
//
|
||
|
||
TempStatus = NtPrivilegedServiceAuditAlarm (
|
||
&LsapLsaAuName,
|
||
&LsapRegisterLogonServiceName,
|
||
ClientToken,
|
||
&Privilege,
|
||
PrivilegeHeld
|
||
);
|
||
// DsysAssert( NT_SUCCESS(TempStatus) );
|
||
|
||
|
||
if ( !PrivilegeHeld ) {
|
||
|
||
TempStatus = NtClose( ClientToken );
|
||
DsysAssert( NT_SUCCESS(TempStatus) );
|
||
|
||
return STATUS_PRIVILEGE_NOT_HELD;
|
||
|
||
}
|
||
}
|
||
if (PrivilegeHeld)
|
||
{
|
||
*Flags |= SESFLAG_TCB_PRIV;
|
||
}
|
||
}
|
||
|
||
TempStatus = NtClose( ClientToken );
|
||
DsysAssert( NT_SUCCESS(TempStatus) );
|
||
|
||
if (!Untrusted && ((*Flags & SESFLAG_KERNEL) == 0))
|
||
{
|
||
LsapAdtAuditLogonProcessRegistration( ConnectionRequest );
|
||
}
|
||
return(STATUS_SUCCESS);
|
||
}
|
||
|
||
//+---------------------------------------------------------------------------
|
||
//
|
||
// Function: LsapSetSessionOptions
|
||
//
|
||
// Synopsis: Allows clients to adjust session options
|
||
//
|
||
// Arguments: [Request] --
|
||
// [Response] --
|
||
//
|
||
// History: 8-05-96 RichardW Created
|
||
//
|
||
// Notes:
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
NTSTATUS
|
||
LsapSetSessionOptions(
|
||
ULONG Request,
|
||
ULONG_PTR Argument,
|
||
PULONG_PTR Response
|
||
)
|
||
{
|
||
PSession pSession;
|
||
PLSAP_TASK_QUEUE pQueue;
|
||
NTSTATUS Status ;
|
||
|
||
pSession = GetCurrentSession();
|
||
|
||
DebugLog(( DEB_TRACE, "[%d] SetSession( %d )\n",
|
||
pSession->dwProcessID, Request ));
|
||
|
||
Status = STATUS_SUCCESS ;
|
||
|
||
LockSession( pSession );
|
||
|
||
switch ( Request )
|
||
{
|
||
case SETSESSION_GET_STATUS:
|
||
*Response = 0;
|
||
break;
|
||
|
||
case SETSESSION_ADD_WORKQUEUE:
|
||
if ( pSession->SharedData->pQueue == NULL )
|
||
{
|
||
if ( CreateSubordinateQueue( pSession, &GlobalQueue ) )
|
||
{
|
||
//
|
||
// If they're going to be that busy, convert the cred list
|
||
// to be a large table
|
||
//
|
||
|
||
AddRundown( pSession, LsapDeleteWorkQueue, NULL );
|
||
|
||
pSession->SharedData->CredTable = LhtConvertSmallToLarge(
|
||
pSession->SharedData->CredTable );
|
||
|
||
pSession->SharedData->CredHandlePackage = &LargeHandlePackage ;
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_UNSUCCESSFUL ;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case SETSESSION_REMOVE_WORKQUEUE:
|
||
break;
|
||
|
||
case SETSESSION_GET_DISPATCH:
|
||
if ( pSession->dwProcessID == GetCurrentProcessId() )
|
||
{
|
||
Status = InitializeDirectDispatcher();
|
||
|
||
if ( NT_SUCCESS( Status ) )
|
||
{
|
||
DllCallbackHandler = (PLSA_DISPATCH_FN) Argument ;
|
||
*Response = (ULONG_PTR) DispatchAPIDirect;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = STATUS_ACCESS_DENIED ;
|
||
}
|
||
break;
|
||
}
|
||
|
||
UnlockSession( pSession );
|
||
|
||
return( Status );
|
||
|
||
}
|
||
|