Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1161 lines
35 KiB

/**********************************************************************/
/** Microsoft Passport **/
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
/**********************************************************************/
/*
RegistryConfig.cpp
FILE HISTORY:
*/
// RegistryConfig.cpp: implementation of the CRegistryConfig class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegistryConfig.h"
#include "KeyCrypto.h"
#include "passport.h"
#include "keyver.h"
#include "dsysdbg.h"
extern BOOL g_bRegistering;
#define PASSPORT_KEY L"Software\\Microsoft\\Passport\\"
#define PASSPORT_SITES_SUBKEY L"Sites"
//===========================================================================
//
// Functions for verbose logging
//
// define for logging with dsysdbg.lib
DEFINE_DEBUG2(Passport);
DEBUG_KEY PassportDebugKeys[] = { {DEB_TRACE, "Trace"},
{0, NULL}
};
BOOL g_fLoggingOn = FALSE;
#define MAX_LOG_STRLEN 512
void PassportLog(CHAR* Format, ...)
{
if (g_fLoggingOn)
{
if (NULL != Format) {
SYSTEMTIME SysTime;
CHAR rgch[MAX_LOG_STRLEN];
int i, cch;
// put the time at the front
cch = sizeof(rgch) / sizeof(rgch[0]) - 1;
GetSystemTime(&SysTime);
i = GetDateFormatA (
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
0, // flags specifying function options
&SysTime, // date to be formatted
"ddd',' MMM dd yy ", // date format string
rgch, // buffer for storing formatted string
cch); // size of buffer
if (i > 0)
i--;
i += GetTimeFormatA (
LOCALE_USER_DEFAULT, // locale for which date is to be formatted
0, // flags specifying function options
&SysTime, // date to be formatted
"HH':'mm':'ss ", // time format string
rgch + i, // buffer for storing formatted string
cch - i); // size of buffer
if (i > 0)
i--;
va_list ArgList; \
va_start(ArgList, Format); \
_vsnprintf(rgch + i, cch - i, Format, ArgList);
rgch[MAX_LOG_STRLEN - 1] = '\0';
PassportDebugPrint(DEB_TRACE, rgch);
}
}
}
//
// This function opens the logging file. "%WINDIR%\system32\microsoftpassport\passport.log"
//
HANDLE OpenPassportLoggingFile()
{
WCHAR szLogPath[MAX_PATH + 13] = {0};
UINT cchMax = sizeof(szLogPath) / sizeof(szLogPath[0]) - 1;
UINT cch;
HANDLE hLogFile = INVALID_HANDLE_VALUE;
cch = GetWindowsDirectory(szLogPath, cchMax);
if ((0 == cch) || (cch > cchMax))
{
goto Cleanup;
}
if (NULL == wcsncat(szLogPath, L"\\system32\\microsoftpassport\\passport.log", cchMax - cch))
{
goto Cleanup;
}
szLogPath[MAX_PATH] = L'\0';
hLogFile = CreateFileW(szLogPath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL, //&sa,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hLogFile)
{
SetFilePointer(hLogFile, 0, NULL, FILE_END);
}
Cleanup:
return hLogFile;
}
//
// This function checks if logging is supposed to be enabled and if it is then
// it opens the log file and sets the appropriate global variables.
// If logging is supposed to be off then the appropriate variables are also
// changed to the correct values.
//
VOID CheckLogging(HKEY hPassport)
{
DWORD dwVerbose = 0;
DWORD cb = sizeof(DWORD);
HANDLE hLogFile = INVALID_HANDLE_VALUE;
// first run off and get the reg value, if this call fails we simply assume no logging
if (ERROR_SUCCESS == RegQueryValueExW(hPassport,
L"Verbose",
NULL,
NULL,
(LPBYTE)&dwVerbose,
&cb))
{
// only start logging if it is off and only stop logging if it's already on
if (!g_fLoggingOn && (0 != dwVerbose))
{
if (INVALID_HANDLE_VALUE != (hLogFile = OpenPassportLoggingFile()))
{
// set the logging file handle
PassportSetLoggingFile(hLogFile);
// set it to log to a file
PassportSetLoggingOption(TRUE);
g_fLoggingOn = TRUE;
PassportLog("Start Logging\r\n");
}
}
else if (g_fLoggingOn && (0 == dwVerbose))
{
PassportLog("Stop Logging\r\n");
PassportSetLoggingOption(FALSE);
g_fLoggingOn = FALSE;
}
}
}
void InitLogging()
{
//
// Initialize the logging stuff
//
PassportInitDebug(PassportDebugKeys);
PassportInfoLevel = DEB_TRACE;
}
void CloseLogging()
{
PassportUnloadDebug();
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
using namespace ATL;
//===========================================================================
//
// CRegistryConfig
//
CRegistryConfig::CRegistryConfig(
LPSTR szSiteName
) :
m_siteId(0), m_valid(FALSE), m_ticketPath(NULL), m_profilePath(NULL), m_securePath(NULL),
m_hostName(NULL), m_hostIP(NULL), m_ticketDomain(NULL), m_profileDomain(NULL), m_secureDomain(NULL),
m_disasterUrl(NULL), m_disasterMode(FALSE), m_forceLogin(FALSE), m_setCookies(TRUE),
m_szReason(NULL), m_refs(0), m_coBrand(NULL), m_ru(NULL), m_ticketAge(1800), m_bInDA(FALSE),
m_hkPassport(NULL), m_secureLevel(0),m_notUseHTTPOnly(0), m_pcrypts(NULL), m_pcryptValidTimes(NULL),
m_KPP(-1),m_NameSpace(NULL),m_ExtraParams(NULL)
{
// Get site id, key from registry
DWORD bufSize = sizeof(m_siteId);
LONG lResult;
HKEY hkSites = NULL;
DWORD dwBufSize = 0, disMode;
DWORD dwLCID;
//
// Record the current DLL state in case it changes
// partway through this routine.
//
BOOL fRegistering = g_bRegistering;
if(szSiteName)
{
lResult = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
PASSPORT_KEY PASSPORT_SITES_SUBKEY,
0,
KEY_READ,
&hkSites);
if(lResult != ERROR_SUCCESS)
{
m_valid = FALSE;
setReason(L"Invalid site name. Site not found.");
goto Cleanup;
}
lResult = RegOpenKeyExA(
hkSites,
szSiteName,
0,
KEY_READ,
&m_hkPassport);
if(lResult != ERROR_SUCCESS)
{
m_valid = FALSE;
setReason(L"Invalid site name. Site not found.");
goto Cleanup;
}
}
else
{
lResult = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
PASSPORT_KEY,
0,
KEY_READ,
&m_hkPassport
);
if(lResult != ERROR_SUCCESS)
{
m_valid = FALSE;
setReason(L"No RegKey HKLM\\SOFTWARE\\Microsoft\\Passport");
goto Cleanup;
}
}
// Get the current key
bufSize = sizeof(m_currentKey);
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("CurrentKey"),
NULL, NULL, (LPBYTE)&m_currentKey, &bufSize))
{
m_valid = FALSE;
setReason(L"No CurrentKey defined in the registry.");
goto Cleanup;
}
if(m_currentKey < KEY_VERSION_MIN || m_currentKey > KEY_VERSION_MAX)
{
m_valid = FALSE;
setReason(L"Invalid CurrentKey value in the registry.");
goto Cleanup;
}
// Get default LCID
bufSize = sizeof(dwLCID);
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("LanguageID"),
NULL, NULL, (LPBYTE)&dwLCID, &bufSize))
{
dwLCID = 0;
}
m_lcid = static_cast<short>(dwLCID & 0xFFFF);
// Get disaster mode status
bufSize = sizeof(disMode);
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("StandAlone"),
NULL, NULL, (LPBYTE)&disMode, &bufSize))
{
m_disasterMode = FALSE;
}
else if (disMode != 0)
{
m_disasterMode = TRUE;
}
// Get the disaster URL
if (m_disasterMode)
{
if (ERROR_SUCCESS == RegQueryValueEx(m_hkPassport,
_T("DisasterURL"),
NULL,
NULL,
NULL,
&dwBufSize)
&&
dwBufSize > 1)
{
m_disasterUrl = new WCHAR[dwBufSize];
if ((!m_disasterUrl)
||
ERROR_SUCCESS != RegQueryValueEx(m_hkPassport,
_T("DisasterURL"),
NULL,
NULL,
(LPBYTE) m_disasterUrl,
&dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading DisasterURL from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
else
{
m_valid = FALSE;
setReason(L"DisasterURL missing from registry.");
goto Cleanup;
}
}
//
// This function wraps the allocations of the crypt objects in a try/except
// since the objects themselves do a poor job in low memory conditions
//
try
{
m_pcrypts = new INT2CRYPT;
m_pcryptValidTimes = new INT2TIME;
}
catch(...)
{
m_valid = FALSE;
setReason(L"Out of memory.");
goto Cleanup;
}
if (!m_pcrypts || !m_pcryptValidTimes)
{
m_valid = FALSE;
setReason(L"Out of memory.");
goto Cleanup;
}
m_valid = readCryptoKeys(m_hkPassport);
if (!m_valid)
{
if (!m_szReason)
setReason(L"Error reading Passport crypto keys from registry.");
goto Cleanup;
}
if (m_pcrypts->count(m_currentKey) == 0)
{
m_valid = FALSE;
if (!m_szReason)
setReason(L"Error reading Passport crypto keys from registry.");
goto Cleanup;
}
// Get the optional default cobrand
if (ERROR_SUCCESS == RegQueryValueExW(m_hkPassport, L"CoBrandTemplate",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 2)
{
m_coBrand = (WCHAR*) new char[dwBufSize];
if (!m_coBrand
||
ERROR_SUCCESS != RegQueryValueExW(m_hkPassport, L"CoBrandTemplate",
NULL, NULL,
(LPBYTE) m_coBrand, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading CoBrand from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional default return URL
if (ERROR_SUCCESS == RegQueryValueExW(m_hkPassport, L"ReturnURL",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 2)
{
m_ru = (WCHAR*) new char[dwBufSize];
if (!m_ru
||
ERROR_SUCCESS != RegQueryValueExW(m_hkPassport, L"ReturnURL",
NULL, NULL,
(LPBYTE) m_ru, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading ReturnURL from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the host name
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "HostName",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_hostName = new char[dwBufSize];
if (m_hostName == NULL
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "HostName",
NULL, NULL,
(LPBYTE) m_hostName, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading HostName from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the host ip
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "HostIP",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_hostIP = new char[dwBufSize];
if (!m_hostIP
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "HostIP",
NULL, NULL,
(LPBYTE) m_hostIP, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading HostIP from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional domain to set ticket cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "TicketDomain",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_ticketDomain = new char[dwBufSize];
if (!m_ticketDomain
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "TicketDomain",
NULL, NULL,
(LPBYTE) m_ticketDomain, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading TicketDomain from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional domain to set profile cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "ProfileDomain",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_profileDomain = new char[dwBufSize];
if (!m_profileDomain
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "ProfileDomain",
NULL, NULL,
(LPBYTE) m_profileDomain, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading ProfileDomain from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional domain to set secure cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "SecureDomain",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_secureDomain = new char[dwBufSize];
if (!m_secureDomain
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "SecureDomain",
NULL, NULL,
(LPBYTE) m_secureDomain, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading SecureDomain from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional path to set ticket cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "TicketPath",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_ticketPath = new char[dwBufSize];
if (!m_ticketPath
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "TicketPath",
NULL, NULL,
(LPBYTE) m_ticketPath, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading TicketPath from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional path to set profile cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "ProfilePath",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_profilePath = new char[dwBufSize];
if (!m_profilePath
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "ProfilePath",
NULL, NULL,
(LPBYTE) m_profilePath, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading ProfilePath from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
// Get the optional path to set secure cookies into
if (ERROR_SUCCESS == RegQueryValueExA(m_hkPassport, "SecurePath",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 1)
{
m_securePath = new char[dwBufSize];
if (!m_securePath
||
ERROR_SUCCESS != RegQueryValueExA(m_hkPassport, "SecurePath",
NULL, NULL,
(LPBYTE) m_securePath, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading SecurePath from registry. (Query worked, but couldn't retrieve data)");
goto Cleanup;
}
}
}
bufSize = sizeof(m_siteId);
// Now get the site id
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("SiteId"),
NULL, NULL, (LPBYTE)&m_siteId, &bufSize))
{
m_valid = FALSE;
setReason(L"No SiteId specified in registry");
goto Cleanup;
}
// And the default ticket time window
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("TimeWindow"),
NULL, NULL, (LPBYTE)&m_ticketAge, &bufSize))
{
m_ticketAge = 1800;
}
bufSize = sizeof(DWORD);
DWORD forced;
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("ForceSignIn"),
NULL, NULL, (LPBYTE)&forced, &bufSize))
{
m_forceLogin = FALSE;
}
else
{
m_forceLogin = forced == 0 ? FALSE : TRUE;
}
bufSize = sizeof(DWORD);
DWORD noSetCookies;
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("DisableCookies"),
NULL, NULL, (LPBYTE)&noSetCookies, &bufSize))
{
m_setCookies = TRUE;
}
else
{
m_setCookies = !noSetCookies;
}
bufSize = sizeof(DWORD);
DWORD dwInDA;
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("InDA"),
NULL, NULL, (LPBYTE)&dwInDA, &bufSize))
{
m_bInDA = FALSE;
}
else
{
m_bInDA = (dwInDA != 0);
}
bufSize = sizeof(m_secureLevel);
// Now get the site id
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("SecureLevel"),
NULL, NULL, (LPBYTE)&m_secureLevel, &bufSize))
{
m_secureLevel = 0;
}
bufSize = sizeof(m_notUseHTTPOnly);
// Now get the NotUseHTTPOnly
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("NotUseHTTPOnly"),
NULL, NULL, (LPBYTE)&m_notUseHTTPOnly, &bufSize))
{
m_notUseHTTPOnly = 0;
}
// Get the KPP value
bufSize = sizeof(m_KPP);
if (ERROR_SUCCESS != RegQueryValueEx(m_hkPassport, _T("KPP"),
NULL, NULL, (LPBYTE)&m_KPP, &bufSize))
{
m_KPP = -1;
}
// Get the optional namespace
if (ERROR_SUCCESS == RegQueryValueExW(m_hkPassport, L"NameSpace",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 2)
{
m_NameSpace = (WCHAR*) new char[dwBufSize];
if (!m_NameSpace
||
ERROR_SUCCESS != RegQueryValueExW(m_hkPassport, L"NameSpace",
NULL, NULL,
(LPBYTE) m_NameSpace, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading NameSpace from registry.");
goto Cleanup;
}
}
}
// Get the optional extra parameters
if (ERROR_SUCCESS == RegQueryValueExW(m_hkPassport, L"ExtraParams",
NULL, NULL, NULL, &dwBufSize))
{
if (dwBufSize > 2)
{
m_ExtraParams = (WCHAR*) new char[dwBufSize];
if (!m_ExtraParams
||
ERROR_SUCCESS != RegQueryValueExW(m_hkPassport, L"ExtraParams",
NULL, NULL,
(LPBYTE) m_ExtraParams, &dwBufSize))
{
m_valid = FALSE;
setReason(L"Error reading ExtraParams from registry.");
goto Cleanup;
}
}
}
//
// Check for the verbose flag in the registry and do the appropriate stuff to either
// turn logging on or off.
//
// Only check if this is the default site.
//
if (!szSiteName)
{
CheckLogging(m_hkPassport);
}
m_szReason = NULL;
m_valid = TRUE;
Cleanup:
if ( NULL != hkSites )
{
RegCloseKey(hkSites);
}
if (m_valid == FALSE && !fRegistering)
{
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
PM_INVALID_CONFIGURATION, m_szReason);
}
return;
}
//===========================================================================
//
// ~CRegistryConfig
//
CRegistryConfig::~CRegistryConfig()
{
if (m_pcrypts)
{
if (!m_pcrypts->empty())
{
INT2CRYPT::iterator itb = m_pcrypts->begin();
for (; itb != m_pcrypts->end(); itb++)
{
delete itb->second;
}
m_pcrypts->clear();
}
delete m_pcrypts;
}
// may be a leak that we don't iterate through and delete the elements
if (m_pcryptValidTimes)
{
delete m_pcryptValidTimes;
}
if (m_szReason)
SysFreeString(m_szReason);
if (m_ticketDomain)
delete[] m_ticketDomain;
if (m_profileDomain)
delete[] m_profileDomain;
if (m_secureDomain)
delete[] m_secureDomain;
if (m_ticketPath)
delete[] m_ticketPath;
if (m_profilePath)
delete[] m_profilePath;
if (m_securePath)
delete[] m_securePath;
if (m_disasterUrl)
delete[] m_disasterUrl;
if (m_coBrand)
delete[] m_coBrand;
if (m_hostName)
delete[] m_hostName;
if (m_hostIP)
delete[] m_hostIP;
if (m_ru)
delete[] m_ru;
if (m_NameSpace)
delete[] m_NameSpace;
if (m_ExtraParams)
delete[] m_ExtraParams;
if (m_hkPassport != NULL)
{
RegCloseKey(m_hkPassport);
}
}
//===========================================================================
//
// GetCurrentConfig
//
#define __MAX_STRING_LENGTH__ 1024
HRESULT CRegistryConfig::GetCurrentConfig(LPCWSTR name, VARIANT* pVal)
{
if(m_hkPassport == NULL || !m_valid)
{
AtlReportError(CLSID_Profile, PP_E_SITE_NOT_EXISTSSTR,
IID_IPassportProfile, PP_E_SITE_NOT_EXISTS);
return PP_E_SITE_NOT_EXISTS;
}
if(!name || !pVal) return E_INVALIDARG;
HRESULT hr = S_OK;
BYTE *pBuf = NULL;
ATL::CComVariant v;
BYTE dataBuf[__MAX_STRING_LENGTH__];
DWORD bufLen = sizeof(dataBuf);
BYTE *pData = dataBuf;
DWORD dwErr = ERROR_SUCCESS;
DWORD dataType = 0;
dwErr = RegQueryValueEx(m_hkPassport, name, NULL, &dataType, (LPBYTE)pData, &bufLen);
if (dwErr == ERROR_MORE_DATA)
{
pBuf = (PBYTE)malloc(bufLen);
if (!pBuf)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pData = pBuf;
dwErr = RegQueryValueEx(m_hkPassport, name, NULL, &dataType, (LPBYTE)pData, &bufLen);
}
if (dwErr != ERROR_SUCCESS)
{
hr = PP_E_NO_ATTRIBUTE;
AtlReportError(CLSID_Manager, PP_E_NO_ATTRIBUTESTR,
IID_IPassportManager3, PP_E_NO_ATTRIBUTE);
}
else
{
switch(dataType)
{
case REG_DWORD:
case REG_DWORD_BIG_ENDIAN:
{
DWORD* pdw = (DWORD*)pData;
v = (long)*pdw;
}
break;
case REG_SZ:
case REG_EXPAND_SZ:
{
LPCWSTR pch = (LPCWSTR)pData;
v = (LPCWSTR)pch;
}
break;
default:
AtlReportError(CLSID_Manager, PP_E_TYPE_NOT_SUPPORTEDSTR,
IID_IPassportManager, PP_E_TYPE_NOT_SUPPORTED);
hr = PP_E_TYPE_NOT_SUPPORTED;
break;
}
}
Exit:
if(pBuf)
free(pBuf);
if (hr == S_OK)
hr = v.Detach(pVal);
return hr;
}
#define MAX_ENCKEYSIZE 1024
//===========================================================================
//
// readCryptoKeys
//
BOOL CRegistryConfig::readCryptoKeys(
HKEY hkPassport
)
{
LONG lResult;
BOOL retVal = FALSE;
HKEY hkDataKey = NULL, hkTimeKey = NULL;
DWORD iterIndex = 0, keySize, keyTime, keyNumSize;
BYTE encKeyBuf[MAX_ENCKEYSIZE];
int kNum;
TCHAR szKeyNum[4];
CKeyCrypto kc;
int foundKeys = 0;
HANDLE hToken = NULL;
if (OpenThreadToken(GetCurrentThread(),
MAXIMUM_ALLOWED,
TRUE,
&hToken))
{
if (FALSE == RevertToSelf())
{
setReason(L"Unable to revert to self");
goto Cleanup;
}
}
// Open both the keydata and keytimes key,
// if there's no keytimes key, we'll assume all keys are valid forever,
// or more importantly, we won't break if that key isn't there
lResult = RegOpenKeyEx(hkPassport, TEXT("KeyData"), 0,
KEY_READ, &hkDataKey);
if(lResult != ERROR_SUCCESS)
{
setReason(L"No Valid Crypto Keys");
goto Cleanup;
}
RegOpenKeyEx(hkPassport, TEXT("KeyTimes"), 0,
KEY_READ, &hkTimeKey);
// Ok, now enumerate the KeyData keys and create crypt objects
while (1)
{
keySize = sizeof(encKeyBuf);
keyNumSize = sizeof(szKeyNum) >> (sizeof(TCHAR) - 1);
lResult = RegEnumValue(hkDataKey, iterIndex++, szKeyNum,
&keyNumSize, NULL, NULL, (LPBYTE)&(encKeyBuf[0]), &keySize);
if (lResult != ERROR_SUCCESS)
{
break;
}
kNum = KeyVerC2I(szKeyNum[0]);
if (kNum > 0)
{
DATA_BLOB iBlob;
DATA_BLOB oBlob = {0};
iBlob.cbData = keySize;
iBlob.pbData = (LPBYTE)&(encKeyBuf[0]);
if(kc.decryptKey(&iBlob, &oBlob) != S_OK)
{
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
PM_CANT_DECRYPT_CONFIG);
break;
}
else
{
// Now set up a crypt object
CCoCrypt* cr = new CCoCrypt();
if (NULL == cr)
{
if(oBlob.pbData)
{
RtlSecureZeroMemory(oBlob.pbData, oBlob.cbData);
::LocalFree(oBlob.pbData);
ZeroMemory(&oBlob, sizeof(oBlob));
}
setReason(L"Out of memory");
goto Cleanup;
}
BSTR km = ::SysAllocStringByteLen((LPSTR)oBlob.pbData, oBlob.cbData);
if (NULL == km)
{
if(oBlob.pbData)
{
RtlSecureZeroMemory(oBlob.pbData, oBlob.cbData);
::LocalFree(oBlob.pbData);
ZeroMemory(&oBlob, sizeof(oBlob));
}
delete cr;
setReason(L"Out of memory");
goto Cleanup;
}
cr->setKeyMaterial(km);
::SysFreeString(km);
if(oBlob.pbData)
{
RtlSecureZeroMemory(oBlob.pbData, oBlob.cbData);
::LocalFree(oBlob.pbData);
ZeroMemory(&oBlob, sizeof(oBlob));
}
// Add it to the bucket...
// wrap the STL calls since in low memory conditions they can AV
try
{
INT2CRYPT::value_type pMapVal(kNum, cr);
m_pcrypts->insert(pMapVal);
}
catch(...)
{
setReason(L"Out of memory");
goto Cleanup;
}
foundKeys++;
keySize = sizeof(DWORD);
if (RegQueryValueEx(hkTimeKey, szKeyNum, NULL,NULL,(LPBYTE)&keyTime,&keySize) ==
ERROR_SUCCESS && (m_currentKey != kNum))
{
// wrap the STL calls since in low memory conditions they can AV
try
{
INT2TIME::value_type pTimeVal(kNum, keyTime);
m_pcryptValidTimes->insert(pTimeVal);
}
catch(...)
{
setReason(L"Out of memory");
goto Cleanup;
}
}
}
}
if (iterIndex > 100) // Safety latch
goto Cleanup;
}
retVal = foundKeys > 0 ? TRUE : FALSE;
Cleanup:
if (hToken)
{
// put the impersonation token back
if (!SetThreadToken(NULL, hToken))
{
setReason(L"Unable to set thread token");
retVal = FALSE;
}
CloseHandle(hToken);
}
if (hkDataKey)
RegCloseKey(hkDataKey);
if (hkTimeKey)
RegCloseKey(hkTimeKey);
return retVal;
}
//===========================================================================
//
// getCrypt
//
CCoCrypt* CRegistryConfig::getCrypt(int keyNum, time_t* validUntil)
{
if (validUntil) // If they asked for the validUntil information
{
INT2TIME::const_iterator timeIt = m_pcryptValidTimes->find(keyNum);
if (timeIt == m_pcryptValidTimes->end())
*validUntil = 0;
else
*validUntil = (*timeIt).second;
}
// Now look up the actual crypt object
INT2CRYPT::const_iterator it = m_pcrypts->find(keyNum);
if (it == m_pcrypts->end())
return NULL;
return (*it).second;
}
//===========================================================================
//
// getFailureString
//
BSTR CRegistryConfig::getFailureString()
{
if (m_valid)
return NULL;
return m_szReason;
}
//===========================================================================
//
// setReason
//
void CRegistryConfig::setReason(LPTSTR reason)
{
if (m_szReason)
SysFreeString(m_szReason);
m_szReason = SysAllocString(reason);
}
//===========================================================================
//
// AddRef
//
CRegistryConfig* CRegistryConfig::AddRef()
{
InterlockedIncrement(&m_refs);
return this;
}
//===========================================================================
//
// Release
//
void CRegistryConfig::Release()
{
long refs = InterlockedDecrement(&m_refs);
if (refs == 0)
delete this;
}
//===========================================================================
//
// GetHostName
//
long
CRegistryConfig::GetHostName(
LPSTR szSiteName,
LPSTR szHostName,
LPDWORD lpdwHostNameBufLen
)
{
long lResult;
HKEY hkSites = NULL;
HKEY hkPassport = NULL;
if(!szSiteName || szSiteName[0] == '\0')
{
lResult = E_UNEXPECTED;
goto Cleanup;
}
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
PASSPORT_KEY PASSPORT_SITES_SUBKEY,
0,
KEY_READ,
&hkSites
);
if(lResult != ERROR_SUCCESS)
goto Cleanup;
lResult = RegOpenKeyExA(hkSites,
szSiteName,
0,
KEY_READ,
&hkPassport
);
if(lResult != ERROR_SUCCESS)
goto Cleanup;
lResult = RegQueryValueExA(hkPassport,
"HostName",
NULL,
NULL,
(LPBYTE)szHostName,
lpdwHostNameBufLen
);
Cleanup:
if(hkSites != NULL)
RegCloseKey(hkSites);
if(hkPassport != NULL)
RegCloseKey(hkPassport);
return lResult;
}