📄 nlpcache.c
字号:
/*++
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 + -