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

📄 nlpcache.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:
RTL_CRITICAL_SECTION NlpLogonCacheCritSec;



HANDLE        NlpCacheHandle  = (HANDLE)     INVALID_HANDLE_VALUE;
LSAPR_HANDLE  NlpLsaHandle    = (LSAPR_HANDLE) INVALID_HANDLE_VALUE;
LSAPR_HANDLE  NlpSecretHandle = (LSAPR_HANDLE) INVALID_HANDLE_VALUE;

//
// control information about the cache (number of entries, etc).
//

NLP_CACHE_CONTROL   NlpCacheControl;

//
// This structure is generated and maintained only in memory.
// It indicates which cache entries are valid and which aren't.
// It also indicates what time each entry was established so we
// know which order to discard them in.
//
//  This field is a pointer to an array of CTEs.  The number of CTEs
//  in the array is in NlpCacheControl.Entries.  This structure is
//  allocated at initialization time.
//

PNLP_CTE            NlpCteTable;


//
// The Cache Table Entries in NlpCteTable are linked on either an
// active or inactive list.  The entries on the active list are in
// ascending time order - so the last one on the list is the first
// one to be discarded when a flush is needed to add a new entry.
//

LIST_ENTRY          NlpActiveCtes;
LIST_ENTRY          NlpInactiveCtes;


//
// global, per-machine key used for encrypting NT_5_0 version cache
// entries.
//

CHAR                NlpCacheEncryptionKey[ NLP_CACHE_ENCRYPTION_KEY_LEN ];



#if DBG
#ifdef DUMP_CACHE_INFO
ULONG   DumpCacheInfo = 1;
#else
ULONG   DumpCacheInfo = 0;
#endif
#endif



////////////////////////////////////////////////////////////////////////
//                                                                    //
// Services Exported by this module                                   //
//                                                                    //
////////////////////////////////////////////////////////////////////////






NTSTATUS
NlpCacheInitialize(
    VOID
    )

/*++

Routine Description:

    This routine is called to initialize cached logon processing.

    Unfortunately, there isn't much we can do when we are called.
    (we can't open LSA, for example).  So, defer initialization
    until later.


Arguments:

    None.

Return Value:

    NTSTATUS

--*/

{
    return RtlInitializeCriticalSection(&NlpLogonCacheCritSec);
}


NTSTATUS
NlpCacheTerminate(
    VOID
    )

/*++

Routine Description:

    Called when process detaches

Arguments:

    None.

Return Value:

    NTSTATUS

--*/

{
#if DBG
    if (DumpCacheInfo) {
        DbgPrint("NlpCacheTerminate\n");
    }
#endif

    if (!NlpInitializationNotYetPerformed) {
        NlpCloseCache();
        NlpCloseSecret();

        if (IS_VALID_HANDLE(NlpLsaHandle)) {
            I_LsarClose( &NlpLsaHandle );
        }
        if (IS_VALID_HANDLE(NlpCacheHandle)) {
            NtClose( NlpCacheHandle );
        }

        FreeToHeap( NlpCteTable );
    }

    return RtlDeleteCriticalSection(&NlpLogonCacheCritSec);

}


NTSTATUS
NlpGetCacheEntry(
    IN  PNETLOGON_LOGON_IDENTITY_INFO LogonInfo,
    OUT PNETLOGON_VALIDATION_SAM_INFO2* AccountInfo,
    OUT PCACHE_PASSWORDS Passwords,
    OUT PVOID *ppSupplementalCacheData OPTIONAL ,
    OUT PULONG SupplementalCacheDataLength OPTIONAL
    )

/*++

Routine Description:

    If the user logging on has information stored in the cache,
    then it is retrieved. Also returns the cached password from
    'secret' storage

Arguments:

    LogonInfo   - pointer to NETLOGON_IDENTITY_INFO structure which contains
                  the domain name, user name for this user

    AccountInfo - pointer to NETLOGON_VALIDATION_SAM_INFO2 structure to
                  receive this user's specific interactive logon information

    Passwords   - pointer to CACHE_PASSWORDS structure to receive passwords
                  returned from secret storage

Return Value:

    NTSTATUS
        Success = STATUS_SUCCESS
                    *AccountInfo points to a NETLOGON_VALIDATION_SAM_INFO2
                    structure. This must be freed by caller

                    *Passwords contain USER_INTERNAL1_INFORMATION structure
                    which contains NT OWF password and LM OWF password. These
                    must be used to validate the logon

        Failure = STATUS_LOGON_FAILURE
                    The user logging on isn't in the cache.

--*/

