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

📄 credhand.cxx

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

Copyright (c) 1993  Microsoft Corporation

Module Name:

    credhand.cxx

Abstract:

    API and support routines for handling credential handles.

Author:


    Cliff Van Dyke (CliffV) 26-Jun-1993
Revision History:
    ChandanS 03-Aug-1996  Stolen from net\svcdlls\ntlmssp\common\credhand.c

--*/


//
// Common include files.
//

#include <global.h>
#include <align.h>      // ALIGN_WCHAR

extern "C"
{

#include <nlp.h>

}

//
// Crit Sect to protect various globals in this module.
//

CRITICAL_SECTION SspCredentialCritSect;

LIST_ENTRY SspCredentialList;

// This is the definition of a null session string.
// Change this if the definition changes

#define IsNullSessionString(x) (((x)->Length == 0) &&    \
                          ((x)->Buffer != NULL))

BOOLEAN
AlterRtlEqualUnicodeString(
    IN PUNICODE_STRING String1,
    IN PUNICODE_STRING String2,
    IN BOOLEAN CaseInSensitive
    )
/*++
    This is here to catch cases that RtlEqualUnicodeString does not.
    For e.g, if String1 is (NULL,0,0) and String2 is ("",0,2),
    RtlEqualUnicodeString returned TRUE but we really want it to return FALSE
--*/
{
    BOOL fRet = RtlEqualUnicodeString(String1, String2, CaseInSensitive);

    if (fRet && (IsNullSessionString(String1) != IsNullSessionString(String2)))
    {
        fRet = FALSE;
    }
    return (fRet != 0);
}

BOOL
EnableAllPrivileges(
    IN  HANDLE ClientTokenHandle
    );


NTSTATUS
SspCredentialReferenceCredential(
    IN ULONG_PTR CredentialHandle,
    IN BOOLEAN DereferenceCredential,
    IN BOOLEAN ForceRemoveCredential,
    OUT PSSP_CREDENTIAL * UserCredential
    )

/*++

Routine Description:

    This routine checks to see if the Credential is from a currently
    active client, and references the Credential if it is valid.

    The caller may optionally request that the client's Credential be
    removed from the list of valid Credentials - preventing future
    requests from finding this Credential.

    For a client's Credential to be valid, the Credential value
    must be on our list of active Credentials.


Arguments:

    CredentialHandle - Points to the CredentialHandle of the Credential
        to be referenced.

    DereferenceCredential - This boolean value indicates that that a call
        a single instance of this credential handle should be freed. If there
        are multiple instances, they should still continue to work.

    ForceRemoveCredential - This boolean value indicates whether the caller
        wants the logon process's Credential to be removed from the list
        of Credentials.  TRUE indicates the Credential is to be removed.
        FALSE indicates the Credential is not to be removed.


Return Value:

    NULL - the Credential was not found.

    Otherwise - returns a pointer to the referenced credential.

--*/

{
    PLIST_ENTRY ListEntry;
    PSSP_CREDENTIAL Credential = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    SECPKG_CLIENT_INFO ClientInfo;

    ULONG DereferenceCount = 1;


    //
    // Make sure that nobody tries to force removal without also
    // trying to dereference the credential.
    //

    ASSERT(!(ForceRemoveCredential && !DereferenceCredential));

    *UserCredential = NULL ;

    Status = LsaFunctions->GetClientInfo(&ClientInfo);

    if(!NT_SUCCESS(Status))
    {
        SECPKG_CALL_INFO CallInfo;

        //
        // this call can fail during a cleanup call.  so ignore that for now,
        // and check for cleanup disposition.
        //

        if(LsaFunctions->GetCallInfo(&CallInfo)) {

            if ((CallInfo.Attributes & SECPKG_CALL_CLEANUP) != 0)
            {
                Status = STATUS_SUCCESS;
                RtlZeroMemory(
                    &ClientInfo,
                    sizeof(SECPKG_CLIENT_INFO)
                    );
                ClientInfo.HasTcbPrivilege = TRUE;
                ClientInfo.ProcessID = CallInfo.ProcessId;

                DereferenceCount = CallInfo.CallCount;
            }
        }

        if( !NT_SUCCESS( Status ) )
        {
            SspPrint(( SSP_CRITICAL, "SspCredentialReferenceCredential: GetClientInfo returned 0x%lx\n", Status));
            return( Status );
        }

    }


    //
    // Acquire exclusive access to the Credential list
    //

    EnterCriticalSection( &SspCredentialCritSect );


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

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

        Credential = CONTAINING_RECORD( ListEntry, SSP_CREDENTIAL, Next );


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

        if ( Credential == (PSSP_CREDENTIAL) CredentialHandle
            ) {

            // Make sure we have the privilege of accessing
            // this handle

            if (!ClientInfo.HasTcbPrivilege &&
               (Credential->ClientProcessID != ClientInfo.ProcessID)
               )
            {
                break;
            }

            if (!DereferenceCredential) {
                Credential->References += 1;
            } else {

                ASSERT( DereferenceCount > 0 );

                //
                // we've eliminated the two separate ref counters.
                // therefore, we let SspCredentialDereferenceCredential
                // take care of reducing the refcount.
                //

                DereferenceCount--;

                //
                // Decremenent the credential references, indicating
                // that a call to free

                ASSERT( DereferenceCount <= Credential->References );
                Credential->References -= DereferenceCount;

                ASSERT( Credential->References > 0 );

            }

            LeaveCriticalSection( &SspCredentialCritSect );

            *UserCredential = Credential ;

            return STATUS_SUCCESS ;

        }

    }


    //
    // No match found
    //
    SspPrint(( SSP_API_MORE, "Tried to reference unknown Credential 0x%lx\n",
               CredentialHandle ));

    LeaveCriticalSection( &SspCredentialCritSect );

    return STATUS_INVALID_HANDLE ;

}

