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

📄 credhand.cxx

📁 安全支持提供器接口(SSPI)源码
💻 CXX
📖 第 1 页 / 共 3 页
字号:
        SspPrint(( SSP_CRITICAL, "SspCredentialLookupSupplementalCredential: GetClientInfo returned 0x%lx\n", Status));
        return(NULL);
    }

    if ( !LsaFunctions->GetCallInfo( &CallInfo ) )
    {
        SspPrint(( SSP_CRITICAL, "SspCredentialLookupSupplementalCredential: GetCallInfo returned FALSE\n" ));
        return NULL ;
    }


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

    EnterCriticalSection( &SspCredentialCritSect );

    ListHead = &SspCredentialList;

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

    for ( ListEntry = ListHead->Flink;
          ListEntry != ListHead;
          ListEntry = ListEntry->Flink ) {

        Credential = CONTAINING_RECORD( ListEntry, SSP_CREDENTIAL, Next );

        //
        // We are only looking for outbound credentials.
        //

        if ((Credential->CredentialUseFlags & SECPKG_CRED_OUTBOUND) == 0) {
            continue;
        }

        //
        // We only want credentials from the same caller
        //
        if (Credential->ClientProcessID != ClientInfo.ProcessID) {
            continue;
        }

        //
        // if the caller is from kernel mode, only return creds
        // granted to kernel mode
        //

        if ( ( CallInfo.Attributes & SECPKG_CALL_KERNEL_MODE ) != 0 )
        {
            if ( !Credential->KernelClient )
            {
                continue;
            }
        }

        //
        // Check for a match
        //

        // The credential use check was added because null session
        // credentials were being returned when default credentials
        // were being asked. This happened becuase RtlEqualUnicodeString
        // for NULL,0,0 and "",0,2 is TRUE

        if ( (CredentialUseFlags == Credential->CredentialUseFlags) &&
            AlterRtlEqualUnicodeString(
                UserName,
                &Credential->UserName,
                FALSE
                ) &&
            AlterRtlEqualUnicodeString(
                DomainName,
                &Credential->DomainName,
                FALSE
                ) &&
            RtlEqualLuid(
                LogonId,
                &Credential->LogonId
                )) {

            UNICODE_STRING RevealedPassword;
            BOOLEAN fMatch;

            Status = NtLmDuplicateUnicodeString( &RevealedPassword, &Credential->Password );
            if(!NT_SUCCESS( Status ) ) {
                SspPrint(( SSP_CRITICAL,
                "SspCredentialLookupSupplementalCredential: NtLmDuplicateUnicodeString returned %d\n",Status));
                // an allocation failure is catastrophic, bail out now.
                break;
            }

            SspRevealPassword(&RevealedPassword);

            fMatch = AlterRtlEqualUnicodeString(
                    Password,
                    &RevealedPassword,
                    FALSE
                    );

            if( RevealedPassword.Buffer != NULL ) {
                ZeroMemory( RevealedPassword.Buffer, RevealedPassword.Length );
                NtLmFree( RevealedPassword.Buffer );
            }

            if( fMatch ) {

                //
                // Found a match - reference the credential
                //


                //
                // Reference the credential and indicate that
                // it is in use as two different handles to the caller
                // (who may call FreeCredentialsHandle twice)
                //

                Credential->References++;

                LeaveCriticalSection( &SspCredentialCritSect );
                SspPrint((SSP_API_MORE, "Leaving SspCredentialLookupSupplementalCredential\n"));
                return Credential;

            }

        }

    }


    //
    // No match found
    //
    SspPrint(( SSP_API_MORE, "Tried to reference unknown Credential\n" ));

    LeaveCriticalSection( &SspCredentialCritSect );
    SspPrint((SSP_API_MORE, "Leaving SspCredentialLookupSupplementalCredential\n"));
    return NULL;

}


VOID
SspCredentialDereferenceCredential(
    IN PSSP_CREDENTIAL Credential
    )

/*++

Routine Description:

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

Arguments:

    Credential - Points to the Credential to be dereferenced.


Return Value:

    None.

--*/

{
    ULONG References;

    //
    // Decrement the reference count
    //

    EnterCriticalSection( &SspCredentialCritSect );
    ASSERT( Credential->References >= 1 );

    References = -- Credential->References;

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

    if ( References == 0 ) {

        LPWSTR DomainName = Credential->DomainName.Buffer;
        LPWSTR UserName = Credential->UserName.Buffer;
        LPWSTR Password = Credential->Password.Buffer;
        // note: Password.Length may contain run-encoding hint, so size may be illegal.
        DWORD cbPassword = Credential->Password.MaximumLength;
        HANDLE ClientTokenHandle = Credential->ClientTokenHandle;

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

        if (!Credential->Unlinked) {
            RemoveEntryList( &Credential->Next );
        }

        ZeroMemory( Credential, sizeof(SSP_CREDENTIAL) );

        LeaveCriticalSection( &SspCredentialCritSect );

        if ( DomainName ) {
            (VOID) NtLmFree( DomainName );
        }
        if ( UserName ) {
            (VOID) NtLmFree( UserName );
        }
        if ( Password ) {
            ZeroMemory( Password, cbPassword );
            (VOID) NtLmFree( Password );
        }

        if ( ClientTokenHandle ) {
            (VOID) NtClose( ClientTokenHandle );
        }

        (VOID) NtLmFree( Credential );

        return;
    }

    LeaveCriticalSection( &SspCredentialCritSect );

    return;

}

BOOLEAN
SsprCheckMachineLogon(
    IN  OUT PLUID pLogonId,
    IN      PUNICODE_STRING UserName,
    IN      PUNICODE_STRING DomainName,
    IN      PUNICODE_STRING Password
    )