{
    NTSTATUS
        NtStatus;

    PNETLOGON_VALIDATION_SAM_INFO2
        SamInfo = NULL;

    PLOGON_CACHE_ENTRY
        CacheEntry = NULL;

    ULONG
        EntrySize,
        Index;

    PLSAPR_CR_CIPHER_VALUE
        CurrentSecret = NULL,
        OldSecret = NULL;


    BOOLEAN fCacheLocked = FALSE;


    *AccountInfo = NULL;

    if( ppSupplementalCacheData )
        *ppSupplementalCacheData = NULL;


#if DBG
    if (DumpCacheInfo) {
        DbgPrint("NlpGetCacheEntry\n");
        DumpLogonInfo(LogonInfo);
    }
#endif

    if (NlpInitializationNotYetPerformed) {
        NtStatus = NlpInternalCacheInitialize();
        if (!NT_SUCCESS(NtStatus)) {
            return(NtStatus);
        }
    }

    if (NlpCacheControl.Entries == 0) {
        return(STATUS_LOGON_FAILURE);
    }

    ENTER_CACHE();
    fCacheLocked = TRUE;

    //
    // Find the cache entry and open its secret (if found)
    //

    NtStatus = NlpReadCacheEntry(&LogonInfo->LogonDomainName,
                                 &LogonInfo->UserName,
                                 &Index,
                                 &CacheEntry,
                                 &EntrySize);

    if(!NT_SUCCESS(NtStatus)) {
        LEAVE_CACHE();
        return (NtStatus);
    }

    if( CacheEntry->Revision >= NLP_CACHE_REVISION_NT_5_0 ) {

        //
        // for NT5, we can release the cache lock now, since all data
        // stored in one place.
        //

        LEAVE_CACHE();
        fCacheLocked = FALSE;

        //
        // if caller wanted supplemental data, give it to them.
        //

        if( ppSupplementalCacheData  && SupplementalCacheDataLength ) {

            *SupplementalCacheDataLength = CacheEntry->SupplementalCacheDataLength;

            *ppSupplementalCacheData = MIDL_user_allocate( *SupplementalCacheDataLength );

            if( *ppSupplementalCacheData == NULL ) {
                NtStatus = STATUS_NO_MEMORY;
            } else {

                LPBYTE Source;

                //
                // note: the decrypt operation that occurred during the
                // ReadCacheEntry validates any data and pointers through
                // integrity checking via HMAC.  Having said that, we can be
                // lazy and not do boundry checking.
                //

                Source = ((LPBYTE)CacheEntry + CacheEntry->SupplementalCacheDataOffset);

                CopyMemory( *ppSupplementalCacheData,
                            Source,
                            *SupplementalCacheDataLength
                            );
            }
        }

    }


    NtStatus = NlpBuildAccountInfo(CacheEntry, EntrySize, &SamInfo);
    if (NT_SUCCESS(NtStatus)) {


        if( CacheEntry->Revision >= NLP_CACHE_REVISION_NT_5_0 ) {

            //
            // for NT5, the Passwords are stored in the CacheEntry.
            // note: passwords are assumed to be salted.
            //

            RtlCopyMemory( Passwords, &(CacheEntry->CachePasswords), sizeof(*Passwords) );


        } else {

            //
            // prior to NT5, the Passwords are stored separately in their
            // own LSA secret.
            //

            NtStatus = NlpReadSecret(&CurrentSecret, &OldSecret);

            //
            // can release the cache lock now, since second data item fetched.
            //

            LEAVE_CACHE();
            fCacheLocked = FALSE;

            if (NT_SUCCESS(NtStatus)) {

                if (CurrentSecret) {
                    //
                    // Check to see which version of the passwords are stored
                    // here - the normal or the salted.
                    //

                    RtlCopyMemory((PVOID)Passwords,
                        (PVOID)CurrentSecret->Buffer,
                        (ULONG)CurrentSecret->Length
                        );
                    if (CacheEntry->Revision < NLP_CACHE_REVISION_NT_4_SP4 ) {
                        if (Passwords->SecretPasswords.NtPasswordPresent) {
                            NtStatus = NlpComputeSaltedHashedPassword(
                                            &Passwords->SecretPasswords.NtOwfPassword,
                                            &Passwords->SecretPasswords.NtOwfPassword,
                                            &SamInfo->EffectiveName
                                            );
                        }
                        if (NT_SUCCESS(NtStatus) && Passwords->SecretPasswords.LmPasswordPresent) {
                            NtStatus = NlpComputeSaltedHashedPassword(
                                            &Passwords->SecretPasswords.LmOwfPassword,
                                            &Passwords->SecretPasswords.LmOwfPassword,
                                            &SamInfo->EffectiveName
                                            );

                        }

                    }
                }
            }

        }

    }



    if( fCacheLocked ) {
        LEAVE_CACHE();
    }


    //
    // free structure allocated by NlpReadCacheEntry
    //

    if( CacheEntry ) {
        ZeroMemory( CacheEntry, EntrySize );
        FreeToHeap(CacheEntry);
    }


    //
    // free structures allocated by NlpReadSecret
    //

    if (CurrentSecret) {
        MIDL_user_free(CurrentSecret);
    }
    if (OldSecret) {
        MIDL_user_free(OldSecret);
    }


    if( NT_SUCCESS( NtStatus ) ) {
        *AccountInfo = SamInfo;
    } else {

        if ( SamInfo != NULL ) {
            MIDL_user_free( SamInfo );
        }

        if( ppSupplementalCacheData && *ppSupplementalCacheData ) {
            MIDL_user_free( *ppSupplementalCacheData );
            *ppSupplementalCacheData = NULL;
        }
    }

    return(NtStatus);
}