NTSTATUS
SspGetToken (
    OUT PHANDLE ReturnedTokenHandle)
{
    HANDLE TokenHandle = NULL;
    NTSTATUS Status = STATUS_SUCCESS;
    HANDLE TmpHandle = NULL;
    SECURITY_IMPERSONATION_LEVEL SecImpLevel = SecurityImpersonation;

    Status = LsaFunctions->ImpersonateClient();

    if (!NT_SUCCESS (Status))
    {
            goto Cleanup;
    }

    // get the token
    // note: there MUST be an impersonation token.
    // LsaFunctions->ImpersonateClient will call ImpersonateSelf() when necessary

    Status = NtOpenThreadToken(NtCurrentThread(),
                               TOKEN_DUPLICATE |
                               TOKEN_QUERY |
                               WRITE_DAC,
                               TRUE,
                               &TokenHandle);

    if (!NT_SUCCESS (Status))
    {
            goto Cleanup;
    }

    Status = SspDuplicateToken(TokenHandle,
                               SecImpLevel,
                               &TmpHandle);

    if (!NT_SUCCESS (Status))
    {
            goto Cleanup;
    }

Cleanup:

    if (ReturnedTokenHandle != NULL)
    {
        if (!NT_SUCCESS (Status))
        {
            *ReturnedTokenHandle = NULL;
        }
        else
        {
            *ReturnedTokenHandle = TmpHandle;
            TmpHandle = NULL;
        }
    }

    if (TokenHandle != NULL)
    {
        NtClose(TokenHandle);
    }

    if (TmpHandle != NULL)
    {
        NtClose(TmpHandle);
    }

    // ignore return value, we may not have impersonated successfully..
    RevertToSelf();

    return Status;
}


NTSTATUS
SspCredentialGetPassword(
    IN PSSP_CREDENTIAL Credential,
    OUT PUNICODE_STRING Password
    )
/*++

Routine Description:

    This routine copies the password out of credential. It requires locking
    the credential list because other threads may be hiding/revealing the
    password and we need exclusive access to do that.

    NOTE: Locking is no longer required, because the caller is expected
    to NtLmDuplicateUnicodeString() the cipher text Password prior to
    passing it to this routine.  This change allows the following advantages:

    1. Avoid taking Credential list lock.
    2. Avoid having to avoid having to Re-hide the password after reveal.
    3. Avoid having to take locks elsewhere associated with hiding/revealing.


Arguments:

    Credential - Credential record to retrieve the password from.

    Password - UNICODE_STRING to store the password in.


Return Value:

    STATUS_NO_MEMORY - there was not enough memory to copy
        the password.

--*/

{
    NTSTATUS Status = STATUS_SUCCESS;

    if ( Credential->Password.Buffer != NULL ) {
        Status = NtLmDuplicateUnicodeString(
                        Password,
                        &Credential->Password
                        );
    } else {
        RtlInitUnicodeString(
            Password,
            NULL
            );
    }

    return(Status);
}


PSSP_CREDENTIAL
SspCredentialLookupSupplementalCredential(
    IN PLUID LogonId,
    IN ULONG CredentialUseFlags,
    IN PUNICODE_STRING UserName,
    IN PUNICODE_STRING DomainName,
    IN PUNICODE_STRING Password
    )

/*++

Routine Description:

    This routine walks the list of credentials for this client looking
    for one that has the same supplemental credentials as those passed
    in.  If it is found, its reference count is increased and a pointer
    to it is returned.


Arguments:

    UserName - User name to match.

    DomainName - Domain name to match.

    Password - Password to match.


Return Value:

    NULL - the Credential was not found.

    Otherwise - returns a pointer to the referenced credential.

--*/

{
    SspPrint((SSP_API_MORE, "Entering SspCredentialLookupSupplementalCredential\n"));
    NTSTATUS Status;
    PLIST_ENTRY ListEntry;
    PSSP_CREDENTIAL Credential = NULL;
    PLIST_ENTRY ListHead;
    SECPKG_CLIENT_INFO ClientInfo;
    SECPKG_CALL_INFO CallInfo ;


    Status = LsaFunctions->GetClientInfo(&ClientInfo);

    if (!NT_SUCCESS(Status)) {

⌨️ 快捷键说明

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