504 lines
14 KiB
C++
504 lines
14 KiB
C++
//+-----------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (c) Microsoft Corporation 2000
|
||
//
|
||
// File: logsess.cxx
|
||
//
|
||
// Contents: LogonSession functions:
|
||
//
|
||
//
|
||
// History: KDamour 15Mar00 Stolen from NTLM
|
||
//
|
||
//------------------------------------------------------------------------
|
||
#include "global.h"
|
||
|
||
//
|
||
// Crit Sect to protect various globals in this module.
|
||
//
|
||
|
||
RTL_CRITICAL_SECTION l_LogSessCritSect;
|
||
|
||
LIST_ENTRY l_LogSessList;
|
||
|
||
// Simple variable to make sure that the package was initialize
|
||
BOOL g_bLogSessInitialized = FALSE;
|
||
|
||
|
||
|
||
//+--------------------------------------------------------------------
|
||
//
|
||
// Function: LogSessHandlerInit
|
||
//
|
||
// Synopsis: Initializes the LogonSession manager package
|
||
//
|
||
// Arguments: none
|
||
//
|
||
// Returns: NTSTATUS
|
||
//
|
||
// Notes: Called by SpInitialize
|
||
//
|
||
//---------------------------------------------------------------------
|
||
NTSTATUS
|
||
LogSessHandlerInit(VOID)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// Initialize the LogonSession list to be empty.
|
||
//
|
||
|
||
Status = RtlInitializeCriticalSection(&l_LogSessCritSect);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
DebugLog((DEB_ERROR, "LogSessHandlerInit: Failed to initialize critsec 0x%x\n", Status));
|
||
goto CleanUp;
|
||
}
|
||
|
||
InitializeListHead( &l_LogSessList );
|
||
|
||
// Simple variable test to make sure all initialized;
|
||
g_bLogSessInitialized = TRUE;
|
||
|
||
CleanUp:
|
||
|
||
return Status;
|
||
}
|
||
|
||
NTSTATUS
|
||
LogSessHandlerInsert(
|
||
IN PDIGEST_LOGONSESSION pDigestLogSess
|
||
)
|
||
{
|
||
RtlEnterCriticalSection( &l_LogSessCritSect );
|
||
InsertHeadList( &l_LogSessList, &pDigestLogSess->Next );
|
||
RtlLeaveCriticalSection( &l_LogSessCritSect );
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
// Initialize the LogSess Structure
|
||
NTSTATUS
|
||
LogonSessionInit(
|
||
IN PDIGEST_LOGONSESSION pLogonSession)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
if (!pLogonSession)
|
||
{
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
ZeroMemory(pLogonSession, sizeof(DIGEST_LOGONSESSION));
|
||
pLogonSession->LogonSessionHandle = (ULONG_PTR)pLogonSession;
|
||
pLogonSession->lReferences = 1;
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
// Free up memory utilized by LogonSession Structure
|
||
NTSTATUS
|
||
LogonSessionFree(
|
||
IN PDIGEST_LOGONSESSION pDigestLogSess)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
// Free up all Unicode & String structures
|
||
UnicodeStringFree(&(pDigestLogSess->ustrAccountName));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrDownlevelName));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrDomainName));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrPassword));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrDnsDomainName));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrUpn));
|
||
UnicodeStringFree(&(pDigestLogSess->ustrLogonServer));
|
||
|
||
DigestFreeMemory(pDigestLogSess);
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine checks to see if the LogonID is from a currently
|
||
active client, and references the LogSess if it is valid.
|
||
|
||
The caller may optionally request that the client's LogSess be
|
||
removed from the list of valid LogonSession - preventing future
|
||
requests from finding this LogSess.
|
||
|
||
For a client's LogSess to be valid, the LogSess value
|
||
must be on our list of active LogonSession.
|
||
|
||
|
||
Arguments:
|
||
|
||
LogonSessionHandle - Points to the LogonSession Handle of the LogSess
|
||
to be referenced.
|
||
|
||
ForceRemove - This boolean value indicates whether the caller
|
||
wants the logon process's LogSess to be removed from the list
|
||
of LogonSession. TRUE indicates the LogSess is to be removed.
|
||
FALSE indicates the LogSess is not to be removed.
|
||
|
||
|
||
Return Value:
|
||
|
||
STATUS_INVALID_HANDLE - the LogSess was not found.
|
||
|
||
STATUS_SUCCESS - returns a pointer to the referenced LogonSession.
|
||
|
||
|
||
--*/
|
||
NTSTATUS
|
||
LogSessHandlerLogonIdToPtr(
|
||
IN PLUID pLogonId,
|
||
IN BOOLEAN ForceRemove,
|
||
OUT PDIGEST_LOGONSESSION * ppUserLogonSession
|
||
)
|
||
{
|
||
PLIST_ENTRY ListEntry = NULL;
|
||
PDIGEST_LOGONSESSION pLogonSession = NULL;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
LONG lReferences = 0;
|
||
|
||
*ppUserLogonSession = NULL ;
|
||
|
||
//
|
||
// Acquire exclusive access to the LogonSession list
|
||
//
|
||
|
||
RtlEnterCriticalSection( &l_LogSessCritSect );
|
||
|
||
|
||
//
|
||
// Now walk the list of LogonSession looking for a match.
|
||
//
|
||
|
||
for ( ListEntry = l_LogSessList.Flink;
|
||
ListEntry != &l_LogSessList;
|
||
ListEntry = ListEntry->Flink )
|
||
{
|
||
|
||
pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
|
||
|
||
if (RtlEqualLuid(&(pLogonSession->LogonId), pLogonId))
|
||
{
|
||
// Found the LogonSession
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Found LogSess for LogonID (%x:%lx)\n",
|
||
pLogonId->HighPart, pLogonId->LowPart ));
|
||
|
||
if (!ForceRemove)
|
||
{
|
||
lReferences = InterlockedIncrement(&pLogonSession->lReferences);
|
||
|
||
DebugLog((DEB_TRACE, "CredHandlerHandleToPtr: Incremented ReferenceCount %ld\n", lReferences));
|
||
}
|
||
else
|
||
{
|
||
// ForceRemove of True will unlink this LogonSession from the list of active LogonSessions
|
||
// The structure pointet will be returned for the calling function to free up if required
|
||
// Would call LogSessHandlerRelease to dereference the counter (and maybe free up)
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Unlinking 0x%lx Refcount = %d\n",
|
||
pLogonSession, pLogonSession->lReferences));
|
||
|
||
RemoveEntryList( &pLogonSession->Next );
|
||
}
|
||
|
||
// Return a pointer to the LogSess found
|
||
*ppUserLogonSession = pLogonSession ;
|
||
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
|
||
//
|
||
// No match found
|
||
//
|
||
DebugLog((DEB_WARN, "LogSessHandlerLogonIdToPtr: Tried to reference unknown LogonID (%x:%lx)\n",
|
||
pLogonId->HighPart, pLogonId->LowPart ));
|
||
Status = STATUS_INVALID_HANDLE;
|
||
|
||
CleanUp:
|
||
|
||
RtlLeaveCriticalSection( &l_LogSessCritSect );
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
// Locate a LogonSession based on a Principal Name (UserName) ok
|
||
NTSTATUS
|
||
LogSessHandlerAccNameToPtr(
|
||
IN PUNICODE_STRING pustrAccountName,
|
||
OUT PDIGEST_LOGONSESSION *ppUserLogonSession
|
||
)
|
||
{
|
||
PLIST_ENTRY ListEntry = NULL;
|
||
PDIGEST_LOGONSESSION pLogonSession = NULL;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
LONG lReferences = 0;
|
||
|
||
|
||
*ppUserLogonSession = NULL ;
|
||
|
||
if ((!pustrAccountName) || (!pustrAccountName->Length))
|
||
{
|
||
DebugLog((DEB_ERROR, "LogSessHandlerAccNameToPtr: No AccountName provided\n"));
|
||
Status = STATUS_INVALID_PARAMETER_1;
|
||
return(Status);
|
||
}
|
||
|
||
//
|
||
// Acquire exclusive access to the LogonSession list
|
||
//
|
||
|
||
RtlEnterCriticalSection( &l_LogSessCritSect );
|
||
|
||
|
||
//
|
||
// Now walk the list of LogonSession looking for a match.
|
||
//
|
||
|
||
for ( ListEntry = l_LogSessList.Flink;
|
||
ListEntry != &l_LogSessList;
|
||
ListEntry = ListEntry->Flink )
|
||
{
|
||
|
||
pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
|
||
|
||
|
||
if ((pLogonSession->ustrAccountName).Length)
|
||
{
|
||
DebugLog((DEB_TRACE, "LogSessHandlerAccNameToPtr: Checking %wZ against AccountName %wZ\n",
|
||
&(pLogonSession->ustrAccountName), pustrAccountName ));
|
||
|
||
if (RtlEqualUnicodeString(&(pLogonSession->ustrAccountName), pustrAccountName, TRUE))
|
||
{
|
||
lReferences = InterlockedIncrement(&pLogonSession->lReferences);
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerAccNameToPtr: Incremented ReferenceCount %ld\n", lReferences));
|
||
|
||
// Found the LogonSession
|
||
*ppUserLogonSession = pLogonSession ;
|
||
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// No match found
|
||
//
|
||
DebugLog((DEB_WARN, "LogSessHandlerAccNameToPtr: Tried to reference unknown AccountName %wZ\n",
|
||
pustrAccountName ));
|
||
|
||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||
|
||
CleanUp:
|
||
|
||
RtlLeaveCriticalSection( &l_LogSessCritSect );
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
//+--------------------------------------------------------------------
|
||
//
|
||
// Function: LogSessHandlerRelease
|
||
//
|
||
// Synopsis: Releases the LogonSession by decrementing reference counter
|
||
//
|
||
// Arguments: pLogonSession - pointer to logonsession to de-reference
|
||
//
|
||
// Returns: NTSTATUS
|
||
//
|
||
// Notes: Called by ACH & AcceptCredentials. Since multiple threads can have a context
|
||
// checked out, simply decrease the reference counter on release. LsaApLogonTerminated
|
||
// is called by LSA to remove the LogonSession from the Active LIst.
|
||
// There can be atmost only 1 reference for a handle (owned by LSA and release by call
|
||
// to this function). The other references will be pointer references so these can
|
||
// be decremented without it being attached to active logonsession list.
|
||
//
|
||
//---------------------------------------------------------------------
|
||
NTSTATUS
|
||
LogSessHandlerRelease(
|
||
PDIGEST_LOGONSESSION pLogonSession)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
LONG lReferences = 0;
|
||
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerRelease: Entering for LogonSession 0x%0x LogonID (%x:%lx) \n",
|
||
pLogonSession, pLogonSession->LogonId.HighPart, pLogonSession->LogonId.LowPart));
|
||
|
||
lReferences = InterlockedDecrement(&pLogonSession->lReferences);
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerRelease: Decremented to ReferenceCount %ld\n", lReferences));
|
||
|
||
ASSERT( lReferences >= 0 );
|
||
//
|
||
// If the count has dropped to zero, then free all alloced stuff
|
||
//
|
||
|
||
if (lReferences == 0)
|
||
{
|
||
DebugLog((DEB_TRACE, "LogSessHandlerRelease: Deleting LogonSession\n"));
|
||
Status = LogonSessionFree(pLogonSession);
|
||
}
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerRelease: Leaving Status 0x%x\n", Status));
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
// Helper functions for processing fields within the logonsessions
|
||
|
||
|
||
|
||
//+--------------------------------------------------------------------
|
||
//
|
||
// Function: LogSessHandlerPasswdSet
|
||
//
|
||
// Synopsis: Set the unicode string password in the LogonSession
|
||
//
|
||
// Arguments: pLogonID - pointer to LogonSession LogonID to use
|
||
// pustrPasswd - pointer to new password
|
||
//
|
||
// Returns: NTSTATUS
|
||
//
|
||
// Notes:
|
||
//
|
||
//---------------------------------------------------------------------
|
||
NTSTATUS
|
||
LogSessHandlerPasswdSet(
|
||
IN PLUID pLogonId,
|
||
IN PUNICODE_STRING pustrPasswd)
|
||
{
|
||
|
||
PLIST_ENTRY ListEntry = NULL;
|
||
PDIGEST_LOGONSESSION pLogonSession = NULL;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdSet: Entering LogonID (%x:%lx)\n",
|
||
pLogonId->HighPart, pLogonId->LowPart));
|
||
|
||
//
|
||
// Acquire exclusive access to the LogonSession list
|
||
//
|
||
|
||
RtlEnterCriticalSection( &l_LogSessCritSect );
|
||
|
||
//
|
||
// Now walk the list of LogonSession looking for a match.
|
||
//
|
||
|
||
for ( ListEntry = l_LogSessList.Flink;
|
||
ListEntry != &l_LogSessList;
|
||
ListEntry = ListEntry->Flink )
|
||
{
|
||
|
||
pLogonSession = CONTAINING_RECORD( ListEntry, DIGEST_LOGONSESSION, Next );
|
||
|
||
if (RtlEqualLuid(&(pLogonSession->LogonId), pLogonId))
|
||
{
|
||
// Found the LogonSession
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerLogonIdToPtr: Found LogSess with LogonID (%x:%lx)\n",
|
||
pLogonId->HighPart, pLogonId->LowPart ));
|
||
|
||
if (pLogonSession->ustrPassword.Buffer)
|
||
{
|
||
UnicodeStringFree(&(pLogonSession->ustrPassword));
|
||
}
|
||
Status = UnicodeStringDuplicatePassword(&(pLogonSession->ustrPassword), pustrPasswd);
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
DebugLog((DEB_ERROR, "LogSessHandlerPasswdGet: Error in setting LogonSession password, status 0x%0x\n", Status ));
|
||
goto CleanUp;
|
||
}
|
||
|
||
DebugLog((DEB_TRACE, "LogSessHandlerPasswdSet: updated password\n"));
|
||
|
||
goto CleanUp;
|
||
}
|
||
}
|
||
|
||
//
|
||
// No match found
|
||
//
|
||
DebugLog((DEB_WARN, "LogSessHandlerPasswdSet: Unable to locate LogonID (%x:%lx) \n",
|
||
pLogonId->HighPart, pLogonId->LowPart ));
|
||
|
||
Status = STATUS_INVALID_HANDLE;
|
||
|
||
CleanUp:
|
||
|
||
RtlLeaveCriticalSection( &l_LogSessCritSect );
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdSet: Exiting LogonID (%x:%lx)\n",
|
||
pLogonId->HighPart, pLogonId->LowPart));
|
||
|
||
return(Status);
|
||
}
|
||
|
||
|
||
|
||
//+--------------------------------------------------------------------
|
||
//
|
||
// Function: LogSessHandlerPasswdGet
|
||
//
|
||
// Synopsis: Get the unicode string password in the logonsession
|
||
//
|
||
// Arguments: pLogonSession - pointer to LogonSession to use
|
||
// pustrPasswd - pointer to destination copy of password
|
||
//
|
||
// Returns: NTSTATUS
|
||
//
|
||
// Notes:
|
||
//
|
||
//---------------------------------------------------------------------
|
||
NTSTATUS
|
||
LogSessHandlerPasswdGet(
|
||
IN PDIGEST_LOGONSESSION pLogonSession,
|
||
OUT PUNICODE_STRING pustrPasswd)
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdGet: Entering\n" ));
|
||
|
||
if (pustrPasswd->Buffer)
|
||
{
|
||
UnicodeStringFree(pustrPasswd);
|
||
}
|
||
// Protect reading from the LogonSession
|
||
RtlEnterCriticalSection( &l_LogSessCritSect );
|
||
Status = UnicodeStringDuplicatePassword(pustrPasswd, &(pLogonSession->ustrPassword));
|
||
RtlLeaveCriticalSection( &l_LogSessCritSect );
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
DebugLog((DEB_ERROR, "LogSessHandlerPasswdGet: Error in getting LogonSession password, status 0x%0x\n", Status ));
|
||
}
|
||
|
||
DebugLog((DEB_TRACE_FUNC, "LogSessHandlerPasswdGet: Exiting, status 0x%0x\n", Status ));
|
||
|
||
return(Status);
|
||
}
|
||
|