NTSTATUS
NlpAddCacheEntry(
    IN  PNETLOGON_INTERACTIVE_INFO LogonInfo,
    IN  PNETLOGON_VALIDATION_SAM_INFO2 AccountInfo,
    IN  PVOID SupplementalCacheData,
    IN  ULONG SupplementalCacheDataLength
    )

/*++

Routine Description:

    Adds this domain:user interactive logon information to the cache.

Arguments:

    LogonInfo   - pointer to NETLOGON_INTERACTIVE_INFO structure which contains
                  the domain name, user name and password for this user. These
                  are what the user typed to WinLogon

    AccountInfo - pointer to NETLOGON_VALIDATION_SAM_INFO2 structure which
                  contains this user's specific interactive logon information

Return Value:

    NTSTATUS
        Success = STATUS_SUCCESS
                    AccountInfo successfully added to cache

        Failure = STATUS_NO_MEMORY


--*/

{
    NTSTATUS
        NtStatus;

    PLOGON_CACHE_ENTRY
        CacheEntry = NULL;

    PLOGON_CACHE_ENTRY
        CacheEntryExisting = NULL;

    ULONG
        EntrySize,
        EntrySizeExisting,
        Index;



#if DBG
    if (DumpCacheInfo) {
        DbgPrint("NlpAddCacheEntry\n");
        DumpLogonInfo(&LogonInfo->Identity);
        DumpAccountInfo(AccountInfo);
    }
#endif

    if (NlpInitializationNotYetPerformed) {
        NtStatus = NlpInternalCacheInitialize();
        if (!NT_SUCCESS(NtStatus)) {
            return(NtStatus);
        }
    }

    if (NlpCacheControl.Entries == 0) {
        return(STATUS_SUCCESS);
    }



    //
    // build base cache entry.
    //

    NtStatus = NlpBuildCacheEntry(LogonInfo, AccountInfo, &CacheEntry, &EntrySize);

    if(!NT_SUCCESS(NtStatus) )
        return (NtStatus);



    //
    // add any supplemental data to the cache entry.
    // (this is new for NT5).
    //

    NtStatus = NlpAddSupplementalCacheData(
                            SupplementalCacheData,
                            SupplementalCacheDataLength,
                            &CacheEntry,
                            &EntrySize
                            );


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

    //
    // add in salted OWFs.
    //

    NtStatus = NlpMakeSecretPasswordNT5(

⌨️ 快捷键说明

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