mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
388 lines
7.5 KiB
388 lines
7.5 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
This program is released into the public domain for any purpose.
|
|
|
|
|
|
Module Name:
|
|
|
|
cache.c
|
|
|
|
Abstract:
|
|
|
|
This module implements a simple user cache. The cached users are kept
|
|
in an LRU sorted list. If there will be a large number of simultaneous
|
|
users, then a sorted array would be more appropriate.
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <httpfilt.h>
|
|
#include <authfilt.h>
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
//
|
|
// The maximum number of users we will cache. If there will be a large number
|
|
// of simultaneous users, bump this value
|
|
//
|
|
|
|
#define MAX_CACHED_USERS 100
|
|
|
|
//
|
|
// The position after which we'll move a cache entry to the front of the list
|
|
//
|
|
|
|
#define LIST_REORDER_THRESHOLD 6
|
|
|
|
//
|
|
// Cached user structure
|
|
//
|
|
|
|
typedef struct _USER_INFO
|
|
{
|
|
LIST_ENTRY ListEntry; // Double linked list entry
|
|
|
|
CHAR achUserName[SF_MAX_USERNAME]; // External username and password
|
|
CHAR achPassword[SF_MAX_PASSWORD];
|
|
|
|
CHAR achNTUserName[SF_MAX_USERNAME]; // NT account and password to map user to
|
|
CHAR achNTUserPassword[SF_MAX_PASSWORD];
|
|
|
|
} USER_INFO, *PUSER_INFO;
|
|
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
//
|
|
// Circular double linked list of cached users
|
|
//
|
|
|
|
LIST_ENTRY CacheListHead;
|
|
|
|
//
|
|
// Critical section protects cache list
|
|
//
|
|
|
|
CRITICAL_SECTION csCacheLock;
|
|
|
|
//
|
|
// Indicates whether we are initialized
|
|
//
|
|
|
|
BOOL fCacheInitialized = FALSE;
|
|
|
|
//
|
|
// Number of items in the cache
|
|
//
|
|
|
|
DWORD cCacheItems = 0;
|
|
|
|
|
|
BOOL
|
|
InitializeCache(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes the cache module
|
|
|
|
Return Value:
|
|
|
|
TRUE if initialized successfully, FALSE on error
|
|
|
|
--*/
|
|
{
|
|
if ( fCacheInitialized )
|
|
return TRUE;
|
|
|
|
InitializeCriticalSection( &csCacheLock );
|
|
CacheListHead.Blink = CacheListHead.Flink = &CacheListHead;
|
|
|
|
fCacheInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
LookupUserInCache(
|
|
CHAR * pszUserName,
|
|
BOOL * pfFound,
|
|
CHAR * pszPassword,
|
|
CHAR * pszNTUser,
|
|
CHAR * pszNTUserPassword
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Checks to see if a user is in the cache and returns the user properties
|
|
if found
|
|
|
|
Arguments:
|
|
|
|
pszUserName - Case insensitive username to find
|
|
pfFound - Set to TRUE if the specified user was found
|
|
pszPassword - Receives password for specified if found
|
|
pszNTUser - Receives the NT Username to map this user to
|
|
pszNTUserPassword - Receives the NT Password for pszNTUser
|
|
|
|
Note: pszPassword and pszNTUserPassword must be at least SF_MAX_PASSWORD
|
|
characters. pszNTUser must be at least SF_MAX_USERNAME characters.
|
|
|
|
Return Value:
|
|
|
|
TRUE if no errors occurred.
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY * pEntry;
|
|
USER_INFO * pUser;
|
|
DWORD cPosition = 0;
|
|
|
|
//
|
|
// Search the cache for the specified user
|
|
//
|
|
|
|
EnterCriticalSection( &csCacheLock );
|
|
|
|
for ( pEntry = CacheListHead.Flink;
|
|
pEntry != &CacheListHead;
|
|
pEntry = pEntry->Flink )
|
|
{
|
|
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
|
|
|
|
if ( !stricmp( pszUserName, pUser->achUserName ))
|
|
{
|
|
goto Found;
|
|
}
|
|
|
|
cPosition++;
|
|
}
|
|
|
|
LeaveCriticalSection( &csCacheLock );
|
|
|
|
//
|
|
// Not Found
|
|
//
|
|
|
|
*pfFound = FALSE;
|
|
return TRUE;
|
|
|
|
Found:
|
|
|
|
//
|
|
// Copy out the user properties
|
|
//
|
|
|
|
strcpy( pszPassword, pUser->achPassword );
|
|
strcpy( pszNTUser, pUser->achNTUserName );
|
|
strcpy( pszNTUserPassword, pUser->achNTUserPassword );
|
|
|
|
//
|
|
// Move this user entry to the front of the list as we're probably going
|
|
// to get subsequent requests for this user. Note we only move it
|
|
// if it's not already near the front
|
|
//
|
|
|
|
if ( cPosition > LIST_REORDER_THRESHOLD )
|
|
{
|
|
//
|
|
// Remove from the old position...
|
|
//
|
|
|
|
pEntry->Blink->Flink = pEntry->Flink;
|
|
pEntry->Flink->Blink = pEntry->Blink;
|
|
|
|
//
|
|
// ...and insert it at the beginning of the list
|
|
//
|
|
|
|
pEntry->Blink = &CacheListHead;
|
|
pEntry->Flink = CacheListHead.Flink;
|
|
|
|
CacheListHead.Flink->Blink = pEntry;
|
|
CacheListHead.Flink = pEntry;
|
|
}
|
|
|
|
LeaveCriticalSection( &csCacheLock );
|
|
|
|
*pfFound = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
AddUserToCache(
|
|
CHAR * pszUserName,
|
|
CHAR * pszPassword,
|
|
CHAR * pszNTUser,
|
|
CHAR * pszNTUserPassword
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds the specified user to the cache
|
|
|
|
Arguments:
|
|
|
|
pszUserName - Username to add
|
|
pszPassword - Contains the external password for this user
|
|
pszNTUser - Contains the NT user name to use for this user
|
|
pszNTUserPassword - Contains the password for NTUser
|
|
|
|
Return Value:
|
|
|
|
TRUE if no errors occurred.
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY * pEntry;
|
|
USER_INFO * pUser;
|
|
|
|
//
|
|
// Check our parameters before adding them to the cache
|
|
//
|
|
|
|
if ( strlen( pszUserName ) > SF_MAX_USERNAME ||
|
|
strlen( pszPassword ) > SF_MAX_PASSWORD ||
|
|
strlen( pszNTUser ) > SF_MAX_USERNAME ||
|
|
strlen( pszNTUserPassword ) > SF_MAX_PASSWORD )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Search the cache for the specified user to make sure there are no
|
|
// duplicates
|
|
//
|
|
|
|
EnterCriticalSection( &csCacheLock );
|
|
|
|
for ( pEntry = CacheListHead.Flink;
|
|
pEntry != &CacheListHead;
|
|
pEntry = pEntry->Flink )
|
|
{
|
|
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
|
|
|
|
if ( !stricmp( pszUserName, pUser->achUserName ))
|
|
{
|
|
goto Found;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate a new cache item and put it at the head of the list
|
|
//
|
|
|
|
pUser = (USER_INFO *) LocalAlloc( LPTR, sizeof( USER_INFO ));
|
|
|
|
if ( !pUser )
|
|
{
|
|
LeaveCriticalSection( &csCacheLock );
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return FALSE;
|
|
}
|
|
|
|
pUser->ListEntry.Flink = CacheListHead.Flink;
|
|
pUser->ListEntry.Blink = &CacheListHead;
|
|
|
|
CacheListHead.Flink = &pUser->ListEntry;
|
|
|
|
Found:
|
|
|
|
//
|
|
// Set the various fields
|
|
//
|
|
|
|
strcpy( pUser->achUserName, pszUserName );
|
|
strcpy( pUser->achPassword, pszPassword );
|
|
strcpy( pUser->achNTUserName, pszNTUser );
|
|
strcpy( pUser->achNTUserPassword, pszNTUserPassword );
|
|
|
|
cCacheItems++;
|
|
|
|
//
|
|
// If there are too many cached users, remove the least recently
|
|
// used one now
|
|
//
|
|
|
|
if ( cCacheItems > MAX_CACHED_USERS )
|
|
{
|
|
pEntry = CacheListHead.Blink;
|
|
|
|
pEntry->Blink->Flink = &CacheListHead;
|
|
CacheListHead.Blink = pEntry->Blink;
|
|
|
|
LocalFree( CONTAINING_RECORD( pEntry, USER_INFO, ListEntry ));
|
|
|
|
cCacheItems--;
|
|
}
|
|
|
|
LeaveCriticalSection( &csCacheLock );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
TerminateCache(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Terminates the cache module and frees any allocated memory
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY * pEntry;
|
|
LIST_ENTRY * pEntryNext;
|
|
USER_INFO * pUser;
|
|
|
|
if ( !fCacheInitialized )
|
|
return;
|
|
|
|
EnterCriticalSection( &csCacheLock );
|
|
|
|
//
|
|
// Free all of the cache entries
|
|
//
|
|
|
|
for ( pEntry = CacheListHead.Flink;
|
|
pEntry != &CacheListHead;
|
|
pEntry = pEntryNext )
|
|
|
|
{
|
|
pUser = CONTAINING_RECORD( pEntry, USER_INFO, ListEntry );
|
|
|
|
pEntryNext = pEntry->Flink;
|
|
|
|
//
|
|
// Remove this entry from the list and free it
|
|
//
|
|
|
|
pEntry->Blink->Flink = pEntry->Flink;
|
|
pEntry->Flink->Blink = pEntry->Blink;
|
|
|
|
LocalFree( pUser );
|
|
}
|
|
|
|
cCacheItems = 0;
|
|
LeaveCriticalSection( &csCacheLock );
|
|
|
|
DeleteCriticalSection( &csCacheLock );
|
|
|
|
fCacheInitialized = FALSE;
|
|
}
|