2784 lines
78 KiB
C++
2784 lines
78 KiB
C++
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: userinfo.cpp
|
|
//
|
|
// Module: CMDIAL32.DLL
|
|
//
|
|
// Synopsis: This module contains the code that handles getting/saving user info.
|
|
//
|
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
//
|
|
// Author: henryt created 02/??/98
|
|
// quintinb created Header 08/16/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
#include "cmmaster.h"
|
|
#include "cmuufns.h"
|
|
|
|
#include "pwd_str.h"
|
|
#include "userinfo_str.h"
|
|
#include "conact_str.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// define's
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// CM_MAX_PWD - Maximum possible size of password dataencrypted or otherwise.
|
|
// Includes inbound buffer size + room for encryption expansion.
|
|
//
|
|
|
|
const DWORD CM_MAX_PWD = PWLEN * 3; // 2.73 would be enough
|
|
|
|
//
|
|
// Define this if you want to test userinfo upgrade! You should also delete the key
|
|
// HKEY_CURRENT_USER\Software\Microsoft\Connection Manager\UserInfo\<Service Name>
|
|
//
|
|
//#define TEST_USERINFO_UPGRADE 1
|
|
|
|
#define CACHE_KEY_LEN 80 // Don't change unless you've read every comment regarding it
|
|
|
|
//
|
|
// Suffix for CacheEntry name used on Legacy and W9x. Note: the space is not a typo
|
|
|
|
const TCHAR* const c_pszCacheEntryNameSuffix = TEXT(" (Connection Manager)");
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// typedef's
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// func prototypes
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////
|
|
|
|
|
|
|
|
BOOL WriteDataToReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
DWORD dwType,
|
|
CONST BYTE *lpData,
|
|
DWORD cbData,
|
|
BOOL fAllUser);
|
|
|
|
|
|
BOOL ReadDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
LPDWORD lpdwType,
|
|
BYTE *lpData,
|
|
LPDWORD lpcbData,
|
|
BOOL fAllUser);
|
|
|
|
LPBYTE GetDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
DWORD dwType,
|
|
DWORD dwSize,
|
|
BOOL fAllUser);
|
|
|
|
BOOL DeleteDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
BOOL fAllUser);
|
|
|
|
BOOL DeleteUserInfoFromReg(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry);
|
|
|
|
BOOL ReadPasswordFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
LPTSTR *ppszPassword);
|
|
|
|
LPCTSTR TranslateUserDataID(
|
|
UINT uiDataID);
|
|
|
|
BOOL ReadUserInfoFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID *ppvData);
|
|
|
|
BOOL DeleteUserInfoFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry);
|
|
|
|
DWORD RasSetCredsWrapper(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPhoneBook,
|
|
DWORD dwMask,
|
|
LPCTSTR pszData);
|
|
|
|
int WriteUserInfoToRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiDataID,
|
|
PVOID pvData);
|
|
|
|
int DeleteUserInfoFromRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry);
|
|
|
|
DWORD RasGetCredsWrapper(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPhoneBook,
|
|
DWORD dwMask,
|
|
PVOID *ppvData);
|
|
|
|
BOOL ReadUserInfoFromRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID *ppvData);
|
|
|
|
///////////////
|
|
|
|
BOOL ReadStringFromCache(
|
|
ArgsStruct *pArgs,
|
|
LPTSTR pszEntryName,
|
|
LPTSTR *ppszStr
|
|
);
|
|
|
|
BOOL DeleteStringFromCache(
|
|
ArgsStruct *pArgs,
|
|
LPTSTR pszEntryName
|
|
);
|
|
|
|
LPTSTR GetLegacyKeyName(ArgsStruct *pArgs);
|
|
|
|
LPTSTR EncryptPassword(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPassword,
|
|
LPDWORD lpdwBufSize,
|
|
LPDWORD lpdwCryptType,
|
|
BOOL fReg,
|
|
LPSTR pszSubKey);
|
|
|
|
LPBYTE DecryptPassword(
|
|
ArgsStruct *pArgs,
|
|
LPBYTE pszEncryptedData,
|
|
DWORD dwEncryptionType,
|
|
DWORD dwEncryptedBytes,
|
|
BOOL /*fReg*/,
|
|
LPSTR pszSubKey);
|
|
|
|
LPTSTR BuildUserInfoSubKey(
|
|
LPCTSTR pszServiceKey,
|
|
BOOL fAllUser);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Implementation
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef TEST_USERINFO_UPGRADE
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: WriteStringToCache
|
|
//
|
|
// Synopsis: Write a null terminated password string to cache.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// pszEntryName name to identify the cache entry
|
|
// pszStr the string
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WriteStringToCache(
|
|
ArgsStruct *pArgs,
|
|
LPTSTR pszEntryName,
|
|
LPTSTR pszStr)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(pszEntryName && *pszEntryName);
|
|
MYDBGASSERT(pszStr && *pszStr);
|
|
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
|
|
//
|
|
// In the legacy case, we use mpr.dll for caching user data on W9x.
|
|
// On NT we use the Local Security Authority (LSA)
|
|
//
|
|
|
|
if (OS_NT)
|
|
{
|
|
if (InitLsa(pArgs))
|
|
{
|
|
if (!(*ppszStr = (LPTSTR)CmMalloc(dwBufSize)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dwRes = LSA_WriteString(pArgs, pszEntryName, pszStr);
|
|
DeInitLsa(pArgs);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// for Windows95
|
|
//
|
|
HINSTANCE hInst = NULL;
|
|
WORD (WINAPI *pfnFunc)(LPSTR,WORD,LPSTR,WORD,BYTE,UINT) = NULL;
|
|
|
|
//
|
|
// Load MPR for system password cache support
|
|
//
|
|
|
|
MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
|
|
|
|
if (hInst)
|
|
{
|
|
//
|
|
// Get function ptr for WNetCachePassword API and cache the password
|
|
//
|
|
|
|
MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,LPSTR,WORD,BYTE,UINT))
|
|
GetProcAddress(hInst, "WNetCachePassword"));
|
|
|
|
if (pfnFunc)
|
|
{
|
|
//
|
|
// Convert the EntryName and Password Strings to Ansi
|
|
//
|
|
|
|
LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
|
|
LPSTR pszAnsiStr = WzToSzWithAlloc(pszStr);
|
|
|
|
if (pszAnsiStr && pszAnsiEntryName)
|
|
{
|
|
//
|
|
// Store the password
|
|
//
|
|
|
|
dwRes = pfnFunc(pszAnsiEntryName,
|
|
(WORD)lstrlenA(pszAnsiEntryName),
|
|
pszAnsiStr,
|
|
(WORD)lstrlenA(pszAnsiStr),
|
|
CACHE_KEY_LEN,
|
|
0);
|
|
}
|
|
else
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
CmFree(pszAnsiStr);
|
|
CmFree(pszAnsiEntryName);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
|
|
FreeLibrary(hInst);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (dwRes)
|
|
{
|
|
CMTRACE1(TEXT("WriteStringToCache() failed, err=%u."), dwRes);
|
|
}
|
|
#endif
|
|
|
|
return (ERROR_SUCCESS == dwRes);
|
|
}
|
|
|
|
#endif //TEST_USERINFO_UPGRADE
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: BuildUserInfoSubKey
|
|
//
|
|
// Synopsis: Constructs the appropriate subkey for UserInfo based on the service
|
|
// name key and the user mode of the profile.
|
|
//
|
|
// Arguments: LPCTSTR pszServiceKey - The service name key
|
|
// BOOL fAllUser - Flag indicating that profile is All-User
|
|
//
|
|
// Returns: LPTSTR - Ptr to allocated buffer containing subkey or NULL on failure.
|
|
//
|
|
// History: nickball Created 8/14/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPTSTR BuildUserInfoSubKey(LPCTSTR pszServiceKey, BOOL fAllUser)
|
|
{
|
|
MYDBGASSERT(pszServiceKey);
|
|
|
|
if (NULL == pszServiceKey)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Use the appropriate base key
|
|
//
|
|
|
|
LPTSTR pszSubKey = NULL;
|
|
|
|
if (fAllUser)
|
|
{
|
|
pszSubKey = CmStrCpyAlloc(c_pszRegCmUserInfo);
|
|
}
|
|
else
|
|
{
|
|
pszSubKey = CmStrCpyAlloc(c_pszRegCmSingleUserInfo);
|
|
}
|
|
|
|
MYDBGASSERT(pszSubKey);
|
|
|
|
//
|
|
// Append profile service name
|
|
//
|
|
|
|
if (pszSubKey && *pszSubKey)
|
|
{
|
|
pszSubKey = CmStrCatAlloc(&pszSubKey, pszServiceKey);
|
|
MYDBGASSERT(pszSubKey);
|
|
|
|
return pszSubKey;
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: BuildICSDataInfoSubKey
|
|
//
|
|
// Synopsis: Constructs the appropriate subkey for ICS UserInfo based on the service
|
|
// name key.
|
|
//
|
|
// Arguments: LPCTSTR pszServiceKey - The service name key
|
|
//
|
|
// Returns: LPTSTR - Ptr to allocated buffer containing subkey or NULL on failure.
|
|
//
|
|
// History: 03/30/2001 tomkel Created
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPTSTR BuildICSDataInfoSubKey(LPCTSTR pszServiceKey)
|
|
{
|
|
MYDBGASSERT(pszServiceKey);
|
|
|
|
if (NULL == pszServiceKey)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Use the appropriate base key
|
|
//
|
|
|
|
LPTSTR pszSubKey = NULL;
|
|
|
|
pszSubKey = CmStrCpyAlloc(c_pszRegCmRoot);
|
|
|
|
MYDBGASSERT(pszSubKey);
|
|
|
|
//
|
|
// Append profile service name
|
|
//
|
|
|
|
if (pszSubKey && *pszSubKey)
|
|
{
|
|
pszSubKey = CmStrCatAlloc(&pszSubKey, pszServiceKey);
|
|
|
|
MYDBGASSERT(pszSubKey);
|
|
|
|
if (pszSubKey)
|
|
{
|
|
CmStrCatAlloc(&pszSubKey, TEXT("\\"));
|
|
if (pszSubKey)
|
|
{
|
|
CmStrCatAlloc(&pszSubKey, c_pszCmRegKeyICSDataKey);
|
|
}
|
|
}
|
|
|
|
return pszSubKey;
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: dwGetWNetCachedPassword
|
|
//
|
|
// Synopsis: Wrapper to encapsulate linking to MPR.DLL and calling GetWNetCac
|
|
// hedPassword.
|
|
//
|
|
// Arguments: LPSTR pszEntryName - The names of the key used to identify the password.
|
|
// LPSTR* ppszStr - The buffer to receive the retrieved password.
|
|
// WORD* pwSizeOfStr - The size of the input buffer. Also receives
|
|
// of the # of chars retrieved.
|
|
//
|
|
// Returns: DWORD - Windows error code.
|
|
//
|
|
// History: nickball Created Header 6/17/99
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
DWORD dwGetWNetCachedPassword(LPSTR pszEntryName, LPSTR* ppszStr, WORD* pwSizeOfStr)
|
|
{
|
|
MYDBGASSERT(OS_W9X);
|
|
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
WORD (WINAPI *pfnFunc)(LPSTR,WORD,LPSTR,LPWORD,BYTE) = NULL;
|
|
HINSTANCE hInst = NULL;
|
|
|
|
//
|
|
// Load MPR for system password cache support
|
|
//
|
|
|
|
MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
|
|
|
|
if (hInst)
|
|
{
|
|
//
|
|
// Get function ptr for WNetGetCachedPassword API and retrieve the string
|
|
//
|
|
|
|
MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,LPSTR,LPWORD,BYTE))
|
|
GetProcAddress(hInst, "WNetGetCachedPassword"));
|
|
|
|
//
|
|
// Read the cache data
|
|
//
|
|
|
|
if (pfnFunc)
|
|
{
|
|
//
|
|
// NOTE: Final param must be CACHE_KEY_LEN (80), no docs to indicate
|
|
// exact usage of API but retrieval is tied to the value used when
|
|
// storing the pwd. Thus we hard code to CACHE_KEY_LEN because this
|
|
// is the value that was used by the original version that stored
|
|
// the password in the 9X cache. The receiving buffer size is
|
|
// retained at 256 to minimize delta from latest shipping version.
|
|
//
|
|
// NT# 355459 - nickball - 6/17/99
|
|
//
|
|
|
|
dwRes = pfnFunc(pszEntryName, (WORD)lstrlenA(pszEntryName),
|
|
*ppszStr, pwSizeOfStr, CACHE_KEY_LEN);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
|
|
if (NULL != hInst)
|
|
{
|
|
FreeLibrary(hInst);
|
|
}
|
|
|
|
return (dwRes);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadStringFromCache
|
|
//
|
|
// Synopsis: Read a null terminated string from cache.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// pszEntryName name to identify the cache entry
|
|
// ppszStr ptr to the ptr of the buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL ReadStringFromCache(
|
|
ArgsStruct *pArgs,
|
|
LPTSTR pszEntryName,
|
|
LPTSTR *ppszStr
|
|
)
|
|
{
|
|
DWORD dwRes = ERROR_SUCCESS;
|
|
|
|
//
|
|
// Alloc buffer - the buffer is uuencoded. See UserInfoToString().
|
|
//
|
|
|
|
WORD wBufSize = 256; // arbitrary, we used to use 80 on W95
|
|
|
|
//
|
|
// On NT, we use the Local Security Authority (LSA) services for reading
|
|
// the string in the legacy case. On Win9x, we uses mpr.dll.
|
|
// Note: wBufSize is used as an in\out param, can be modified below.
|
|
//
|
|
|
|
if (OS_NT)
|
|
{
|
|
if (InitLsa(pArgs))
|
|
{
|
|
if (!(*ppszStr = (LPTSTR)CmMalloc(wBufSize)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
dwRes = LSA_ReadString(pArgs, pszEntryName, *ppszStr, wBufSize);
|
|
DeInitLsa(pArgs);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// for Windows95
|
|
//
|
|
|
|
LPSTR pszAnsiStr = (LPSTR)CmMalloc(wBufSize);
|
|
LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
|
|
|
|
if (pszAnsiStr && pszAnsiEntryName)
|
|
{
|
|
dwRes = dwGetWNetCachedPassword(pszAnsiEntryName, &pszAnsiStr, &wBufSize);
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
*ppszStr = SzToWzWithAlloc(pszAnsiStr);
|
|
if (NULL == *ppszStr)
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
CmFree (pszAnsiStr);
|
|
CmFree (pszAnsiEntryName);
|
|
}
|
|
|
|
if (dwRes)
|
|
{
|
|
CmFree(*ppszStr);
|
|
*ppszStr = NULL;
|
|
CMTRACE1(TEXT("ReadStringFromCache() failed, err=%u."), dwRes);
|
|
}
|
|
|
|
return (ERROR_SUCCESS == dwRes);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteStringFromCache
|
|
//
|
|
// Synopsis: Delete the string from cache.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// pszEntryName name to identify the cache entry
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL DeleteStringFromCache(
|
|
ArgsStruct *pArgs,
|
|
LPTSTR pszEntryName
|
|
)
|
|
{
|
|
DWORD dwRes;
|
|
|
|
//
|
|
// on NT, we use the Local Security Authority (LSA) services for storing
|
|
// the string. On Win95, we use mpr.dll.
|
|
//
|
|
if (OS_NT)
|
|
{
|
|
if (InitLsa(pArgs))
|
|
{
|
|
dwRes = LSA_WriteString(pArgs, pszEntryName, NULL);
|
|
DeInitLsa(pArgs);
|
|
}
|
|
else
|
|
{
|
|
dwRes = GetLastError();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// for Windows95
|
|
//
|
|
HINSTANCE hInst = NULL;
|
|
WORD (WINAPI *pfnFunc)(LPSTR,WORD,BYTE) = NULL;
|
|
|
|
// Load MPR for system password cache support
|
|
|
|
MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
|
|
|
|
// Get function ptr for WNetRemoveCachedPassword API and remove the string
|
|
|
|
if (!hInst)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,BYTE))
|
|
GetProcAddress(hInst, "WNetRemoveCachedPassword"));
|
|
|
|
if (!pfnFunc)
|
|
{
|
|
FreeLibrary(hInst);
|
|
return FALSE;
|
|
}
|
|
|
|
LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
|
|
|
|
if (pszAnsiEntryName)
|
|
{
|
|
dwRes = pfnFunc(pszAnsiEntryName, (WORD)lstrlenA(pszAnsiEntryName), CACHE_KEY_LEN);
|
|
}
|
|
else
|
|
{
|
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
CmFree (pszAnsiEntryName);
|
|
|
|
FreeLibrary(hInst);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (dwRes)
|
|
{
|
|
CMTRACE1(TEXT("DeleteStringFromCache() LSA_WriteString/WNetRemoveCachedPassword() failed, err=%u."), dwRes);
|
|
}
|
|
#endif
|
|
|
|
return (ERROR_SUCCESS == dwRes);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RasSetCredsWrapper
|
|
//
|
|
// Synopsis: Wrapper to call RasSetCredential. This function stores the
|
|
// given string in the appropriate field of a RASCREDENTIALS struct
|
|
// (based on the value in dwMask) and calls RasSetCredentials.
|
|
//
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// pszPhoneBook Full path to the phonebook file, or NULL for
|
|
// the default all user pbk
|
|
// dwMask dwMask value to set in the RASCREDENTIALS
|
|
// struct. Currently must be one of RASCM_UserName,
|
|
// RASCM_Domain, or RASCM_Password.
|
|
// pszData string data to set
|
|
//
|
|
// Returns: DWORD ERROR_SUCCESS if successful, a windows error code otherwise
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD RasSetCredsWrapper(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPhoneBook,
|
|
DWORD dwMask,
|
|
LPCTSTR pszData
|
|
)
|
|
{
|
|
DWORD dwRet = ERROR_INVALID_PARAMETER;
|
|
BOOL fSavePassword = TRUE;
|
|
|
|
MYDBGASSERT(pArgs && pArgs->rlsRasLink.pfnSetCredentials);
|
|
MYDBGASSERT(pszData);
|
|
MYDBGASSERT((RASCM_UserName == dwMask) || (RASCM_Domain == dwMask) || (RASCM_Password == dwMask));
|
|
|
|
if (pArgs && pszData && pArgs->rlsRasLink.pfnSetCredentials)
|
|
{
|
|
LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
|
|
|
|
if (pszConnectoid)
|
|
{
|
|
RASCREDENTIALS RasCredentials = {0};
|
|
RasCredentials.dwSize = sizeof(RasCredentials);
|
|
|
|
if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
|
|
{
|
|
RasCredentials.dwMask = dwMask | RASCM_DefaultCreds;
|
|
}
|
|
else
|
|
{
|
|
RasCredentials.dwMask = dwMask;
|
|
}
|
|
|
|
BOOL bClearPassword = FALSE;
|
|
|
|
if (RASCM_UserName == dwMask)
|
|
{
|
|
lstrcpyU(RasCredentials.szUserName, pszData);
|
|
}
|
|
else if (RASCM_Domain == dwMask)
|
|
{
|
|
lstrcpyU(RasCredentials.szDomain, pszData);
|
|
}
|
|
else if (RASCM_Password == dwMask)
|
|
{
|
|
if (0 == lstrcmpU(c_pszSavedPasswordToken, pszData))
|
|
{
|
|
//
|
|
// We have 16 *'s. This password is from the RAS cred store,
|
|
// so we don't want to save the 16 *'s
|
|
//
|
|
fSavePassword = FALSE;
|
|
}
|
|
else
|
|
{
|
|
lstrcpyU(RasCredentials.szPassword, pszData);
|
|
bClearPassword = (TEXT('\0') == pszData[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CmFree(pszConnectoid);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (fSavePassword)
|
|
{
|
|
dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
|
|
|
|
if (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRet)
|
|
{
|
|
//
|
|
// Then the phonebook entry doesn't exist yet, lets create it.
|
|
//
|
|
LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
|
|
|
|
if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
|
|
{
|
|
pRasEntry->dwSize = sizeof(RASENTRY);
|
|
dwRet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
|
|
|
|
//
|
|
// Lets try to set the credentials one more time ...
|
|
//
|
|
if (ERROR_SUCCESS == dwRet)
|
|
{
|
|
dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
|
|
}
|
|
|
|
CmFree(pRasEntry);
|
|
}
|
|
}
|
|
}
|
|
CmWipePassword(RasCredentials.szPassword);
|
|
CmFree(pszConnectoid);
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: WriteUserInfoToRas
|
|
//
|
|
// Synopsis: Write a userinfo data to ras credential storage
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiDataID the resource ID associated with the data
|
|
// pvData userinfo data
|
|
//
|
|
// Returns: int TRUE = success, FALSE = failure, returns -1 if RAS
|
|
// doesn't cache this piece of data and it should be put
|
|
// in the registry instead.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int WriteUserInfoToRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiDataID,
|
|
PVOID pvData)
|
|
{
|
|
int iReturn = -1;
|
|
|
|
if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
|
|
{
|
|
DWORD dwMask;
|
|
LPTSTR pszPhoneBook = NULL;
|
|
|
|
switch (uiDataID)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
dwMask = RASCM_UserName;
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
|
|
break;
|
|
|
|
case UD_ID_PASSWORD:
|
|
dwMask = RASCM_Password;
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
|
|
MYDBGASSERT(iReturn);
|
|
|
|
//
|
|
// Note that if we are using the same username then we want to write the password to both the
|
|
// password and the InetPassword storage. This is because we don't actually have a password, just
|
|
// 16 *'s. This tells RAS to look in its internal store for the password. The trouble is that if
|
|
// we don't cache the real password when we hand RAS the 16 *'s, it looks and finds a NULL password.
|
|
// Thus we keep both passwords the same and this avoids that problem.
|
|
//
|
|
if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName))
|
|
{
|
|
pszPhoneBook = CreateRasPrivatePbk(pArgs);
|
|
|
|
if (pszPhoneBook)
|
|
{
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
|
|
CmFree(pszPhoneBook);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case UD_ID_DOMAIN:
|
|
dwMask = RASCM_Domain;
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
|
|
break;
|
|
|
|
case UD_ID_INET_PASSWORD:
|
|
dwMask = RASCM_Password;
|
|
pszPhoneBook = CreateRasPrivatePbk(pArgs);
|
|
|
|
if (pszPhoneBook)
|
|
{
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
|
|
CmFree(pszPhoneBook);
|
|
}
|
|
break;
|
|
|
|
case UD_ID_INET_USERNAME:
|
|
dwMask = RASCM_UserName;
|
|
pszPhoneBook = CreateRasPrivatePbk(pArgs);
|
|
|
|
if (pszPhoneBook)
|
|
{
|
|
iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
|
|
CmFree(pszPhoneBook);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((0 != iReturn) && (-1 != iReturn))
|
|
{
|
|
if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
|
|
{
|
|
CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the Global RAS Credential store"), TranslateUserDataID(uiDataID));
|
|
}
|
|
else
|
|
{
|
|
CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the User RAS Credential store"), TranslateUserDataID(uiDataID));
|
|
}
|
|
}
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: WriteUserInfoToReg
|
|
//
|
|
// Synopsis: Write a userinfo data to the registry.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiDataID the resource ID associated with the data
|
|
// pvData userinfo data
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL WriteUserInfoToReg(
|
|
ArgsStruct *pArgs,
|
|
UINT uiDataID,
|
|
PVOID pvData)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(pvData);
|
|
|
|
BOOL fRet = FALSE;
|
|
UINT uiID = uiDataID; // can be changed in switch
|
|
BYTE *lpData;
|
|
|
|
if (NULL == pArgs || NULL == pvData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Determine Reg params based upon uiDataID
|
|
//
|
|
|
|
switch (uiID)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
case UD_ID_INET_USERNAME:
|
|
case UD_ID_DOMAIN:
|
|
case UD_ID_CURRENTACCESSPOINT:
|
|
{
|
|
//
|
|
// Store as strings
|
|
//
|
|
|
|
DWORD dwSize = (lstrlenU((LPTSTR)pvData) + 1) * sizeof(TCHAR);
|
|
|
|
MYDBGASSERT(dwSize <= (UNLEN + sizeof(TCHAR))); // Make sure size is reasonable
|
|
|
|
lpData = (BYTE *) pvData;
|
|
|
|
fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_SZ, lpData, dwSize, pArgs->fAllUser);
|
|
break;
|
|
}
|
|
|
|
case UD_ID_PASSWORD:
|
|
case UD_ID_INET_PASSWORD:
|
|
{
|
|
DWORD dwBufLen = 0;
|
|
DWORD dwCrypt = 0;
|
|
LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
|
|
|
|
LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
|
|
|
|
if (UD_ID_INET_PASSWORD == uiID)
|
|
{
|
|
dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
|
|
}
|
|
|
|
//
|
|
// Encrypt
|
|
//
|
|
|
|
LPTSTR pszEncryptedData = EncryptPassword(pArgs, (LPTSTR) pvData, &dwBufLen, &dwCrypt, TRUE, pszAnsiSubKey);
|
|
|
|
//
|
|
// Free in case we return if the function failed
|
|
//
|
|
CmFree(pszSubKey);
|
|
CmFree(pszAnsiSubKey);
|
|
|
|
if (!pszEncryptedData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
MYDBGASSERT(dwBufLen <= CM_MAX_PWD); // Can't read it out otherwise
|
|
|
|
//
|
|
// Write the password and the encryption type on success
|
|
//
|
|
|
|
if (WriteDataToReg(pArgs->szServiceName, uiID, REG_BINARY, (BYTE *) pszEncryptedData, dwBufLen, pArgs->fAllUser))
|
|
{
|
|
//
|
|
// A second write for the encryption type. Written as a DWORD.
|
|
//
|
|
|
|
uiID = UD_ID_PCS;
|
|
|
|
//
|
|
// Now that we're UNICODE enabled, we will always be encrypting
|
|
// a UNICODE string, so update the crypt type, so that it can be
|
|
// properly decrypted.
|
|
//
|
|
|
|
dwCrypt = AnsiToUnicodePcs(dwCrypt);
|
|
|
|
lpData = (BYTE *) &dwCrypt;
|
|
|
|
fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
|
|
}
|
|
|
|
//
|
|
// Release the buffer before we go
|
|
//
|
|
|
|
CmFree(pszEncryptedData);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
case UD_ID_NOPROMPT:
|
|
case UD_ID_REMEMBER_PWD:
|
|
case UD_ID_REMEMBER_INET_PASSWORD:
|
|
case UD_ID_ACCESSPOINTENABLED:
|
|
{
|
|
//
|
|
// Store BOOL as DWORD
|
|
//
|
|
|
|
DWORD dwTmp = *(LPBOOL)pvData;
|
|
lpData = (BYTE *) &dwTmp;
|
|
|
|
fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
MYDBGASSERT(fRet);
|
|
return fRet;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: WriteDataToReg
|
|
//
|
|
// Synopsis: Stores the specified data as the specifed value under the
|
|
// specified key under the userinfo root.
|
|
//
|
|
// Arguments: LPCTSTR pszKey - The key name (service name)
|
|
// UINT uiDataID - The resource ID, used to name the value
|
|
// DWORD dwType - The registry data type
|
|
// CONST BYTE *lpData - Ptr to the data to be stored
|
|
// DWORD cbData - The size of the data buffer
|
|
// BOOL fAllUser - Flag indicating that profile is All-User
|
|
//
|
|
// Returns: BOOL - TRUE on success, otherwise FALSE
|
|
//
|
|
// History: nickball Created 5/21/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
BOOL WriteDataToReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
DWORD dwType,
|
|
CONST BYTE *lpData,
|
|
DWORD cbData,
|
|
BOOL fAllUser)
|
|
{
|
|
MYDBGASSERT(pszKey && *pszKey);
|
|
MYDBGASSERT(lpData);
|
|
|
|
HKEY hKeyCm;
|
|
DWORD dwDisposition;
|
|
DWORD dwRes = 1;
|
|
LPTSTR pszSubKey;
|
|
|
|
if (NULL == pszKey || !*pszKey || NULL == lpData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Per-user data is always stored under HKEY_CURRENT_USER
|
|
// Build the sub key to be opened.
|
|
//
|
|
|
|
pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
|
|
|
|
if (NULL == pszSubKey)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Open the sub key under HKCU
|
|
//
|
|
|
|
dwRes = RegCreateKeyExU(HKEY_CURRENT_USER,
|
|
pszSubKey,
|
|
0,
|
|
TEXT(""),
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_SET_VALUE,
|
|
NULL,
|
|
&hKeyCm,
|
|
&dwDisposition);
|
|
|
|
//
|
|
// If we opened the key successfully, write the value
|
|
//
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwRes = RegSetValueExU(hKeyCm,
|
|
TranslateUserDataID(uiDataID),
|
|
NULL,
|
|
dwType,
|
|
lpData,
|
|
cbData);
|
|
#ifdef DEBUG
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
CMTRACE1(TEXT("WriteDataToReg() - %s written to registry"), TranslateUserDataID(uiDataID));
|
|
}
|
|
#endif
|
|
|
|
RegCloseKey(hKeyCm);
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
|
|
return (ERROR_SUCCESS == dwRes);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteDataFromReg
|
|
//
|
|
// Synopsis: Deletes the specified value under the specified by uiDataID
|
|
//
|
|
// Arguments: LPCTSTR pszKey - The key name (service name)
|
|
// UINT uiDataID - The resource ID, used to name the value
|
|
// BOOL fAllUser - Flag indicating that profile is All-User
|
|
//
|
|
// Returns: BOOL - TRUE on success, otherwise FALSE
|
|
//
|
|
// History: nickball Created 5/21/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
BOOL DeleteDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
BOOL fAllUser)
|
|
{
|
|
MYDBGASSERT(pszKey && *pszKey);
|
|
|
|
HKEY hKeyCm;
|
|
DWORD dwRes = 1;
|
|
LPTSTR pszSubKey;
|
|
|
|
if (NULL == pszKey || !*pszKey)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Per-user data is always stored under HKEY_CURRENT_USER
|
|
// Build the sub key to be opened.
|
|
//
|
|
|
|
pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
|
|
|
|
if (NULL == pszSubKey)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Open the sub key under HKCU
|
|
//
|
|
|
|
dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
|
|
pszSubKey,
|
|
0,
|
|
KEY_SET_VALUE,
|
|
&hKeyCm);
|
|
|
|
//
|
|
// If we opened the key successfully, delete the value
|
|
//
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwRes = RegDeleteValueU(hKeyCm, TranslateUserDataID(uiDataID));
|
|
|
|
//
|
|
// Delete the key used for encrypting the passwords
|
|
//
|
|
if (UD_ID_PASSWORD == uiDataID)
|
|
{
|
|
dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedPasswordKey);
|
|
}
|
|
|
|
if (UD_ID_INET_PASSWORD == uiDataID)
|
|
{
|
|
dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedInternetPasswordKey);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
CMTRACE1(TEXT("DeleteDataFromReg() - %s removed from registry"), TranslateUserDataID(uiDataID));
|
|
}
|
|
#endif
|
|
|
|
RegCloseKey(hKeyCm);
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
|
|
return (ERROR_SUCCESS == dwRes);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDataFromReg
|
|
//
|
|
// Synopsis: Allocates a buffer for and retrieves the specifed data from the
|
|
// registry.
|
|
//
|
|
// Arguments: LPCTSTR pszKey - The key name (service name)
|
|
// UINT uiDataID - The resource ID, used to name the value
|
|
// DWORD dwType - The registry data type
|
|
// DWORD dwSize - Numbrt of bytes in the data buffer
|
|
// BOOL fAllUser - Flag indicating that profile is All-User
|
|
//
|
|
// Returns: LPBYTE - Ptr to retrieved data, NULL on error
|
|
//
|
|
// History: nickball Created 5/21/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPBYTE GetDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
DWORD dwType,
|
|
DWORD dwSize,
|
|
BOOL fAllUser)
|
|
{
|
|
MYDBGASSERT(pszKey);
|
|
|
|
DWORD dwSizeTmp = dwSize;
|
|
DWORD dwTypeTmp = dwType;
|
|
|
|
if (NULL == pszKey || !*pszKey)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer of the desired size
|
|
//
|
|
|
|
LPBYTE lpData = (BYTE *) CmMalloc(dwSize);
|
|
|
|
if (NULL == lpData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Read the data from the registry
|
|
//
|
|
|
|
if (!ReadDataFromReg(pszKey, uiDataID, &dwTypeTmp, lpData, &dwSizeTmp, fAllUser))
|
|
{
|
|
CmFree(lpData);
|
|
lpData = NULL;
|
|
}
|
|
|
|
return lpData;
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadUserInfoFromReg
|
|
//
|
|
// Synopsis: Read the specified userinfo data from the registry.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiDataID the resource ID associated with the data
|
|
// ppvData ptr to ptr to be allocated and filled
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL ReadUserInfoFromReg(
|
|
ArgsStruct *pArgs,
|
|
UINT uiDataID,
|
|
PVOID *ppvData)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(ppvData);
|
|
|
|
BYTE *lpData = NULL;
|
|
|
|
if (NULL == pArgs || NULL == ppvData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set size and type as appropriate
|
|
//
|
|
|
|
switch (uiDataID)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
case UD_ID_INET_USERNAME:
|
|
case UD_ID_DOMAIN:
|
|
case UD_ID_CURRENTACCESSPOINT:
|
|
{
|
|
lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_SZ, (UNLEN + 1) * sizeof(TCHAR), pArgs->fAllUser);
|
|
|
|
if (lpData)
|
|
{
|
|
*ppvData = lpData;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case UD_ID_PASSWORD:
|
|
case UD_ID_INET_PASSWORD:
|
|
{
|
|
BYTE *lpTmp = NULL;
|
|
|
|
//
|
|
// Get the encryption type
|
|
//
|
|
|
|
lpData = GetDataFromReg(pArgs->szServiceName, UD_ID_PCS, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
|
|
|
|
if (!lpData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Since we know the return value in this case is a DWORD, then cast it to DWORD pointer
|
|
// and get the value
|
|
//
|
|
DWORD dwCrypt = *((DWORD*)lpData);
|
|
CmFree(lpData);
|
|
|
|
//
|
|
// Now retrieve the encrypted password
|
|
//
|
|
|
|
lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_BINARY, CM_MAX_PWD, pArgs->fAllUser);
|
|
|
|
if (!lpData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Decrypt it
|
|
//
|
|
|
|
DWORD dwSize = lstrlenU((LPTSTR)lpData)*sizeof(TCHAR);
|
|
|
|
//
|
|
// Crypt routines only know about Ansi PCS values, so convert as necessary
|
|
//
|
|
LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
|
|
LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
|
|
|
|
if (UD_ID_INET_PASSWORD == uiDataID)
|
|
{
|
|
dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
|
|
}
|
|
|
|
lpTmp = DecryptPassword(pArgs, (LPBYTE)lpData, UnicodeToAnsiPcs(dwCrypt), dwSize, TRUE, pszAnsiSubKey);
|
|
|
|
//
|
|
// Free the buffer for the reg query
|
|
//
|
|
|
|
CmFree(lpData);
|
|
|
|
//
|
|
// We're Unicode now, so if the password was encrypted
|
|
// as an Ansi string convert the data to a UNICODE string.
|
|
// Otherwise, just update the supplied buffer.
|
|
//
|
|
|
|
if (IsAnsiPcs(dwCrypt) && lpTmp)
|
|
{
|
|
*ppvData = SzToWzWithAlloc((LPSTR)lpTmp);
|
|
CmFree(lpTmp);
|
|
}
|
|
else
|
|
{
|
|
*ppvData = lpTmp;
|
|
}
|
|
|
|
//
|
|
// Assign lpData for return purposes
|
|
//
|
|
|
|
lpData = (BYTE*) *ppvData; // NULL on failure
|
|
|
|
CmFree(pszSubKey);
|
|
CmFree(pszAnsiSubKey);
|
|
break;
|
|
}
|
|
|
|
case UD_ID_NOPROMPT:
|
|
case UD_ID_REMEMBER_PWD:
|
|
case UD_ID_REMEMBER_INET_PASSWORD:
|
|
case UD_ID_ACCESSPOINTENABLED:
|
|
{
|
|
lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
|
|
|
|
if (lpData)
|
|
{
|
|
//
|
|
// Translate to DWORD pointer and check the value
|
|
//
|
|
|
|
if (*((DWORD*)lpData))
|
|
{
|
|
*(BOOL *)*ppvData = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*(BOOL *)*ppvData = FALSE;
|
|
}
|
|
|
|
CmFree(lpData);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
MYDBGASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
return (NULL != lpData);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadDataFromReg
|
|
//
|
|
// Synopsis: Retrieves the data from the specifed value under the
|
|
// specified key under the userinfo root.
|
|
//
|
|
// Arguments: LPCTSTR pszKey - The key name (service name)
|
|
// UINT uiDataID - The resource ID, used to name the value
|
|
// LPDWORD lpdwType - The registry data type expected, and returned
|
|
// CONST BYTE *lpData - Ptr to buffer for data
|
|
// LPDWORD lpcbData - The size of the data buffer
|
|
// BOOL fAllUser - Flag indicating that profile is All-User
|
|
//
|
|
// Returns: BOOL - TRUE on success, otherwise FALSE
|
|
//
|
|
// History: nickball Created 5/21/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
BOOL ReadDataFromReg(
|
|
LPCTSTR pszKey,
|
|
UINT uiDataID,
|
|
LPDWORD lpdwType,
|
|
BYTE *lpData,
|
|
LPDWORD lpcbData,
|
|
BOOL fAllUser)
|
|
{
|
|
MYDBGASSERT(pszKey && *pszKey);
|
|
MYDBGASSERT(lpData);
|
|
MYDBGASSERT(lpcbData);
|
|
MYDBGASSERT(lpdwType);
|
|
|
|
HKEY hKeyCm;
|
|
DWORD dwRes = 1;
|
|
DWORD dwTypeTmp; // the value returned by query
|
|
|
|
LPTSTR pszSubKey;
|
|
|
|
if (NULL == pszKey || !*pszKey || NULL == lpData)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Per-user data is always stored under HKEY_CURRENT_USER
|
|
// Build the sub key to be opened.
|
|
//
|
|
|
|
pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
|
|
|
|
if (NULL == pszSubKey)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Open the sub key under HKCU
|
|
//
|
|
|
|
dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
|
|
pszSubKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKeyCm);
|
|
//
|
|
// If we opened the key successfully, retrieve the value
|
|
//
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
dwRes = RegQueryValueExU(hKeyCm,
|
|
TranslateUserDataID(uiDataID),
|
|
NULL,
|
|
&dwTypeTmp,
|
|
lpData,
|
|
lpcbData);
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
CMTRACE1(TEXT("ReadDataFromReg() - %s read from registry"), TranslateUserDataID(uiDataID));
|
|
MYDBGASSERT(*lpdwType == dwTypeTmp);
|
|
|
|
if (*lpdwType == dwTypeTmp)
|
|
{
|
|
*lpdwType = dwTypeTmp;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKeyCm);
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
|
|
return (ERROR_SUCCESS == dwRes && (*lpdwType == dwTypeTmp)); // sanity check that type was expected
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteUserInfoFromReg
|
|
//
|
|
// Synopsis: Delete userinfo data from registry
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry cmp field entry id
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL DeleteUserInfoFromReg(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry
|
|
)
|
|
{
|
|
return DeleteDataFromReg(pArgs->szServiceName, uiEntry, pArgs->fAllUser);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteUserInfoFromRas
|
|
//
|
|
// Synopsis: Delete userinfo data from the RAS credential cache
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry cmp field entry id
|
|
//
|
|
// Returns: int TRUE = success, FALSE = failure, -1 if RAS doesn't
|
|
// store this info
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int DeleteUserInfoFromRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry
|
|
)
|
|
{
|
|
LPTSTR pszEmpty = TEXT("");
|
|
|
|
return WriteUserInfoToRas(pArgs, uiEntry, pszEmpty);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadPasswordFromCmp
|
|
//
|
|
// Synopsis: Read a null terminated password string from Cmp.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry cmp entry name
|
|
// ppszPassword ptr to ptr of the password buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL ReadPasswordFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
LPTSTR *ppszPassword
|
|
)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(ppszPassword);
|
|
|
|
if (NULL == pArgs || NULL == ppszPassword)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Read in password from profile
|
|
//
|
|
|
|
BOOL fOk = FALSE;
|
|
|
|
LPTSTR pszEncryptedData = pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
|
|
|
|
if (*pszEncryptedData)
|
|
{
|
|
//
|
|
// Trim away all the spaces at both ends
|
|
//
|
|
|
|
CmStrTrim(pszEncryptedData);
|
|
|
|
//
|
|
// Get the type and decrypt
|
|
//
|
|
|
|
DWORD dwEncryptionType = (DWORD)pArgs->piniProfile->GPPI(c_pszCmSection,
|
|
c_pszCmEntryPcs,
|
|
CMSECURE_ET_RC2); // default
|
|
//
|
|
// Since this was saved in the CMP in Ansi form, we need to convert the characters back to
|
|
// Ansi form so that we can decrypt them. We still may not be able to (if we cannot
|
|
// round trip the Unicode conversion for instance) but then we will fail and display a
|
|
// blank password. Not the end of the world but hopefully avoidable.
|
|
//
|
|
|
|
LPSTR pszAnsiEncryptedData;
|
|
LPSTR pszAnsiUnEncryptedData;
|
|
|
|
pszAnsiEncryptedData = WzToSzWithAlloc(pszEncryptedData);
|
|
|
|
if (NULL != pszAnsiEncryptedData)
|
|
{
|
|
DWORD dwSize = lstrlenA(pszAnsiEncryptedData)*sizeof(TCHAR);
|
|
|
|
//
|
|
// Here we don't need to differentiate between main password and internet password
|
|
// because we are reading this from a file and the mask is used when reading to/from
|
|
// registry.
|
|
//
|
|
|
|
pszAnsiUnEncryptedData = (LPSTR)DecryptPassword(pArgs,
|
|
(LPBYTE)pszAnsiEncryptedData,
|
|
dwEncryptionType,
|
|
dwSize,
|
|
FALSE,
|
|
NULL);
|
|
|
|
if (pszAnsiUnEncryptedData)
|
|
{
|
|
*ppszPassword = SzToWzWithAlloc(pszAnsiUnEncryptedData);
|
|
|
|
if (NULL != *ppszPassword)
|
|
{
|
|
fOk = ((BOOL)**ppszPassword);
|
|
}
|
|
CmWipePasswordA(pszAnsiUnEncryptedData);
|
|
CmFree(pszAnsiUnEncryptedData);
|
|
}
|
|
}
|
|
|
|
CmFree(pszAnsiEncryptedData);
|
|
}
|
|
|
|
CmFree(pszEncryptedData);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadUserInfoFromCmp
|
|
//
|
|
// Synopsis: Read a userinfo data from cmp.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
// ppvData ptr to ptr to the data buffer. If the userinfo
|
|
// is multiple byte(e.g. password), the func allocs
|
|
// the buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL ReadUserInfoFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID *ppvData
|
|
)
|
|
{
|
|
switch (uiEntry)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
case UD_ID_INET_USERNAME:
|
|
case UD_ID_DOMAIN:
|
|
*ppvData = (PVOID)pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
|
|
break;
|
|
|
|
case UD_ID_PASSWORD:
|
|
case UD_ID_INET_PASSWORD:
|
|
return ReadPasswordFromCmp(pArgs, uiEntry, (LPTSTR *)ppvData);
|
|
break;
|
|
|
|
case UD_ID_NOPROMPT:
|
|
case UD_ID_REMEMBER_PWD:
|
|
case UD_ID_REMEMBER_INET_PASSWORD:
|
|
*(BOOL *)(*ppvData) = pArgs->piniProfile->GPPB(c_pszCmSection, TranslateUserDataID(uiEntry));
|
|
break;
|
|
|
|
//
|
|
// None of these should be in the CMP by this point. Return a failure value.
|
|
//
|
|
case UD_ID_PCS:
|
|
case UD_ID_ACCESSPOINTENABLED:
|
|
case UD_ID_CURRENTACCESSPOINT: // if we are trying to read the access point
|
|
CMASSERTMSG(FALSE, TEXT("ReadUserInfoFromCmp -- trying to read a value that should never be in the cmp, why?"));
|
|
*ppvData = NULL;
|
|
return FALSE;
|
|
break;
|
|
|
|
default:
|
|
MYDBGASSERT(0);
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteUserInfoFromCmp
|
|
//
|
|
// Synopsis: Deletes userinfo data from cmp.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL DeleteUserInfoFromCmp(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
UINT uiKeepDefCreds = 0;
|
|
const TCHAR* const c_pszKeepDefaultCredentials = TEXT("KeepDefaultCredentials");
|
|
|
|
if (NULL == pArgs)
|
|
{
|
|
return bReturn;
|
|
}
|
|
|
|
switch (uiEntry)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
case UD_ID_DOMAIN:
|
|
case UD_ID_INET_USERNAME:
|
|
case UD_ID_NOPROMPT:
|
|
case UD_ID_REMEMBER_PWD:
|
|
case UD_ID_REMEMBER_INET_PASSWORD:
|
|
case UD_ID_PASSWORD:
|
|
case UD_ID_INET_PASSWORD:
|
|
|
|
//
|
|
// Get KeepDefaultCredentials value from CMP
|
|
//
|
|
uiKeepDefCreds = GetPrivateProfileIntU(c_pszCmSection, c_pszKeepDefaultCredentials, 0,
|
|
pArgs->piniProfile->GetFile());
|
|
|
|
if (0 == uiKeepDefCreds)
|
|
{
|
|
if (WritePrivateProfileStringU(c_pszCmSection, TranslateUserDataID(uiEntry),
|
|
NULL, pArgs->piniProfile->GetFile()))
|
|
{
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
MYDBGASSERT(0);
|
|
break;
|
|
|
|
}
|
|
return bReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RasGetCredsWrapper
|
|
//
|
|
// Synopsis: Wrapper function to call RasGetCredentials. The function
|
|
// calls RasGetCredentials and then copies the appropriate data
|
|
// from the RASCREDENTIALS struct into the buffer pointed to by
|
|
// *ppvData (allocated on the caller behalf). Note that the value
|
|
// set in dwMask determines which data item is retrieved from the
|
|
// credentials cache. Currently, dwMask must be one of RASCM_UserName,
|
|
// RASCM_Domain, or RASCM_Password.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// pszPhoneBook full path to the phonebook file to get the
|
|
// data from, or NULL to use the all user default pbk
|
|
// dwMask dwMask value for the RASCREDENTIALS struct
|
|
// ppvData ptr to ptr to the data buffer. If the userinfo
|
|
// is multiple byte(e.g. password), the func allocs
|
|
// the buffer.
|
|
//
|
|
// Returns: DWORD ERROR_SUCCESS on success, winerror on failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
DWORD RasGetCredsWrapper(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPhoneBook,
|
|
DWORD dwMask,
|
|
PVOID *ppvData
|
|
)
|
|
{
|
|
DWORD dwRet = ERROR_INVALID_PARAMETER;
|
|
|
|
MYDBGASSERT(pArgs && pArgs->rlsRasLink.pfnGetCredentials);
|
|
MYDBGASSERT(ppvData);
|
|
MYDBGASSERT((RASCM_UserName == dwMask) || (RASCM_Domain == dwMask) || (RASCM_Password == dwMask));
|
|
|
|
if (pArgs && ppvData && pArgs->rlsRasLink.pfnGetCredentials)
|
|
{
|
|
LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
|
|
|
|
if (pszConnectoid)
|
|
{
|
|
RASCREDENTIALS RasCredentials = {0};
|
|
RasCredentials.dwSize = sizeof(RasCredentials);
|
|
|
|
if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
|
|
{
|
|
RasCredentials.dwMask = dwMask | RASCM_DefaultCreds;
|
|
}
|
|
else
|
|
{
|
|
RasCredentials.dwMask = dwMask;
|
|
}
|
|
|
|
dwRet = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials);
|
|
|
|
if (ERROR_SUCCESS == dwRet)
|
|
{
|
|
LPTSTR pszData = NULL;
|
|
|
|
if (RASCM_UserName == dwMask)
|
|
{
|
|
pszData = RasCredentials.szUserName;
|
|
}
|
|
else if (RASCM_Domain == dwMask)
|
|
{
|
|
pszData = RasCredentials.szDomain;
|
|
}
|
|
else if (RASCM_Password == dwMask)
|
|
{
|
|
pszData = RasCredentials.szPassword;
|
|
}
|
|
|
|
LPTSTR pszReturn = CmStrCpyAlloc(pszData);
|
|
|
|
if (NULL == pszReturn)
|
|
{
|
|
dwRet = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
*ppvData = pszReturn;
|
|
}
|
|
}
|
|
|
|
CmWipePassword(RasCredentials.szPassword);
|
|
|
|
CmFree(pszConnectoid);
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadUserInfoFromRas
|
|
//
|
|
// Synopsis: Read userinfo data from the RAS credentials cache
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
// ppvData ptr to ptr to the data buffer. If the userinfo
|
|
// is multiple byte(e.g. password), the func allocs
|
|
// the buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL ReadUserInfoFromRas(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID *ppvData
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
|
|
{
|
|
DWORD dwMask;
|
|
LPTSTR pszPhoneBook = NULL;
|
|
|
|
switch (uiEntry)
|
|
{
|
|
case UD_ID_USERNAME:
|
|
dwMask = RASCM_UserName;
|
|
bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
|
|
|
|
break;
|
|
|
|
case UD_ID_PASSWORD:
|
|
dwMask = RASCM_Password;
|
|
bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
|
|
break;
|
|
|
|
case UD_ID_DOMAIN:
|
|
dwMask = RASCM_Domain;
|
|
bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
|
|
break;
|
|
|
|
case UD_ID_INET_PASSWORD:
|
|
dwMask = RASCM_Password;
|
|
pszPhoneBook = CreateRasPrivatePbk(pArgs);
|
|
|
|
if (pszPhoneBook)
|
|
{
|
|
bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
|
|
CmFree(pszPhoneBook);
|
|
}
|
|
break;
|
|
|
|
case UD_ID_INET_USERNAME:
|
|
dwMask = RASCM_UserName;
|
|
pszPhoneBook = CreateRasPrivatePbk(pArgs);
|
|
|
|
if (pszPhoneBook)
|
|
{
|
|
bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
|
|
CmFree(pszPhoneBook);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bReturn)
|
|
{
|
|
if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
|
|
{
|
|
CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the Global RAS Credential store"), TranslateUserDataID(uiEntry));
|
|
}
|
|
else
|
|
{
|
|
CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the User RAS Credential store"), TranslateUserDataID(uiEntry));
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetUserInfo
|
|
//
|
|
// Synopsis: Get an userinfo. The user info can reside in either the
|
|
// cache, cmp, or registry. This functions hides this from the
|
|
// user.
|
|
//
|
|
// We first try the cmp file. If that fails, we try the cache.
|
|
// We'll get the following user info:
|
|
// username,
|
|
// password,
|
|
// domain,
|
|
// remember main passwd,
|
|
// dial automatically,
|
|
// inet username,
|
|
// inet passwd
|
|
// remember inet password
|
|
// inet use same user name
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
// pvData ptr to ptr to the data buffer. If the userinfo
|
|
// is multiple byte(e.g. password), the func allocs
|
|
// the buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL GetUserInfo(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID *ppvData
|
|
)
|
|
{
|
|
BOOL bReturn = ReadUserInfoFromRas(pArgs, uiEntry, ppvData);
|
|
|
|
if (!bReturn)
|
|
{
|
|
bReturn = ReadUserInfoFromReg(pArgs, uiEntry, ppvData);
|
|
}
|
|
|
|
if (!bReturn)
|
|
{
|
|
bReturn = ReadUserInfoFromCmp(pArgs, uiEntry, ppvData);
|
|
}
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaveUserInfo
|
|
//
|
|
// Synopsis: Save an userinfo. The user info can reside in either the
|
|
// RAS cred cache or the registry. This functions abstracts
|
|
// this from the user.
|
|
//
|
|
// We first try the RAS cred cache. If the RAS cred cache doesn't hold that
|
|
// piece of info we then save it in the registry.
|
|
// We'll save the following user info:
|
|
// username,
|
|
// password,
|
|
// domain,
|
|
// remember main passwd,
|
|
// dial automatically,
|
|
// inet username,
|
|
// inet passwd
|
|
// remember inet password
|
|
// inet use same user name
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
// pvData ptr to the data buffer. If the userinfo is
|
|
// multiple byte(e.g. password), the func allocs
|
|
// the buffer.
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL SaveUserInfo(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry,
|
|
PVOID pvData
|
|
)
|
|
{
|
|
//
|
|
// Try giving the Data to RAS first. If the function returns
|
|
// -1, then this is data that RAS doesn't hold for us and we will
|
|
// have to put it in the registry instead.
|
|
//
|
|
int iReturn = WriteUserInfoToRas(pArgs, uiEntry, pvData);
|
|
|
|
if (-1 == iReturn)
|
|
{
|
|
//
|
|
// Just write the data to the registry. Use CMP only as
|
|
// an upgrade reference for UserInfo data post CM 1.1
|
|
//
|
|
|
|
iReturn = WriteUserInfoToReg(pArgs, uiEntry, pvData);
|
|
}
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteUserInfo
|
|
//
|
|
// Synopsis: Delete an userinfo. The user info can reside in either the
|
|
// RAS Cred cache or the registry. This functions abstracts
|
|
// this from the user.
|
|
//
|
|
// We first try the RAS cache first. If that piece of info isn't stored
|
|
// in the RAS cache then we try the registry.
|
|
//
|
|
// We'll delete the following user info:
|
|
// username,
|
|
// password,
|
|
// domain,
|
|
// remember main passwd,
|
|
// dial automatically,
|
|
// inet username,
|
|
// inet passwd
|
|
// remember inet password
|
|
// inet use same user name
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
// uiEntry the cmp file entry
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL DeleteUserInfo(
|
|
ArgsStruct *pArgs,
|
|
UINT uiEntry
|
|
)
|
|
{
|
|
int iReturn = DeleteUserInfoFromRas(pArgs, uiEntry);
|
|
|
|
if (-1 == iReturn)
|
|
{
|
|
iReturn = DeleteUserInfoFromReg(pArgs, uiEntry);
|
|
}
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NeedToUpgradeUserInfo
|
|
//
|
|
// Synopsis: Do we need to upgrade the cm 1.0/1.1 userinfo to the cm 1.2 format?
|
|
//
|
|
// Arguments: pArgs - Ptr to global args struct
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
int NeedToUpgradeUserInfo(
|
|
ArgsStruct *pArgs)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
|
|
DWORD dwRes;
|
|
HKEY hKeyCm;
|
|
LPTSTR pszSubKey;
|
|
int iReturn = c_iNoUpgradeRequired;
|
|
|
|
if (pArgs)
|
|
{
|
|
//
|
|
// If this is NT5 or greater, we want to be storing our credentials with RAS
|
|
// instead of the registry.
|
|
//
|
|
// If this isn't NT5 we still want to upgrade the user to using the registry as
|
|
// storage instead of the cmp if they haven't already
|
|
// been upgraded. Thus the simple test is to open the service name key in HKCU.
|
|
// This key will exist, if the user has already run 1.2 bits.
|
|
//
|
|
|
|
pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
|
|
|
|
dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
|
|
pszSubKey,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hKeyCm);
|
|
|
|
if (ERROR_SUCCESS == dwRes)
|
|
{
|
|
//
|
|
// Then we have the registry method, unless we are supposed to be using the RAS
|
|
// cred store we are done. If we are supposed to be using the RAS cred store
|
|
// we need to check to make sure that we are using it. Note we could have a problem
|
|
// here if the user has registry cred data and then their registry gets write protected.
|
|
// This would allow us to read from it but not delete the old data. Thus the user
|
|
// would never be able to save any changes because we would always think they needed
|
|
// to upgrade. An unlikely scenario but possible ...
|
|
//
|
|
|
|
if (pArgs->bUseRasCredStore)
|
|
{
|
|
LPTSTR pszUserName = NULL;
|
|
|
|
BOOL bRet = ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
|
|
|
|
if (bRet && (NULL != pszUserName) && (TEXT('\0') != pszUserName[0]))
|
|
{
|
|
//
|
|
// Then we have the username in the registry. Lets upgrade to the RAS
|
|
// credential store.
|
|
//
|
|
iReturn = c_iUpgradeFromRegToRas;
|
|
}
|
|
|
|
CmFree(pszUserName);
|
|
}
|
|
|
|
RegCloseKey(hKeyCm);
|
|
}
|
|
else
|
|
{
|
|
iReturn = c_iUpgradeFromCmp;
|
|
}
|
|
|
|
CmFree(pszSubKey);
|
|
}
|
|
else
|
|
{
|
|
CMASSERTMSG(FALSE, TEXT("NeedToUpgradeUserInfo -- NULL pArgs passed"));
|
|
}
|
|
|
|
//
|
|
// We don't want to upgrade if it's ICS. This prevents from adding info to the registry.
|
|
//
|
|
if (CM_LOGON_TYPE_ICS == pArgs->dwWinLogonType)
|
|
{
|
|
iReturn = c_iNoUpgradeRequired;
|
|
}
|
|
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UpgradeUserInfoFromRegToRasAndReg
|
|
//
|
|
// Synopsis: Upgrade the userinfo from CM 1.2 registry only format to the
|
|
// CM 1.3 format which uses both RAS credential storage and
|
|
// the registry.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL UpgradeUserInfoFromRegToRasAndReg(
|
|
ArgsStruct *pArgs
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
if (OS_NT5)
|
|
{
|
|
LPTSTR pszTmp;
|
|
|
|
pszTmp = NULL;
|
|
|
|
//
|
|
// If we get an empty string "" from ReadUserInfoFromReg we don't want to
|
|
// save the empty string to the RAS Credstore because it might overwrite
|
|
// global credentials information. This can happen if User1 saves global
|
|
// credentials and User2 tries using the same profile. Since User2 is running
|
|
// this profile for the 1st time, he'll run through an upgrade path and if global
|
|
// creds exist we don't want to null them out.
|
|
//
|
|
|
|
if (ReadUserInfoFromReg(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp))
|
|
{
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_INET_USERNAME);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
WriteUserInfoToRas(pArgs, UD_ID_INET_USERNAME, pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
|
|
pszTmp = NULL;
|
|
if (ReadUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
|
|
{
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
WriteUserInfoToRas(pArgs, UD_ID_INET_PASSWORD, pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
|
|
pszTmp = NULL;
|
|
if (ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp))
|
|
{
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_USERNAME);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
WriteUserInfoToRas(pArgs, UD_ID_USERNAME, pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
|
|
pszTmp = NULL;
|
|
if (ReadUserInfoFromReg(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp))
|
|
{
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_DOMAIN);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
WriteUserInfoToRas(pArgs, UD_ID_DOMAIN, pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
|
|
pszTmp = NULL;
|
|
if (ReadUserInfoFromReg(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
|
|
{
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_PASSWORD);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
WriteUserInfoToRas(pArgs, UD_ID_PASSWORD, pszTmp);
|
|
}
|
|
CmFree(pszTmp);
|
|
}
|
|
|
|
//
|
|
// Now delete the PCS value as it is no longer meaningful
|
|
//
|
|
DeleteUserInfoFromReg(pArgs, UD_ID_PCS);
|
|
}
|
|
else
|
|
{
|
|
MYDBGASSERT(FALSE);
|
|
}
|
|
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UpgradeUserInfoFromCmp
|
|
//
|
|
// Synopsis: Upgrade the userinfo from cm1.0/1,1 format to 1.3 format.
|
|
//
|
|
// Arguments: pArgs ptr to ArgsStruct
|
|
//
|
|
// Returns: BOOL TRUE = success, FALSE = failure
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL UpgradeUserInfoFromCmp(
|
|
ArgsStruct *pArgs
|
|
)
|
|
{
|
|
LPTSTR pszTmp;
|
|
BOOL fTmp;
|
|
PVOID pv;
|
|
|
|
//
|
|
// First retrieve each of the non-cached data items
|
|
// Then delete username, internetusername, domain, password,
|
|
// internetpassword, remember password, remember internet password
|
|
// and noprompt (dial automatically) from the CMP file.
|
|
// If the KeepDefaultCredentials is set to 1 in the .CMP file then the
|
|
// DeleteUserInfoFromCmp function does not actually delete the values from
|
|
// the file.
|
|
// If we get an empty string "" from ReadUserInfoFromCmp we don't want to
|
|
// save the empty string to the RAS Credstore because it might overwrite
|
|
// global credentials information. This can happen if User1 saves global
|
|
// credentials and User2 tries using the same profile. Since User2 is running
|
|
// this profile for the 1st time, he'll run through an upgrade path and if global
|
|
// creds exist we don't want to null them out.
|
|
//
|
|
|
|
pszTmp = NULL;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
SaveUserInfo(pArgs, UD_ID_USERNAME, pszTmp);
|
|
}
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_USERNAME);
|
|
CmFree(pszTmp);
|
|
|
|
pszTmp = NULL;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
SaveUserInfo(pArgs, UD_ID_DOMAIN, pszTmp);
|
|
}
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_DOMAIN);
|
|
CmFree(pszTmp);
|
|
|
|
pszTmp = NULL;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp);
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
SaveUserInfo(pArgs, UD_ID_INET_USERNAME, pszTmp);
|
|
}
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME);
|
|
CmFree(pszTmp);
|
|
|
|
pv = &fTmp;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_NOPROMPT, &pv);
|
|
SaveUserInfo(pArgs, UD_ID_NOPROMPT, pv);
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_NOPROMPT);
|
|
|
|
pv = &fTmp;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD, &pv);
|
|
SaveUserInfo(pArgs, UD_ID_REMEMBER_PWD, pv);
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD);
|
|
|
|
pv = &fTmp;
|
|
ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD, &pv);
|
|
SaveUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, pv);
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD);
|
|
|
|
//
|
|
// Construct old cache entry name
|
|
//
|
|
|
|
LPTSTR pszCacheEntryName = GetLegacyKeyName(pArgs);
|
|
|
|
//
|
|
// main passwd
|
|
//
|
|
pszTmp = NULL;
|
|
|
|
//
|
|
// To get the passwords, the cm 1.1 logic is that we first try the cmp, then the cache.
|
|
//
|
|
|
|
if (ReadUserInfoFromCmp(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
|
|
{
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CmFree(pszTmp);
|
|
pszTmp = NULL;
|
|
|
|
#ifdef TEST_USERINFO_UPGRADE
|
|
|
|
MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 main password")));
|
|
#endif
|
|
|
|
//
|
|
// Try to read it from cache
|
|
//
|
|
|
|
if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
|
|
{
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
if (SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp))
|
|
{
|
|
|
|
#ifdef TEST_USERINFO_UPGRADE
|
|
|
|
MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_PASSWORD);
|
|
CmFree(pszTmp);
|
|
|
|
//
|
|
// inet passwd
|
|
//
|
|
pszTmp = NULL;
|
|
if (ReadUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
|
|
{
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CmFree(pszTmp);
|
|
pszTmp = NULL;
|
|
|
|
//
|
|
// Build tunnel entry name and read string from cache
|
|
//
|
|
|
|
pszCacheEntryName = CmStrCatAlloc(&pszCacheEntryName, TEXT("-tunnel"));
|
|
|
|
#ifdef TEST_USERINFO_UPGRADE
|
|
|
|
MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 internet password")));
|
|
#endif
|
|
|
|
if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
|
|
{
|
|
if (pszTmp && lstrlenU(pszTmp))
|
|
{
|
|
if (SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp))
|
|
{
|
|
|
|
#ifdef TEST_USERINFO_UPGRADE
|
|
|
|
MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DeleteUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD);
|
|
CmFree(pszTmp);
|
|
|
|
CmFree(pszCacheEntryName);
|
|
|
|
return TRUE; // MarkUserInfoUpgraded(pArgs);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: GetLegacyKeyName
|
|
//
|
|
// Synopsis: Builds the string fragment used to build cache entry name. The "
|
|
// sign-in" prefix is maintained for legacy compatibility
|
|
//
|
|
// Arguments: ArgsStruct *pArgs - Ptr to global args struct
|
|
//
|
|
// Returns: LPTSTR - Ptr to allocated string containing "<service name> - Sign-In"
|
|
//
|
|
// Note: Used exclusively for cache entry name construction
|
|
//
|
|
// History: nickball Created Header 4/16/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPTSTR GetLegacyKeyName(ArgsStruct *pArgs)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
|
|
//
|
|
// Service name is the basis of the key name. We also include
|
|
// IDMSG_TITLESERVICE and append a suffix of " (Connection Manager)"
|
|
//
|
|
|
|
LPTSTR pszRes = CmFmtMsg(g_hInst, IDMSG_TITLESERVICE, pArgs->szServiceName);
|
|
|
|
MYDBGASSERT(pszRes && *pszRes);
|
|
|
|
if (pszRes)
|
|
{
|
|
pszRes = CmStrCatAlloc(&pszRes, c_pszCacheEntryNameSuffix);
|
|
}
|
|
|
|
return (pszRes);
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: EncryptPassword
|
|
//
|
|
// Synopsis: Wrapper for encrypting password
|
|
//
|
|
// Arguments: ArgsStruct *pArgs - Ptr to global args struct
|
|
// LPCTSTR pszPassword - The password to be encrypted
|
|
// LPDWORD lpdwBufSize - Buffer for size of the encrypted buffer - optional
|
|
// LPDWORD lpdwCryptType - Buffer for crypto type used
|
|
// BOOL fReg - Password is disguised for registry storage
|
|
//
|
|
// Returns: LPTSTR - Ptr to allocated buffer containing encrypted form of password
|
|
//
|
|
// History: nickball Created Header 5/22/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
LPTSTR EncryptPassword(
|
|
ArgsStruct *pArgs,
|
|
LPCTSTR pszPassword,
|
|
LPDWORD lpdwBufSize,
|
|
LPDWORD lpdwCryptType,
|
|
BOOL /*fReg*/,
|
|
LPSTR pszSubKey)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(pszPassword);
|
|
MYDBGASSERT(lpdwCryptType);
|
|
DWORD dwEncryptedBufferLen;
|
|
DWORD dwSize = 0;
|
|
|
|
LPTSTR pszEncryptedData = NULL;
|
|
TCHAR szSourceData[PWLEN + 1];
|
|
|
|
if (NULL == pArgs || NULL == pszPassword || NULL == lpdwCryptType)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Standard encryption, copy the password
|
|
//
|
|
|
|
lstrcpyU(szSourceData, pszPassword);
|
|
|
|
//
|
|
// It is not safe to call InitSecure more than once
|
|
//
|
|
if (!pArgs->fInitSecureCalled)
|
|
{
|
|
pArgs->fInitSecureCalled = TRUE;
|
|
InitSecure(FALSE); // don't use fast encryption anymore
|
|
}
|
|
|
|
//
|
|
// Encrypt the provided password
|
|
//
|
|
|
|
if (EncryptData(
|
|
(LPBYTE)szSourceData,
|
|
(lstrlenU(szSourceData)+1) * sizeof(TCHAR),
|
|
(LPBYTE*)&pszEncryptedData,
|
|
&dwEncryptedBufferLen,
|
|
lpdwCryptType,
|
|
#if defined(DEBUG) && defined(DEBUG_MEM)
|
|
(PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
|
|
(PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
|
|
#else
|
|
(PFN_CMSECUREALLOC)CmMalloc,
|
|
(PFN_CMSECUREFREE)CmFree,
|
|
pszSubKey))
|
|
#endif
|
|
{
|
|
if (lpdwBufSize)
|
|
{
|
|
*lpdwBufSize = dwEncryptedBufferLen;
|
|
}
|
|
}
|
|
|
|
MYDBGASSERT(pszEncryptedData);
|
|
|
|
CmWipePassword(szSourceData);
|
|
return pszEncryptedData;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: DecryptPassword
|
|
//
|
|
// Synopsis: Wrapper to decrypt password
|
|
//
|
|
// Arguments: ArgsStruct *pArgs - Ptr to global args struct
|
|
// LPCTSTR pszEncryptedData - The encrypted data
|
|
// DWORD dwEncryptionType - The encryption type of the data
|
|
// BOOL fReg - Password is disguised for registry storage
|
|
//
|
|
// Returns: LPTSTR - Ptr to a buffer containing the decrypted form of the password.
|
|
//
|
|
// History: nickball Created 5/22/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPBYTE DecryptPassword(
|
|
ArgsStruct *pArgs,
|
|
LPBYTE pszEncryptedData,
|
|
DWORD dwEncryptionType,
|
|
DWORD dwEncryptedBytes,
|
|
BOOL /*fReg*/,
|
|
LPSTR pszSubKey)
|
|
{
|
|
MYDBGASSERT(pArgs);
|
|
MYDBGASSERT(pszEncryptedData);
|
|
|
|
DWORD dwDecryptedBufferLen;
|
|
LPBYTE pszDecryptedData = NULL;
|
|
|
|
if (NULL == pArgs || NULL == pszEncryptedData)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// It is not safe to call InitSecure more than once
|
|
//
|
|
|
|
if (!pArgs->fInitSecureCalled)
|
|
{
|
|
pArgs->fInitSecureCalled = TRUE;
|
|
InitSecure(FALSE); // don't use fast encryption anymore
|
|
}
|
|
|
|
if (DecryptData(pszEncryptedData, dwEncryptedBytes, &pszDecryptedData, &dwDecryptedBufferLen,
|
|
dwEncryptionType,
|
|
#if defined(DEBUG) && defined(DEBUG_MEM)
|
|
(PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
|
|
(PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
|
|
#else
|
|
(PFN_CMSECUREALLOC)CmMalloc,
|
|
(PFN_CMSECUREFREE)CmFree,
|
|
pszSubKey))
|
|
#endif
|
|
{
|
|
return pszDecryptedData;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+----------------------------------------------------------------------------
|
|
//
|
|
// Function: TranslateUserDataID
|
|
//
|
|
// Synopsis: Wrapper to map user data ID to string name of .CMP entry
|
|
//
|
|
// Arguments: UINT uiDataID - UserInfo data ID to be translated
|
|
//
|
|
// Returns: LPCTSTR - Ptr to a constant containing the .CMP entry flag
|
|
//
|
|
// History: nickball Created 10/13/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
LPCTSTR TranslateUserDataID(UINT uiDataID)
|
|
{
|
|
switch(uiDataID)
|
|
{
|
|
|
|
case UD_ID_USERNAME:
|
|
return c_pszCmEntryUserName;
|
|
break;
|
|
|
|
case UD_ID_INET_USERNAME:
|
|
return c_pszCmEntryInetUserName;
|
|
break;
|
|
|
|
case UD_ID_DOMAIN:
|
|
return c_pszCmEntryDomain;
|
|
break;
|
|
|
|
case UD_ID_PASSWORD:
|
|
return c_pszCmEntryPassword;
|
|
break;
|
|
|
|
case UD_ID_INET_PASSWORD:
|
|
return c_pszCmEntryInetPassword;
|
|
break;
|
|
|
|
case UD_ID_NOPROMPT:
|
|
return c_pszCmEntryNoPrompt;
|
|
break;
|
|
|
|
case UD_ID_REMEMBER_PWD:
|
|
return c_pszCmEntryRememberPwd;
|
|
break;
|
|
|
|
case UD_ID_REMEMBER_INET_PASSWORD:
|
|
return c_pszCmEntryRememberInetPwd;
|
|
break;
|
|
|
|
case UD_ID_PCS:
|
|
return c_pszCmEntryPcs;
|
|
break;
|
|
|
|
case UD_ID_ACCESSPOINTENABLED:
|
|
return c_pszCmEntryAccessPointsEnabled;
|
|
break;
|
|
|
|
case UD_ID_CURRENTACCESSPOINT:
|
|
return c_pszCmEntryCurrentAccessPoint;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
MYDBGASSERT(FALSE);
|
|
return NULL;
|
|
} |