/*++

Routine Description:

    This routine determines if the input credential matches a special
    machine account logon over-ride.

Return Value:

    TRUE - the intput credential was the special machine account logon over-ride.
           the pLogonId is updated to utilize the machine credential.

--*/
{
    UNICODE_STRING MachineAccountName;
    static LUID LogonIdSystem = SYSTEM_LUID ;
    BOOLEAN fMachineLogon = FALSE;

    MachineAccountName.Buffer = NULL;


    //
    // check if caller was system, and requested machine credential
    // eg: user=computername$, domain=NULL, password=NULL
    //

    if( !RtlEqualLuid( pLogonId, &LogonIdSystem ) )
    {
        return FALSE;
    }


    if( UserName->Buffer == NULL )
    {
        return FALSE;
    }

    if( DomainName->Buffer != NULL )
    {
        return FALSE;
    }

    if( Password->Buffer != NULL )
    {
        return FALSE;
    }


    EnterCriticalSection (&NtLmGlobalCritSect);

    MachineAccountName.Length = NtLmGlobalUnicodeComputerNameString.Length + sizeof(WCHAR);

    if( MachineAccountName.Length == UserName->Length )
    {
        MachineAccountName.MaximumLength = MachineAccountName.Length;
        MachineAccountName.Buffer = (PWSTR)NtLmAllocate( MachineAccountName.Length );

        if( MachineAccountName.Buffer != NULL )
        {
            RtlCopyMemory(  MachineAccountName.Buffer,
                            NtLmGlobalUnicodeComputerNameString.Buffer,
                            NtLmGlobalUnicodeComputerNameString.Length
                            );

            MachineAccountName.Buffer[ (MachineAccountName.Length / sizeof(WCHAR)) - 1 ] = L'$';
        }
    }

    LeaveCriticalSection (&NtLmGlobalCritSect);


    if( MachineAccountName.Buffer == NULL )
    {
        goto Cleanup;
    }

    if( RtlEqualUnicodeString( &MachineAccountName, UserName, TRUE ) )
    {
        //
        // yes, it's a machine account logon request, update the
        // requested LogonId to match our mapped logon session.
        //

        *pLogonId = NtLmGlobalLuidMachineLogon;
        fMachineLogon = TRUE;
    }


Cleanup:

    if( MachineAccountName.Buffer )
    {
        NtLmFree( MachineAccountName.Buffer );
    }

    return fMachineLogon;
}


NTSTATUS
SsprAcquireCredentialHandle(
    IN PHANDLE TokenHandle,
    IN PLUID LogonId,
    IN ULONG ClientProcessID,
    IN ULONG CredentialUseFlags,
    OUT PLSA_SEC_HANDLE CredentialHandle,
    OUT PTimeStamp Lifetime,
    IN OPTIONAL PUNICODE_STRING DomainName,
    IN OPTIONAL PUNICODE_STRING UserName,
    IN OPTIONAL PUNICODE_STRING Password
    )

/*++

Routine Description:

    This API allows applications to acquire a handle to pre-existing
    credentials associated with the user on whose behalf the call is made
    i.e. under the identity this application is running.  These pre-existing
    credentials have been established through a system logon not described
    here.  Note that this is different from "login to the network" and does
    not imply gathering of credentials.


    This API returns a handle to the credentials of a principal (user, client)
    as used by a specific security package.  This handle can then be used
    in subsequent calls to the Context APIs.  This API will not let a
    process obtain a handle to credentials that are not related to the
    process; i.e. we won't allow a process to grab the credentials of
    another user logged into the same machine.  There is no way for us
    to determine if a process is a trojan horse or not, if it is executed
    by the user.

Arguments:

    CredentialUseFlags - Flags indicating the way with which these
        credentials will be used.

        #define     CRED_INBOUND        0x00000001
        #define     CRED_OUTBOUND       0x00000002
        #define     CRED_BOTH           0x00000003

        The credentials created with CRED_INBOUND option can only be used
        for (validating incoming calls and can not be used for making accesses.

    CredentialHandle - Returned credential handle.

    Lifetime - Time that these credentials expire. The value returned in
        this field depends on the security package.

    DomainName, DomainNameSize, UserName, UserNameSize, Password, PasswordSize -
        Optional credentials for this user.

Return Value:

    STATUS_SUCCESS -- Call completed successfully

    SEC_E_PRINCIPAL_UNKNOWN -- No such principal
    SEC_E_NOT_OWNER -- caller does not own the specified credentials
    STATUS_NO_MEMORY -- Not enough memory

--*/

{
    SspPrint((SSP_API_MORE, "Entering SsprAcquireCredentialHandle\n"));

    NTSTATUS Status = STATUS_SUCCESS;
    PSSP_CREDENTIAL Credential = NULL;
    SECPKG_CALL_INFO CallInfo ;

    if ( !LsaFunctions->GetCallInfo( &CallInfo ) )
    {
        return STATUS_UNSUCCESSFUL ;
    }

    //
    // If this is an outbound credential, and supplemental credentials
    // were supplied, look to see if we have already
    // created one with this set of credentials. Note - this leaves
    // the credential referenced, so if we fail further down we need to
    // dereference the credential.
    //

    if ((CredentialUseFlags & SECPKG_CRED_OUTBOUND) != 0) {

        //
        // check if machine account logon over-ride.
        //

        SsprCheckMachineLogon(
                        LogonId,
                        UserName,
                        DomainName,
                        Password
                        );

        Credential = SspCredentialLookupSupplementalCredential(
                        LogonId,
                        CredentialUseFlags,
                        UserName,
                        DomainName,
                        Password
                        );

⌨️ 快捷键说明

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