⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 context.cxx

📁 安全支持提供器接口(SSPI)源码
💻 CXX
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) 1993  Microsoft Corporation

Module Name:

    context.cxx

Abstract:

    API and support routines for handling security contexts.

Author:

    Cliff Van Dyke (CliffV) 13-Jul-1993

Revision History:
    ChandanS 03-Aug-1996  Stolen from net\svcdlls\ntlmssp\common\context.c

--*/


//
// Common include files.
//

#include <global.h>
#include <align.h>      // ALIGN_WCHAR, etc
extern "C"
{
#include <crypt.h>      // Encryption constants and routine
#include <rc4.h>        // RC4 encryption types and functions
#include <md5.h>
}

// Globals for manipulating Context Lists while in Lsa Mode

CRITICAL_SECTION SspContextCritSect;
LIST_ENTRY       SspContextList;

//
// Performance counters
//

#define TRACK_REQUESTS
#ifdef TRACK_REQUESTS
LONG ServerAuthentications;
LONG ClientAuthentications;
#define INC_CLIENT_AUTH() (InterlockedIncrement(&ClientAuthentications))
#define INC_SERVER_AUTH() (InterlockedIncrement(&ServerAuthentications))
#else
#define INC_CLIENT_AUTH()
#define INC_SERVER_AUTH()
#endif


PSSP_CONTEXT
SspContextReferenceContext(
    IN ULONG_PTR ContextHandle,
    IN BOOLEAN RemoveContext
    )

/*++

Routine Description:

    This routine checks to see if the Context is for the specified
    Client Connection, and references the Context if it is valid.

    The caller may optionally request that the Context be
    removed from the list of valid Contexts - preventing future
    requests from finding this Context.

Arguments:

    ContextHandle - Points to the ContextHandle of the Context
        to be referenced.

    RemoveContext - This boolean value indicates whether the caller
        wants the Context to be removed from the list
        of Contexts.  TRUE indicates the Context is to be removed.
        FALSE indicates the Context is not to be removed.


Return Value:

    NULL - the Context was not found.

    Otherwise - returns a pointer to the referenced Context.

--*/

{
    PLIST_ENTRY ListEntry;
    PSSP_CONTEXT Context;

    SspPrint(( SSP_API_MORE, "Entering SspContextReferenceContext\n" ));


#if 0

    //
    // check that usermode/kernel mode caller matches.
    //

    SECPKG_CALL_INFO CallInfo;
    BOOLEAN KernelCaller;

    if( LsaFunctions->GetCallInfo(&CallInfo) ) {
        KernelCaller = ((CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE) != 0);
    }

#endif



    //
    // Acquire exclusive access to the Context list
    //

    EnterCriticalSection( &SspContextCritSect );

    //
    // Now walk the list of Contexts looking for a match.
    //

    for ( ListEntry = SspContextList.Flink;
          ListEntry != &SspContextList;
          ListEntry = ListEntry->Flink ) {

        Context = CONTAINING_RECORD( ListEntry, SSP_CONTEXT, Next );

        //
        // Found a match ... reference this Context
        // (if the Context is being removed, we would increment
        // and then decrement the reference, so don't bother doing
        // either - since they cancel each other out).
        //

        if ( Context == (PSSP_CONTEXT) ContextHandle)
        {

#if 0
            ASSERT( (KernelCaller == Context->KernelClient) );
#endif
            if (!RemoveContext)
            {
                //
                // Timeout this context if caller is not trying to remove it.
                // We only timeout contexts that are being setup, not
                // fully authenticated contexts.
                //

                if (SspTimeHasElapsed( Context->StartTime, Context->Interval))
                {
                    if ((Context->State != AuthenticatedState) &&
                        (Context->State != AuthenticateSentState) &&
                        (Context->State != PassedToServiceState))
                    {
                        SspPrint(( SSP_CRITICAL, "Context 0x%lx has timed out.\n",
                                    ContextHandle ));

                        LeaveCriticalSection( &SspContextCritSect );
                        return NULL;
                    }
                }

                Context->References += 1;
            }
            else
            {
                RemoveEntryList( &Context->Next );
                SspPrint(( SSP_API_MORE, "Delinked Context 0x%lx\n",
                           Context ));
            }

            SspPrint(( SSP_LEAK_TRACK, "SspContextReferenceContext for Context = 0x%x, RemoveContext = %d, ReferenceCount = %d\n", Context, RemoveContext, Context->References));
            LeaveCriticalSection( &SspContextCritSect );
            SspPrint(( SSP_API_MORE, "Leaving SspContextReferenceContext\n" ));
            return Context;
        }

    }

    //
    // No match found
    //

    SspPrint(( SSP_API_MORE, "Tried to reference unknown Context 0x%lx\n",
               ContextHandle ));

    LeaveCriticalSection( &SspContextCritSect );
    return NULL;

}

