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

📄 nlpcache.c

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

Copyright (c) 1991 - 1999  Microsoft Corporation

Module Name:

    nlpcache.c

Abstract:

    This module contains routines which implement user account caching:

        NlpCacheInitialize
        NlpCacheTerminate
        NlpAddCacheEntry
        NlpGetCacheEntry
        NlpDeleteCacheEntry
        NlpChangeCachePassword


    The cache contains the most recent validated logon information. There is
    only 1 (that's right - one) cache slot. This will probably change though

Author:

    Richard L Firth (rfirth) 17-Dec-1991

    BUGBUG - To Be Done:

             1. call Lsar routines instead of going via Rpc. Use:
                    LsaIOpenPolicyTruseted()
                    Lsar routines to do work
                    LsaIFree() to free returned buffers

Revision History:

   Scott Field (sfield)   04-Jun-99
        Add supplemental cache data.
        Store all cache related data in single location.
        Encrypt interesting elements of cache entry using per-entry key mixed with per-machine key.
        MAC interesting cache elements for integrity check.
        Drastically reduce lock contention.
        Avoid NtFlushKey() for single location cache elements.
        Avoid persisting a new cache entry that matches an existing one.
        Attempt reg query with stack based buffer first.

   Chandana Surlu         21-Jul-96      Stolen from \\kernel\razzle3\src\security\msv1_0\nlpcache.c

--*/

#include <global.h>
#undef EXTERN

#include "msp.h"
#include "nlp.h"
#include "nlpcache.h"


#include <rc4.h>


//
// manifests
//

#if DBG
#include <stdio.h>
#endif

//
// Revision numbers
//
//      NT 3.0 didn't explicitly store a revision number.
//          However, we are designating that release to be revision 0x00010000 (1.0).
//      NT 3.5 prior to build 622 is revision 0x00010001 (1.1).
//      NT 3.5 is revision 0x00010002 (1.2).
//      NT 4.0 SP 4 is revision 0x00010003 (1.3)
//      NT 5.0 build 2054+ is revision 0x00010004 (1.4)
//

#define NLP_CACHE_REVISION_NT_1_0         (0x00010000)  // NT 3.0
#define NLP_CACHE_REVISION_NT_1_0B        (0x00010002)  // NT 3.5
#define NLP_CACHE_REVISION_NT_4_SP4       (0x00010003)  // NT 4.0 SP 4 to save passwords as salted.
#define NLP_CACHE_REVISION_NT_5_0         (0x00010004)  // NT 5.0 to support opaque cache data and single location data storage.
#define NLP_CACHE_REVISION                (NLP_CACHE_REVISION_NT_5_0)





//
// The logon cache may be controlled via a value in the registry.
// If the registry key does not exist, then this default constant defines
// how many logon cache entries will be active.  The max constant
// places an upper limit on how many cache entries we will support.
// If the user specifies more than the max value, we will use the
// max value instead.
//

#define NLP_DEFAULT_LOGON_CACHE_COUNT           (10)
#define NLP_MAX_LOGON_CACHE_COUNT               (50)


//
// length of per-machine cache encryption key.
//

#define NLP_CACHE_ENCRYPTION_KEY_LEN            (64)

//
// name of LSA secret containing cache encryption key.
//

#define NLP_CACHE_ENCRYPTION_KEY_NAME           L"NL$KM"


//
// macros
//

#define AllocateCacheEntry(n)   (PLOGON_CACHE_ENTRY)RtlAllocateHeap(MspHeap, 0, n)
#define FreeCacheEntry(p)       RtlFreeHeap(MspHeap, 0, (PVOID)p)
#define AllocateFromHeap(n)     RtlAllocateHeap(MspHeap, 0, n)
#define FreeToHeap(p)           RtlFreeHeap(MspHeap, 0, (PVOID)p)

//
// guard against simultaneous access
//

#define ENTER_CACHE()   RtlEnterCriticalSection(&NlpLogonCacheCritSec)
#define LEAVE_CACHE()   RtlLeaveCriticalSection(&NlpLogonCacheCritSec)

#define INVALIDATE_HANDLE(handle) (*((PHANDLE)(&handle)) = INVALID_HANDLE_VALUE)
#define IS_VALID_HANDLE(handle)   (handle != INVALID_HANDLE_VALUE)


////////////////////////////////////////////////////////////////////////
//                                                                    //
// datatypes                                                          //
//                                                                    //
////////////////////////////////////////////////////////////////////////

typedef enum _NLP_SET_TIME_HINT {
    NLP_SMALL_TIME,
    NLP_BIG_TIME,
    NLP_NOW_TIME
} NLP_SET_TIME_HINT, *PNLP_SET_TIME_HINT;

#define BIG_PART_1      0x7fffffff  // largest positive large int is 63 bits on
#define BIG_PART_2      0xffffffff
#define SMALL_PART_1    0x0         // smallest positive large int is 64 bits off
#define SMALL_PART_2    0x0


//
// This structure is saved on disk and provides information
// about the rest of the cache.  This structure is in a value
// named "NL$Control" under the cache registry key.
//

typedef struct _NLP_CACHE_CONTROL {

    //
    // Revision of the cache on-disk structure
    //

    ULONG       Revision;

    //
    // The current on-disk size of the cache (number of entries)
    //

    ULONG       Entries;

} NLP_CACHE_CONTROL, *PNLP_CACHE_CONTROL;


//
// This data structure is a single cache table entry (CTE)
// Each entry in the cache has a corresponding CTE.
//

typedef struct _NLP_CTE {

        //
        // CTEs are linked on either an invalid list (in any order)
        // or on a valid list (in ascending order of time).
        // This makes it easy to figure out which entry is to be
        // flushed when adding to the cache.
        //

        LIST_ENTRY Link;


        //
        // Time the cache entry was established.
        // This is used to determine which cache
        // entry is the oldest, and therefore will
        // be flushed from the cache first to make
        // room for new entries.
        //

        LARGE_INTEGER       Time;


        //
        // This field contains the index of the CTE within the
        // CTE table.  This index is used to generate the names
        // of the entrie's secret key and cache key in the registry.
        // This field is valid even if the entry is marked Inactive.
        //

        ULONG               Index;

        //
        // Normally, we walk the active and inactive lists
        // to find entries.  When growing or shrinking the
        // cache, however, it is nice to be able to walk the
        // table using indexes.  In this case, it is nice to
        // have a local way of determining whether an entry
        // is on the active or inactive list.  This field
        // provides that capability.
        //
        //      TRUE  ==> on active list
        //      FALSE ==> not on active list
        //

        BOOLEAN             Active;


} NLP_CTE, *PNLP_CTE;

//
// This structure is used for keeping track of all information that
// is stored on backing store.
//

typedef struct _NLP_CACHE_AND_SECRETS {
    PLOGON_CACHE_ENTRY          CacheEntry;
    ULONG                       EntrySize;
    PLSAPR_CR_CIPHER_VALUE      NewSecret;
    PLSAPR_CR_CIPHER_VALUE      OldSecret;
    BOOLEAN                     Active;
} NLP_CACHE_AND_SECRETS,  *PNLP_CACHE_AND_SECRETS;


////////////////////////////////////////////////////////////////////////
//                                                                    //
// Local Prototypes                                                   //
//                                                                    //
////////////////////////////////////////////////////////////////////////

NTSTATUS
NlpInternalCacheInitialize(
    VOID
    );

NTSTATUS
NlpOpenCache( VOID );

VOID
NlpCloseCache( VOID );


NTSTATUS
NlpGetCacheControlInfo( VOID );

NTSTATUS
NlpCacheKeyInitialize(
    VOID
    );

NTSTATUS
NlpBuildCteTable( VOID );

NTSTATUS
NlpChangeCacheSizeIfNecessary( VOID );

NTSTATUS
NlpWriteCacheControl( VOID );

VOID
NlpMakeCacheEntryName(
    IN  ULONG               EntryIndex,
    OUT PUNICODE_STRING     Name
    );

NTSTATUS
NlpMakeNewCacheEntry(
    ULONG           Index
    );

NTSTATUS
NlpEliminateCacheEntry(
    IN  ULONG               Index
    );

NTSTATUS
NlpConvert1_0To1_0B( VOID );

NTSTATUS
NlpOpen_Nt1_0_Secret( VOID );

NTSTATUS
NlpReadCacheEntryByIndex(
    IN  ULONG               Index,
    OUT PLOGON_CACHE_ENTRY* CacheEntry,
    OUT PULONG EntrySize
    );

VOID
NlpAddEntryToActiveList(
    IN  ULONG   Index
    );

VOID
NlpAddEntryToInactiveList(
    IN  ULONG   Index
    );

VOID
NlpGetFreeEntryIndex(
    OUT PULONG  Index
    );


NTSTATUS
NlpBuildCacheEntry(
    IN  PNETLOGON_INTERACTIVE_INFO LogonInfo,
    IN  PNETLOGON_VALIDATION_SAM_INFO2 AccountInfo,
    OUT PLOGON_CACHE_ENTRY* ppCacheEntry,
    OUT PULONG pEntryLength
    );


NTSTATUS
NlpEncryptCacheEntry(
    IN  PLOGON_CACHE_ENTRY CacheEntry,
    IN  ULONG EntrySize
    );

NTSTATUS
NlpDecryptCacheEntry(
    IN  PLOGON_CACHE_ENTRY CacheEntry,
    IN  ULONG EntrySize
    );

NTSTATUS
NlpAddSupplementalCacheData(
    IN      PVOID SupplementalCacheData,
    IN      ULONG SupplementalCacheDataLength,
    IN OUT  PLOGON_CACHE_ENTRY *ppCacheEntry,
    IN OUT  PULONG pEntryLength
    );

NTSTATUS
NlpOpenCache( VOID );

VOID
NlpCloseCache( VOID );

NTSTATUS
NlpOpenSecret(
    IN  ULONG   Index
    );

VOID
NlpCloseSecret( VOID );

NTSTATUS
NlpWriteSecret(
    IN  PLSAPR_CR_CIPHER_VALUE NewSecret,
    IN  PLSAPR_CR_CIPHER_VALUE OldSecret
    );

NTSTATUS
NlpReadSecret(
    OUT PLSAPR_CR_CIPHER_VALUE * NewSecret,
    OUT PLSAPR_CR_CIPHER_VALUE * OldSecret
    );

NTSTATUS
NlpMakeSecretPassword(
    OUT PLSAPR_CR_CIPHER_VALUE Passwords,
    IN  PUNICODE_STRING UserName,
    IN  PNT_OWF_PASSWORD NtOwfPassword OPTIONAL,
    IN  PLM_OWF_PASSWORD LmOwfPassword OPTIONAL
    );

NTSTATUS
NlpMakeSecretPasswordNT5(
    IN OUT PCACHE_PASSWORDS Passwords,
    IN  PUNICODE_STRING UserName,
    IN  PNT_OWF_PASSWORD NtOwfPassword OPTIONAL,
    IN  PLM_OWF_PASSWORD LmOwfPassword OPTIONAL
    );

NTSTATUS
NlpReadCacheEntry(
    IN PUNICODE_STRING DomainName,
    IN PUNICODE_STRING UserName,
    OUT PULONG              Index,
    OUT PLOGON_CACHE_ENTRY* CacheEntry,
    OUT PULONG              EntrySize
    );

NTSTATUS
NlpWriteCacheEntry(
    IN  ULONG              Index,
    IN  PLOGON_CACHE_ENTRY Entry,
    IN  ULONG              EntrySize
    );

VOID
NlpCopyAndUpdateAccountInfo(
    IN  USHORT Length,
    IN  PUNICODE_STRING pUnicodeString,
    IN OUT PUCHAR* pSource,
    IN OUT PUCHAR* pDest
    );

VOID
NlpSetTimeField(
    OUT POLD_LARGE_INTEGER pTimeField,
    IN  NLP_SET_TIME_HINT Hint
    );

NTSTATUS
NlpBuildAccountInfo(
    IN  PLOGON_CACHE_ENTRY pCacheEntry,
    IN  ULONG EntryLength,
    OUT PNETLOGON_VALIDATION_SAM_INFO2* AccountInfo
    );



/////////////////////////////////////////////////////////////////////////
//                                                                     //
//          Diagnostic support services prototypes                     //
//                                                                     //
/////////////////////////////////////////////////////////////////////////


#if DBG
PCHAR
DumpOwfPasswordToString(
    OUT PCHAR Buffer,
    IN  PLM_OWF_PASSWORD Password
    );

VOID
DumpLogonInfo(
    IN  PNETLOGON_LOGON_IDENTITY_INFO LogonInfo
    );

char*
MapWeekday(
    IN  CSHORT  Weekday
    );

VOID
DumpTime(
    IN  LPSTR   String,
    IN  POLD_LARGE_INTEGER OldTime
    );

VOID
DumpGroupIds(
    IN  LPSTR   String,
    IN  ULONG   Count,
    IN  PGROUP_MEMBERSHIP GroupIds
    );

VOID
DumpSessKey(
    IN  LPSTR   String,
    IN  PUSER_SESSION_KEY Key
    );

VOID
DumpSid(
    LPSTR   String,
    PISID   Sid
    );

VOID
DumpAccountInfo(
    IN  PNETLOGON_VALIDATION_SAM_INFO2 AccountInfo
    );

VOID
DumpCacheEntry(
    IN  ULONG              Index,
    IN  PLOGON_CACHE_ENTRY pEntry
    );

#endif //DBG




////////////////////////////////////////////////////////////////////////
//                                                                    //
// global data                                                        //
//                                                                    //
////////////////////////////////////////////////////////////////////////

//
// This boolean indicates whether or not we have been able to
// initialize caching yet.  It turn out that during authentication
// package load time, we can't do everything we would like to (like
// call LSA RPC routines).  So, we delay initializing until we can
// call LSA.  All publicly exposed interfaces must check this value
// before assuming work can be done.
//

BOOLEAN     NlpInitializationNotYetPerformed = TRUE;


⌨️ 快捷键说明

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