📄 nlpcache.c
字号:
&CacheEntry->CachePasswords,
&AccountInfo->EffectiveName,
&LogonInfo->NtOwfPassword,
&LogonInfo->LmOwfPassword
);
if(!NT_SUCCESS(NtStatus)) {
goto Cleanup;
}
//
// encrypt sensitive portions of the cache entry.
//
NtStatus = NlpEncryptCacheEntry(CacheEntry, EntrySize);
if(!NT_SUCCESS(NtStatus)) {
goto Cleanup;
}
ENTER_CACHE();
//
// See if this entry already exists in the cache.
// If so, use the same index.
//
NtStatus = NlpReadCacheEntry(&LogonInfo->Identity.LogonDomainName,
&LogonInfo->Identity.UserName,
&Index,
&CacheEntryExisting,
&EntrySizeExisting
);
//
// If we didn't find an entry, then we need to allocate an
// entry.
//
if (!NT_SUCCESS(NtStatus)) {
NlpGetFreeEntryIndex( &Index );
CacheEntryExisting = NULL;
} else {
//
// We already have an entry for this user.
// Discard the structure we got back but
// use the same index.
// Note: structure discarded outside cache lock.
//
// TODO: check if existing entry matches new built entry.
// if so, avoid write.
}
//
// now, write the entry out...
//
NtStatus = NlpWriteCacheEntry(Index, CacheEntry, EntrySize);
if (NT_SUCCESS(NtStatus)) {
NlpCteTable[Index].Time = CacheEntry->Time;
NlpAddEntryToActiveList( Index );
}
LEAVE_CACHE();
Cleanup:
if( CacheEntry ) {
ZeroMemory( CacheEntry, EntrySize );
FreeCacheEntry( CacheEntry );
}
if( CacheEntryExisting ) {
ZeroMemory( CacheEntryExisting, EntrySizeExisting );
FreeCacheEntry( CacheEntryExisting );
}
return(NtStatus);
}
NTSTATUS
NlpAddSupplementalCacheData(
IN PVOID SupplementalCacheData,
IN ULONG SupplementalCacheDataLength,
IN OUT PLOGON_CACHE_ENTRY *ppCacheEntry,
IN OUT PULONG pEntryLength
)
/*++
Routine Description:
Extends the supplied LOGON_CACHE_ENTRY with opaque authentication package
SupplementalCacheData (eg: smart-card logon cache info).
Return Value:
NTSTATUS
Success = STATUS_SUCCESS
Failure =
--*/
{
PLOGON_CACHE_ENTRY NewCacheEntry = NULL;
if( (*ppCacheEntry)->Revision < NLP_CACHE_REVISION_NT_5_0 ) {
return STATUS_SUCCESS;
}
(*ppCacheEntry)->SupplementalCacheDataLength = SupplementalCacheDataLength;
(*ppCacheEntry)->SupplementalCacheDataOffset = *pEntryLength;
if( SupplementalCacheData == NULL || SupplementalCacheDataLength == 0 ) {
return STATUS_SUCCESS;
}
//
// allocate new entry, and copy existing entry + supplemental data to end.
//
NewCacheEntry = AllocateCacheEntry( *pEntryLength + SupplementalCacheDataLength );
if( NewCacheEntry == NULL ) {
return STATUS_NO_MEMORY;
}
CopyMemory( NewCacheEntry, *ppCacheEntry, *pEntryLength );
CopyMemory( ((PBYTE)(NewCacheEntry) + *pEntryLength),
SupplementalCacheData,
SupplementalCacheDataLength
);
ZeroMemory( *ppCacheEntry, *pEntryLength );
FreeCacheEntry( *ppCacheEntry );
*ppCacheEntry = NewCacheEntry;
*pEntryLength += SupplementalCacheDataLength;
return STATUS_SUCCESS;
}
NTSTATUS
NlpDeleteCacheEntry(
IN PNETLOGON_INTERACTIVE_INFO LogonInfo
)
/*++
Routine Description:
Deletes a user account from the local user account cache, if the corresponding
entry can be found. We actually just null out the current contents instead of
destroying the storage - this should save us some time when we next come to
add an entry to the cache
Arguments:
LogonInfo - pointer to NETLOGON_INTERACTIVE_INFO structure which contains
the domain name, user name and password for this user
Return Value:
NTSTATUS
Success = STATUS_SUCCESS
Failure =
--*/
{
NTSTATUS
NtStatus;
PLOGON_CACHE_ENTRY
CacheEntry = NULL;
ULONG
EntrySize,
Index;
if (NlpInitializationNotYetPerformed) {
NtStatus = NlpInternalCacheInitialize();
if (!NT_SUCCESS(NtStatus)) {
return(NtStatus);
}
}
if (NlpCacheControl.Entries == 0) {
return(STATUS_SUCCESS);
}
ENTER_CACHE();
//
// See if this entry exists in the cache.
//
NtStatus = NlpReadCacheEntry( &LogonInfo->Identity.LogonDomainName,
&LogonInfo->Identity.UserName,
&Index,
&CacheEntry,
&EntrySize
);
//
// If we didn't find an entry, then there is nothing to do.
//
if (!NT_SUCCESS(NtStatus)) {
LEAVE_CACHE();
return(STATUS_SUCCESS);
}
//
// Mark it as invalid.
//
CacheEntry->Valid = FALSE;
NtStatus = NlpWriteCacheEntry( Index, CacheEntry, EntrySize );
if (NT_SUCCESS(NtStatus)) {
//
// Put the CTE entry on the inactive list.
//
NlpAddEntryToInactiveList( Index );
}
LEAVE_CACHE();
//
// Free the structure returned from NlpReadCacheEntry()
//
if( CacheEntry ) {
ZeroMemory( CacheEntry, EntrySize );
FreeToHeap( CacheEntry );
}
return(NtStatus);
}
VOID
NlpChangeCachePassword(
IN PUNICODE_STRING DomainName,
IN PUNICODE_STRING UserName,
IN PLM_OWF_PASSWORD LmOwfPassword,
IN PNT_OWF_PASSWORD NtOwfPassword
)
/*++
Routine Description:
Update a cached password to the specified value, if we have
the specified account cached.
Arguments:
DomainName - The name of the domain in which the account exists.
UserName - The name of the account whose password is to be changed.
LmOwfPassword - The new LM compatible password.
NtOwfPassword - The new NT compatible password.
Return Value:
None.
--*/
{
NTSTATUS
NtStatus;
PLOGON_CACHE_ENTRY
CacheEntry = NULL;
ULONG
EntrySize,
Index;
PLSAPR_CR_CIPHER_VALUE
CurrentSecret = NULL,
OldSecret = NULL;
LSAPR_CR_CIPHER_VALUE
Passwords;
#if DBG
if (DumpCacheInfo) {
DbgPrint("NlpChangeCachePassword\n");
}
#endif
if (NlpInitializationNotYetPerformed) {
NtStatus = NlpInternalCacheInitialize();
if (!NT_SUCCESS(NtStatus)) {
return;
}
}
if (NlpCacheControl.Entries == 0) {
return;
}
ENTER_CACHE();
NtStatus = NlpReadCacheEntry( DomainName,
UserName,
&Index,
&CacheEntry,
&EntrySize);
if(!NT_SUCCESS( NtStatus) ) {
LEAVE_CACHE();
return ;
}
if( CacheEntry->Revision >= NLP_CACHE_REVISION_NT_5_0 ) {
UNICODE_STRING CachedUser;
CachedUser.Length =
CachedUser.MaximumLength = CacheEntry->UserNameLength;
CachedUser.Buffer = (PWSTR) ((PBYTE) CacheEntry + sizeof(LOGON_CACHE_ENTRY));
NtStatus = NlpMakeSecretPasswordNT5( &CacheEntry->CachePasswords,
&CachedUser,
NtOwfPassword,
LmOwfPassword );
if(NT_SUCCESS(NtStatus)) {
//
// encrypt the entry...
//
NtStatus = NlpEncryptCacheEntry( CacheEntry, EntrySize );
}
if(NT_SUCCESS( NtStatus )) {
//
// now, write the entry out...
//
NtStatus = NlpWriteCacheEntry(Index, CacheEntry, EntrySize);
#ifdef DBG
if(DumpCacheInfo) {
if( NT_SUCCESS( NtStatus ) ) {
DbgPrint("NlpChangeCachePassword: SUCCEED write NT5 version cache entry.\n");
} else {
DbgPrint("NlpChangeCachePassword: FAIL write NT5 version cache entry.\n");
}
}
#endif
}
} else {
NtStatus = NlpOpenSecret( Index );
if (NT_SUCCESS(NtStatus)) {
NtStatus = NlpReadSecret(&CurrentSecret, &OldSecret);
if (NT_SUCCESS(NtStatus)) {
UNICODE_STRING CachedUser;
//
// Grab the various strings from the cache entry.
//
ASSERT( CacheEntry->Revision >= NLP_CACHE_REVISION_NT_1_0B );
CachedUser.Length =
CachedUser.MaximumLength = CacheEntry->UserNameLength;
CachedUser.Buffer = (PWSTR) ((PBYTE) CacheEntry + sizeof(LOGON_CACHE_ENTRY_NT_4_SP4));
NtStatus = NlpMakeSecretPassword( &Passwords,
&CachedUser,
NtOwfPassword,
LmOwfPassword );
if (NT_SUCCESS(NtStatus)) {
NtStatus = NlpWriteSecret(&Passwords, CurrentSecret);
//
// free the buffer allocated to store the passwords
//
FreeToHeap(Passwords.Buffer);
}
//
// free strings returned by NlpReadSecret
//
if (CurrentSecret) {
MIDL_user_free(CurrentSecret);
}
if (OldSecret) {
MIDL_user_free(OldSecret);
}
}
}
}
LEAVE_CACHE();
//
// free structure allocated by NlpReadCacheEntry
//
if( CacheEntry ) {
ZeroMemory( CacheEntry, EntrySize );
FreeToHeap(CacheEntry);
}
return;
}
////////////////////////////////////////////////////////////////////////
// //
// Services Internal to this module //
// //
////////////////////////////////////////////////////////////////////////
NTSTATUS
NlpInternalCacheInitialize(
VOID
)
/*++
Routine Description:
This routine is called to initialize cached logon processing.
This routine will automatically adjust the size of the logon
cache if necessary to accomodate a new user-specified length
(specified in the Winlogon part of the registry).
NOTE: If called too early, this routine won't be able to call
LSA's RPC routines. In this case, initialization is
defered until later.
Arguments:
None.
Return Value:
NTSTATUS
--*/
{
NTSTATUS
NtStatus;
OBJECT_ATTRIBUTES
ObjectAttributes;
// DbgPrint("\n\n\n REMEMBER TO TAKE THIS BREAKPOINT OUT BEFORE CHECKIN.\n\n\n");
// DumpCacheInfo = 1; // Remember to take this out too !!!!!!
// DbgBreakPoint(); // Remember to take this out before checking
#if DBG
if (DumpCacheInfo) {
DbgPrint("NlpCacheInitialize\n");
}
#endif
//
// Upon return from this routine, if logon caching is enabled,
// the following will be true:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -