Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

526 lines
15 KiB

//#----------------------------------------------------------------------------
//
// File: pwdcache.c
//
// Synopsis: SSPI Shared Memory Password Cache related code.
//
// Copyright (C) 1993-1995 Microsoft Corporation. All Rights Reserved.
//
// Authors: LucyC Created 16 Oct 1995
//
//-----------------------------------------------------------------------------
#include <msnssph.h>
//
// Pointer to the shared memory for caching password
//
static PMsnSspCache g_pPwdCache = NULL;
static HANDLE g_hMapFile = NULL;
static HANDLE g_hMutex = NULL;
SECURITY_STATUS
MsnSspEncryptPassword (
LM_OWF_PASSWORD *pLmPassword,
LPSTR pPassword
);
//+---------------------------------------------------------------
//
// Function: GetWorldSecurityAttributes
//
// Synopsis: code is cut and pasted from the Win32 SDK help files
//
// Arguments: void
//
// Returns: static security attributes for Everyone access
//
//----------------------------------------------------------------
LPSECURITY_ATTRIBUTES
GetWorldSecurityAttributes (
VOID
)
{
static SECURITY_ATTRIBUTES SecurityAttrib;
static SECURITY_DESCRIPTOR SecurityDesc;
FillMemory ((char*)&SecurityDesc, 0, sizeof(SECURITY_DESCRIPTOR));
if ( InitializeSecurityDescriptor (&SecurityDesc,
SECURITY_DESCRIPTOR_REVISION) )
{
//
// Add a NULL disc. ACL to the security descriptor.
//
if ( SetSecurityDescriptorDacl( &SecurityDesc,
TRUE, // specifying a disc. ACL
(PACL)NULL,
FALSE)) // not a default disc. ACL
{
SecurityAttrib.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttrib.lpSecurityDescriptor = &SecurityDesc;
SecurityAttrib.bInheritHandle = FALSE;
return &SecurityAttrib;
}
}
return (LPSECURITY_ATTRIBUTES) NULL;
}
//+----------------------------------------------------------------------------
//
// Function: MsnSspInitPwdCache
//
// Synopsis: This function creates the Mutex object for the password cache.
// This must be called before referencing any password cache
// function. BUGBUG?? if the Mutex object can not be created,
// the shared memory password caching capability will be disabled.
//
// Arguments: void.
//
// Returns: void.
//
// History: LucyC Created 16 Oct 1995
//
//-----------------------------------------------------------------------------
VOID
MsnSspInitPwdCache (
VOID
)
{
LPSECURITY_ATTRIBUTES lpSecAttr;
DWORD err;
if (g_hMutex) // If Mutex object is already created, do nothing
return;
lpSecAttr = GetWorldSecurityAttributes ();
if (lpSecAttr == NULL)
return;
g_hMutex = CreateMutex (lpSecAttr, FALSE, MSN_SSP_PWD_MTX_NAME);
if (g_hMutex == (HANDLE) NULL)
{
if (GetLastError () == ERROR_INVALID_HANDLE)
{
SspPrint(( SSP_API,
"MsnSspInitPwdCache: CreateMutex failed: mismatch object type\n"));
}
else
{
SspPrint(( SSP_API,
"MsnSspInitPwdCache: CreateMutex failed: general error\n"));
}
}
//
// Password caching will be disabled if we are unsuccessful in creating
// or opening the g_hMutex handle. BUGBUG: Should we have risked it???
//
}
//+----------------------------------------------------------------------------
//
// Function: MsnSspClosePwdCache
//
// Synopsis: This function unmaps the shared memory and closes the
// File Mapping and Mutex object handle which are opened for
// the password cache.
//
// Arguments: void.
//
// Returns: void.
//
// History: LucyC Created 1 May 1996
//
//-----------------------------------------------------------------------------
VOID
MsnSspClosePwdCache (
VOID
)
{
if (g_pPwdCache)
UnmapViewOfFile (g_pPwdCache);
if (g_hMapFile)
CloseHandle (g_hMapFile);
if (g_hMutex) // If Mutex object is created
CloseHandle (g_hMutex);
}
//+----------------------------------------------------------------------------
//
// Function: MsnSspOpenPwdCache
//
// Synopsis: This function opens the shared memory password cache.
// If bDoCreate is set, and if the shared memory is not yet
// created, this function will create the shared memory for
// password caching capability.
//
// Arguments: bDoCreate - whether to create the shared memory if it is
// not yet created.
//
// Returns: NULL if the password cache can not be opened for any reason.
// Otherwise, pointer to the password cache is returned.
//
// History: LucyC Created 16 Oct 1995
//
//-----------------------------------------------------------------------------
PMsnSspCache
MsnSspOpenPwdCache (
BOOLEAN bDoCreate
)
{
BOOLEAN bJustCreated = FALSE;
//
// Check if the password cache already exists
//
if (!g_hMapFile)
g_hMapFile = OpenFileMapping (FILE_MAP_ALL_ACCESS, FALSE,
MSN_SSP_PWD_CACHE_NAME);
if (!g_hMapFile)
{
if (!bDoCreate)
return NULL;
else
{
//
// The password cache has not been created
//
g_hMapFile = CreateFileMapping (SYSTEM_PAGING_FILE_HANDLE, NULL,
PAGE_READWRITE, 0, sizeof (MsnSspCache),
MSN_SSP_PWD_CACHE_NAME);
}
if (!g_hMapFile)
{
SspPrint(( SSP_API,
"MsnSspOpenPwdCache: CreateFileMapping(%s) failed [%d]\n",
MSN_SSP_PWD_CACHE_NAME, GetLastError()));
return NULL;
}
bJustCreated = TRUE;
}
g_pPwdCache = (PMsnSspCache) MapViewOfFile (g_hMapFile, FILE_MAP_ALL_ACCESS,
0, 0, sizeof (MsnSspCache));
if (!g_pPwdCache)
{
SspPrint(( SSP_API, "MsnSspOpenPwdCache: MapViewOfFile() failed [%d]\n",
GetLastError()));
return NULL;
}
//
// If we just created the shared memory, initialize the memory with NULL
//
if (bJustCreated)
memset (g_pPwdCache, 0, sizeof (MsnSspCache));
return (g_pPwdCache);
}
//+----------------------------------------------------------------------------
//
// Function: MsnSspUpdPwdCache
//
// Synopsis: This function updates the password cache with pUsername and
// pLmPassword.
//
// Arguments: pUsername - points to the user name to be copied to cache.
// pLmPassword - points to the password to be copied to cache.
// (note: this is the encrypted password.)
//
// Returns: TRUE if password cache is updated successfully.
// Otherwise, FALSE is returned.
//
// History: LucyC Created 16 Oct 1995
//
//-----------------------------------------------------------------------------
BOOL
MsnSspUpdPwdCache (
PCHAR pUsername,
LM_OWF_PASSWORD *pLmPassword
)
{
DWORD status;
//
// BUGBUG: If there's no way of synchronizing cache access, we'd rather
// disable password caching capability. Should we have risked it???
//
if (g_hMutex == (HANDLE) NULL)
{
SspPrint(( SSP_API,
"MsnSspUpdPwdCache: No synchronization object - return to caller\n"));
return FALSE;
}
//
// Grab ownership of Mutex. BUGBUG: we shouldn't be blocking forever
// here. However, if we not grab the mutex within the timeout, what do
// we do???
//
status = WaitForSingleObject (g_hMutex, INFINITE);
if (status == WAIT_FAILED)
{
SspPrint(( SSP_API,
"MsnSspUpdPwdCache: WaitForSingleObject failed [%d]\n",
GetLastError()));
return FALSE;
}
//
// Map the shared memory into our address space if not already mapped
// If the shared memory has not been created, this will also create it.
// So we must use synchronization object to prevent anybody from grabbing
// the newly created shared memory before the memory is even set with
// user name and password.
//
if (!g_pPwdCache)
{
if (!MsnSspOpenPwdCache (TRUE)) // Create it if not yet existed
{
ReleaseMutex (g_hMutex);
return FALSE;
}
}
if (strcmp (g_pPwdCache->Username, pUsername) != 0)
strcpy (g_pPwdCache->Username, pUsername);
if (memcmp (&g_pPwdCache->Password, pLmPassword,
sizeof(LM_OWF_PASSWORD)) != 0)
{
memcpy (&g_pPwdCache->Password, pLmPassword,
sizeof(LM_OWF_PASSWORD));
}
ReleaseMutex (g_hMutex);
return TRUE;
}
//+----------------------------------------------------------------------------
//
// Function: MsnSspGetPwdFromCache
//
// Synopsis: This function retrieves the user name/password from the
// the password cache and saves them in the user credential
// handle.
//
// Arguments: pCred - the user credential handle.
//
// Returns: TRUE if user name/password is successfully copied to the
// user credential from the password cache.
// Otherwise, FALSE is returned.
//
// History: LucyC Created 16 Oct 1995
//
//-----------------------------------------------------------------------------
BOOL
MsnSspGetPwdFromCache (
PSSP_CREDENTIAL pCred
)
{
DWORD status;
char szUsername[AC_MAX_LOGIN_NAME_LENGTH+1];
LM_OWF_PASSWORD lmPassword;
BOOLEAN bPwdWasNull = FALSE;
//
// BUGBUG: If there's no way of synchronizing cache access, we'd rather
// disable password caching capability. Should we have risked it???
//
if (g_hMutex == (HANDLE) NULL)
{
SspPrint(( SSP_API,
"MsnSspUpdPwdCache: No synchronization object - return to caller\n"));
return FALSE;
}
//
// Map the shared memory into our address space if not already mapped.
// If the shared memory has not been created, just return failure to caller
//
if (!g_pPwdCache)
{
if (!MsnSspOpenPwdCache (FALSE)) // Don't create if not yet existed
return FALSE;
}
//
// Grab ownership of Mutex. BUGBUG: we shouldn't be blocking forever
// here. However, if we not grab the mutex within the timeout, what do
// we do???
//
status = WaitForSingleObject (g_hMutex, INFINITE);
if (status == WAIT_FAILED)
{
SspPrint(( SSP_API,
"MsnSspUpdPwdCache: WaitForSingleObject failed [%d]\n",
GetLastError()));
return FALSE;
}
//
// If no user name and password are cached, return to caller
//
if (g_pPwdCache->Username[0] == '\0')
{
ReleaseMutex (g_hMutex);
return FALSE;
}
strcpy (szUsername, g_pPwdCache->Username);
memcpy (&lmPassword, &g_pPwdCache->Password, sizeof(LM_OWF_PASSWORD));
ReleaseMutex (g_hMutex);
if (pCred->Password == NULL)
{
pCred->Password = (PLM_OWF_PASSWORD)SspAlloc (sizeof (LM_OWF_PASSWORD));
if (pCred->Password == NULL)
return FALSE;
bPwdWasNull = TRUE;
}
if (pCred->Username != NULL)
SspFree (pCred->Username);
pCred->Username = (char *)SspAlloc (strlen (szUsername) + 1);
if (pCred->Username == NULL)
{
//
// If password was NULL originally, we want to restore it as NULL here
//
if (bPwdWasNull)
{
SspFree (pCred->Password);
pCred->Password = NULL;
}
return FALSE;
}
strcpy (pCred->Username, szUsername);
memcpy (pCred->Password, &lmPassword, sizeof(LM_OWF_PASSWORD));
return TRUE;
}
/*-----------------------------------------------------------------------------
**
** Function: SetMSNAccountInfo
**
** Synopsis: This function sets the specified user name and password in the
** SSPI's shared memory password cache. If the user name and
** password in the cache are to be erased/removed, both pUsername
** and pPassword are explicitly set to NULL by the caller.
**
** Arguments: pUsername - pointer to the user name to be cached
** pPassword - pointer to the user password to be cached
**
** Returns: TRUE if user name and password are cached successfully.
** Otherwise, FALSE is returned if any error is encountered;
** this includes invalid user name and password.
**
** History: LucyC Created 20 Oct. 1995
**
**---------------------------------------------------------------------------*/
MSNSSP_DLL BOOL SEC_ENTRY
SetMSNAccountInfo (
LPSTR pUsername,
LPSTR pPassword
)
{
DWORD status;
LM_OWF_PASSWORD LmOwfPassword;
BOOLEAN bErase = FALSE;
//
// BUGBUG: If there's no way of synchronizing cache access, we'd rather
// disable password caching capability. Should we have risked it???
//
if (g_hMutex == (HANDLE) NULL)
{
SspPrint(( SSP_API,
"SetMSNAccountInfo: No synchronization object - return to caller\n"));
return FALSE;
}
if ((pUsername == NULL || pUsername[0] == '\0') && pPassword == NULL)
{
bErase = TRUE;
}
else if (pPassword)
{
//
// Encrypt the password
//
if (MsnSspEncryptPassword (&LmOwfPassword, pPassword) != SEC_E_OK)
{
SspPrint(( SSP_API,
"SetMSNAccountInfo: Password exceeded maximum length\n"));
return FALSE;
}
}
//
// Grab ownership of Mutex. BUGBUG: we shouldn't be blocking forever
// here. However, if we not grab the mutex within the timeout, what do
// we do???
//
status = WaitForSingleObject (g_hMutex, INFINITE);
if (status == WAIT_FAILED)
{
SspPrint(( SSP_API,
"SetMSNAccountInfo: WaitForSingleObject failed [%d]\n",
GetLastError()));
return FALSE;
}
if (bErase) // remove the password cached
{
// Password cache exists, erase user name/password cached
//
if (g_pPwdCache)
memset (g_pPwdCache, 0, sizeof (MsnSspCache));
}
else
{
//
// Map the shared memory into our address space if not already mapped
// If the shared memory has not been created, this will also create it.
// So we must use synchronization object to prevent anybody from
// grabbing the newly created shared memory before the memory is even
// set with user name and password.
//
if (!g_pPwdCache)
{
if (!MsnSspOpenPwdCache (TRUE)) // Create it if not yet existed
{
ReleaseMutex (g_hMutex);
return FALSE;
}
}
if (pUsername && pUsername[0] != '\0')
strcpy (g_pPwdCache->Username, pUsername);
if (pPassword)
memcpy (&g_pPwdCache->Password, &LmOwfPassword,
sizeof(LM_OWF_PASSWORD));
}
ReleaseMutex (g_hMutex);
return TRUE;
}