VOID
SspContextDereferenceContext(
    PSSP_CONTEXT Context
    )

/*++

Routine Description:

    This routine decrements the specified Context's reference count.
    If the reference count drops to zero, then the Context is deleted

Arguments:

    Context - Points to the Context to be dereferenced.


Return Value:

    None.

--*/

{

    ULONG References;

    SspPrint(( SSP_API_MORE, "Entering SspContextDereferenceContext\n" ));
    //
    // Decrement the reference count
    //

    EnterCriticalSection( &SspContextCritSect );
    ASSERT( Context->References >= 1 );
    References = -- Context->References;
    SspPrint(( SSP_LEAK_TRACK, "SspContextDereferenceContext for Context = 0x%x, ReferenceCount = %d\n", Context, Context->References));
    LeaveCriticalSection( &SspContextCritSect );

    //
    // If the count dropped to zero, then run-down the Context
    //

    if (References == 0) {

        SspPrint(( SSP_API_MORE, "Deleting Context 0x%lx\n",
                   Context ));

        if ( Context->DomainName.Buffer != NULL ) {
            (VOID) NtLmFree( Context->DomainName.Buffer );
        }
        if ( Context->UserName.Buffer != NULL ) {
            (VOID) NtLmFree( Context->UserName.Buffer );
        }
        if ( Context->Password.Buffer != NULL ) {
            // note: Password.Length may contain run-encoding hint, so size may be illegal.
            ZeroMemory( Context->Password.Buffer, Context->Password.MaximumLength );
            (VOID) NtLmFree( Context->Password.Buffer );
        }
        if ( Context->TokenHandle != NULL ) {
            NTSTATUS IgnoreStatus;
            IgnoreStatus = NtClose( Context->TokenHandle );
            ASSERT( NT_SUCCESS(IgnoreStatus) );
        }
        if (Context->Credential != NULL) {
            SspCredentialDereferenceCredential( Context->Credential );
        }

        ZeroMemory( Context, sizeof(SSP_CONTEXT) );
        (VOID) NtLmFree( Context );

    }

    return;

}

PSSP_CONTEXT
SspContextAllocateContext(
    )

/*++

Routine Description:

    This routine allocates the security context block, initializes it and
    links it onto the specified credential.

Arguments: None

Return Value:

    NULL -- Not enough memory to allocate context.

    otherwise -- pointer to allocated and referenced context.

--*/

