Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

503 lines
14 KiB

//+-----------------------------------------------------------------------
//
// 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);
}