{

    SspPrint(( SSP_API_MORE, "Entering SspContextAllocateContext\n" ));
    PSSP_CONTEXT Context;
    SECPKG_CALL_INFO CallInfo;


    //
    // Allocate a Context block and initialize it.
    //

    Context = (PSSP_CONTEXT)NtLmAllocate(sizeof(SSP_CONTEXT) );

    if ( Context == NULL ) {
        SspPrint(( SSP_CRITICAL, "SspContextAllocateContext: Error allocating Context.\n" ));
        return NULL;
    }

    ZeroMemory( Context, sizeof(SSP_CONTEXT) );


    if( LsaFunctions->GetCallInfo(&CallInfo) ) {
        Context->ClientProcessID = CallInfo.ProcessId;
        Context->KernelClient = ((CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE) != 0);
    }

    //
    // The reference count is set to 2.  1 to indicate it is on the
    // valid Context list, and one for the our own reference.
    //

    Context->References = 2;
    Context->State = IdleState;

    //
    // Timeout this context.
    //

    (VOID) NtQuerySystemTime( &Context->StartTime );
    Context->Interval = NTLMSSP_MAX_LIFETIME;

    //
    // Add it to the list of valid Context handles.
    //

    EnterCriticalSection( &SspContextCritSect );
    InsertHeadList( &SspContextList, &Context->Next );
    SspPrint(( SSP_LEAK_TRACK, "SspContextAllocateContext for Context = 0x%x, ReferenceCount = %d\n", Context, Context->References));
    LeaveCriticalSection( &SspContextCritSect );

    SspPrint(( SSP_API_MORE, "Added Context 0x%lx\n", Context ));

    SspPrint(( SSP_API_MORE, "Leaving SspContextAllocateContext\n" ));
    return Context;

}

NTSTATUS
SspContextGetMessage(
    IN PVOID InputMessage,
    IN ULONG InputMessageSize,
    IN NTLM_MESSAGE_TYPE ExpectedMessageType,
    OUT PVOID* OutputMessage
    )

/*++

Routine Description:

    This routine copies the InputMessage into the local address space.
    This routine then validates the message header.

Arguments:

    InputMessage - Address of the message in the client process.

    InputMessageSize - Size of the message (in bytes).

    ExpectedMessageType - The type of message the should be in the message
        header.

    OutputMessage - Returns a pointer to an allocated buffer that contains
        the message.  The buffer should be freed using NtLmFree.


Return Value:

    STATUS_SUCCESS - Call completed successfully

    SEC_E_INVALID_TOKEN -- Message improperly formatted
    SEC_E_INSUFFICIENT_MEMORY -- Not enough memory to allocate message

--*/

{

    NTSTATUS Status = STATUS_SUCCESS;
    PNEGOTIATE_MESSAGE TypicalMessage = NULL;

    //
    // Allocate a local buffer for the message.
    //

    ASSERT( NTLMSP_MAX_TOKEN_SIZE >= NTLMSSP_MAX_MESSAGE_SIZE );
    if ( InputMessageSize > NTLMSSP_MAX_MESSAGE_SIZE ) {
        Status = SEC_E_INVALID_TOKEN;
        SspPrint(( SSP_CRITICAL, "SspContextGetMessage, invalid input message size.\n" ));
        goto Cleanup;
    }

    TypicalMessage = (PNEGOTIATE_MESSAGE)NtLmAllocate(InputMessageSize );

    if ( TypicalMessage == NULL ) {
        Status = STATUS_NO_MEMORY;
        SspPrint(( SSP_CRITICAL, "SspContextGetMessage: Error allocating TypicalMessage.\n" ));
        goto Cleanup;
    }

    //
    // Copy the message into the buffer
    //

    RtlCopyMemory( TypicalMessage,
                   InputMessage,
                   InputMessageSize );

    //
    // Validate the message header.
    //

    if ( strncmp( (const char *)TypicalMessage->Signature,
                  NTLMSSP_SIGNATURE,
                  sizeof(NTLMSSP_SIGNATURE)) != 0 ||
         TypicalMessage->MessageType != ExpectedMessageType ) {

        (VOID) NtLmFree( TypicalMessage );
        TypicalMessage = NULL;
        Status = SEC_E_INVALID_TOKEN;
        SspPrint(( SSP_CRITICAL, "SspContextGetMessage, Bogus Message.\n" ));
        goto Cleanup;

    }

Cleanup:

    *OutputMessage = TypicalMessage;

    return Status;

}

VOID
SspContextCopyString(
    IN PVOID MessageBuffer,
    OUT PSTRING32 OutString,
    IN PSTRING InString,
    IN OUT PCHAR *Where
    )

/*++

Routine Description:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -