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.
 
 
 
 
 
 

711 lines
19 KiB

/**********************************************************************/
/** Microsoft Passport **/
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
/**********************************************************************/
/*
Passport.cpp
FILE HISTORY:
*/
// Passport.cpp : Implementation of DLL Exports.
// Note: Proxy/Stub Information
// To build a separate proxy/stub DLL,
// run nmake -f Passportps.mk in the project directory.
#include "stdafx.h"
#include <atlbase.h>
#include "resource.h"
#include <initguid.h>
#include "Passport.h"
#include "Passport_i.c"
#include "Admin.h"
#include "Ticket.h"
#include "Profile.h"
#include "Manager.h"
#include "PassportCrypt.h"
#include "PassportFactory.h"
#include "PassportLock.hpp"
#include "PassportEvent.hpp"
#include "FastAuth.h"
#include "RegistryConfig.h"
#include "commd5.h"
#include <shlguid.h>
#include <shlobj.h> // IShellLink
#define IS_DOT_NET_SERVER() (LOWORD(GetVersion()) >= 0x0105)
#define PASSPORT_DIRECTORY L"MicrosoftPassport"
#define PASSPORT_DIRECTORY_LEN (sizeof(PASSPORT_DIRECTORY) / sizeof(WCHAR) - 1)
#define NT_PARTNER_FILE L"msppptnr.xml"
#define NT_PARTNER_FILE_LEN (sizeof(NT_PARTNER_FILE) / sizeof(WCHAR) - 1)
#define WEB_PARTNER_FILE L"partner2.xml"
#define WEB_PARTNER_FILE_LEN (sizeof(WEB_PARTNER_FILE) / sizeof(WCHAR) - 1)
#define CONFIG_UTIL_NAME L"\\msppcnfg.exe"
#define CONFIG_UTIL_NAME_LEN (sizeof(CONFIG_UTIL_NAME) / sizeof(WCHAR) - 1)
#define SHORTCUT_SUFFIX_NAME L"\\Programs\\Microsoft Passport\\Passport Administration Utility.lnk"
#define SHORTCUT_SUFFIX_NAME_LEN (sizeof(SHORTCUT_SUFFIX_NAME) / sizeof(WCHAR) - 1)
HINSTANCE hInst;
CComModule _Module;
CPassportConfiguration *g_config=NULL;
// CProfileSchema *g_authSchema = NULL;
BOOL g_bStarted = FALSE;
BOOL g_bRegistering = FALSE;
PassportAlertInterface* g_pAlert = NULL;
PassportPerfInterface* g_pPerf = NULL;
static CComPtr<IMD5> g_spCOMmd5;
//===========================================================================
//
// GetGlobalCOMmd5
//
HRESULT GetGlobalCOMmd5(IMD5 ** ppMD5)
{
HRESULT hr = S_OK;
if (!ppMD5)
{
return E_INVALIDARG;
}
if(!g_spCOMmd5)
{
hr = CoCreateInstance(__uuidof(CoMD5),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IMD5),
(void**)ppMD5);
*ppMD5 = (IMD5*) ::InterlockedExchangePointer((void**) &g_spCOMmd5, (void*) *ppMD5);
}
if (*ppMD5 == NULL && g_spCOMmd5 != NULL)
{
*ppMD5 = g_spCOMmd5;
(*ppMD5)->AddRef();
}
return hr;
};
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Manager, CManager)
OBJECT_ENTRY(CLSID_Ticket, CTicket)
OBJECT_ENTRY(CLSID_Profile, CProfile)
OBJECT_ENTRY(CLSID_Crypt, CCrypt)
OBJECT_ENTRY(CLSID_Admin, CAdmin)
OBJECT_ENTRY(CLSID_FastAuth, CFastAuth)
OBJECT_ENTRY(CLSID_PassportFactory, CPassportFactory)
END_OBJECT_MAP()
// {{2D2B36FC-EB86-4e5c-9A06-20303542CCA3}
static const GUID CLSID_Manager_ALT =
{ 0x2D2B36FC, 0xEB86, 0x4e5c, { 0x9A, 0x06, 0x20, 0x30, 0x35, 0x42, 0xCC, 0xA3 } };
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
hInst = hInstance;
// gmarks
// Initialize the Alert object
if(!g_pAlert)
{
g_pAlert = CreatePassportAlertObject(PassportAlertInterface::EVENT_TYPE);
if(g_pAlert)
{
g_pAlert->initLog(PM_ALERTS_REGISTRY_KEY, EVCAT_PM, NULL, 1);
}
}
if(g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE, PM_STARTED);
}
//
// Initialize the logging stuff
//
InitLogging();
// gmarks
// Initialize the Perf object
if(!g_pPerf)
{
g_pPerf = CreatePassportPerformanceObject(PassportPerfInterface::PERFMON_TYPE);
if(g_pPerf)
{
// Initialize.
g_pPerf->init(PASSPORT_PERF_BLOCK);
}
}
_Module.Init(ObjectMap, hInstance, &LIBID_PASSPORTLib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// gmarks
if(g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE, PM_STOPPED);
g_pAlert->closeLog();
delete g_pAlert;
}
CloseLogging();
if(g_pPerf)
{
delete g_pPerf;
}
if (g_config)
{
delete g_config;
}
g_config = NULL;
_Module.Term();
}
return TRUE; // ok
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
HRESULT hr = (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
if( hr == S_OK)
{
g_spCOMmd5.Release();
if (g_config)
{
delete g_config;
}
g_config = NULL;
g_bStarted = FALSE;
}
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
HRESULT hr;
GUID guidCLSID;
static PassportLock startLock;
if(!g_bStarted)
{
PassportGuard<PassportLock> g(startLock);
if(!g_bStarted)
{
g_config = new CPassportConfiguration();
if (!g_config)
{
hr = CLASS_E_CLASSNOTAVAILABLE;
goto Cleanup;
}
g_config->UpdateNow(FALSE);
g_bStarted = TRUE;
}
}
if (InlineIsEqualGUID(rclsid, CLSID_Manager_ALT))
{
guidCLSID = CLSID_Manager;
}
else
{
guidCLSID = rclsid;
}
hr = _Module.GetClassObject(guidCLSID, riid, ppv);
Cleanup:
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// UpdateConfigShortcut - Checks if a shortcut exists for msppcnfg and if so
// updates the shortcut to point to the config utility
// is %WINDIR%\system32.
BOOL UpdateConfigShortcut(WCHAR *pszSystemDir)
{
WCHAR pszConfigUtilPath[MAX_PATH];
WCHAR pszShortcutPath[MAX_PATH];
IShellLink* pShellLink = NULL;
IPersistFile* pPersistFile = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
HRESULT hr;
BOOL fResult = FALSE;
// from the path to the shortcut
hr = SHGetFolderPath(NULL,
ssfCOMMONSTARTMENU,
NULL,
SHGFP_TYPE_DEFAULT,
pszShortcutPath);
if (S_OK != hr)
{
goto Cleanup;
}
wcsncat(pszShortcutPath, SHORTCUT_SUFFIX_NAME, MAX_PATH - wcslen(pszShortcutPath));
// determine if an existing shortcut exists
hFile = CreateFile(pszShortcutPath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
// form the path for the new config utility in system32
wcsncpy(pszConfigUtilPath, pszSystemDir, MAX_PATH);
pszConfigUtilPath[MAX_PATH - 1] = L'\0';
wcsncat(pszConfigUtilPath, CONFIG_UTIL_NAME, MAX_PATH - wcslen(pszConfigUtilPath));
// Get a pointer to the IShellLink interface.
hr = CoCreateInstance(CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
IID_IShellLink,
(LPVOID*)&pShellLink);
if (S_OK == hr)
{
// Query IShellLink for the IPersistFile interface for saving the shortcut in persistent storage.
hr = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
if (S_OK != hr)
{
goto Cleanup;
}
// load the shortcut file
hr = pPersistFile->Load(pszShortcutPath, STGM_READWRITE);
if (S_OK != hr)
{
goto Cleanup;
}
// Set the path to the shortcut target, and add the description.
hr = pShellLink->SetPath(pszConfigUtilPath);
if (S_OK != hr)
{
goto Cleanup;
}
hr = pPersistFile->Save(pszShortcutPath, TRUE);
if (S_OK != hr)
{
goto Cleanup;
}
}
}
fResult = TRUE;
Cleanup:
if (pPersistFile)
{
pPersistFile->Release();
}
if (pShellLink)
{
pShellLink->Release();
}
return fResult;
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
HRESULT hr;
IPassportAdmin* pIPassportManager = NULL;
BSTR key;
VARIANT_BOOL foo = 0;
WCHAR wszOldFile[MAX_PATH];
WCHAR wszNewFile[MAX_PATH];
UINT uRet;
HKEY hKey = 0;
HKEY hPPKey = 0;
BOOL fCoInitialized = FALSE;
DWORD dwType;
DWORD cbKeyData = 0;
DWORD dwSecureLevel;
LONG err;
//
// Prevent CRegistryConfig class from logging "config's bad" errors
// until the config should actually be there.
//
g_bRegistering = TRUE;
//
// registers object, typelib and all interfaces in typelib
//
hr = _Module.RegisterServer(TRUE);
if (FAILED(hr))
{
g_bRegistering = FALSE;
return hr;
}
//
// Stuff below this point is handled by the Passport SDK
// installation on non-.NET (or beyond) servers.
//
if (!IS_DOT_NET_SERVER())
{
goto Cleanup;
}
//
// Create the encrypted partner key.
//
::CoInitialize(NULL);
fCoInitialized = TRUE;
hr = ::CoCreateInstance(CLSID_Admin,
NULL,
CLSCTX_INPROC_SERVER,
IID_IPassportAdmin,
(void**) &pIPassportManager);
if (hr != S_OK)
{
goto Cleanup;
}
//
// check if there is already key data and if so, leave it alone
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Passport\\KeyData",
0,
KEY_QUERY_VALUE,
&hKey)
!= ERROR_SUCCESS)
{
goto Cleanup;
}
err = RegQueryValueEx(hKey,
L"1",
0,
&dwType,
NULL,
&cbKeyData);
RegCloseKey(hKey);
hKey = 0;
if (ERROR_FILE_NOT_FOUND == err)
{
key = SysAllocString(L"123456781234567812345678");
hr = (pIPassportManager->addKey(key, 1, 0, &foo));
SysFreeString(key);
if (hr != S_OK)
{
goto Cleanup;
}
}
hr = (pIPassportManager->put_currentKeyVersion(1));
if (hr != S_OK)
{
goto Cleanup;
}
//
// Create/set the CCDPassword
//
hr = SetCCDPassword();
//
// First, get the Windows directory
//
uRet = GetSystemDirectory(wszOldFile, MAX_PATH);
if (uRet == 0 || uRet >= MAX_PATH ||
((MAX_PATH - uRet) <= (PASSPORT_DIRECTORY_LEN + WEB_PARTNER_FILE_LEN + 1)) ||
((MAX_PATH - uRet) <= NT_PARTNER_FILE_LEN))
{
goto Cleanup;
}
//
// The following call checks for a start up menu shortcut (would have been
// previously created by PP SDK and if it finds one then updates that
// shortcut.
//
UpdateConfigShortcut(wszOldFile);
//
// partner2.xml is designed to be updated via the web. However, the NT version of
// that XML file is msppptnr.xml, which is in the %windir% and protected by SFP. As
// such, copy the out-of-the-box XML file to a location where it can be updated.
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Passport\\Nexus\\Partner",
0,
KEY_SET_VALUE | KEY_QUERY_VALUE,
&hKey)
!= ERROR_SUCCESS)
{
goto Cleanup;
}
err = RegQueryValueEx(hKey,
L"CCDLocalFile",
0,
&dwType,
NULL,
&cbKeyData);
if (ERROR_FILE_NOT_FOUND == err)
{
//
// Create the MicrosoftPassport subdirectory
//
wszOldFile[uRet++] = L'\\';
wszOldFile[uRet] = L'\0';
wcscpy(wszNewFile, wszOldFile);
wcscpy(wszNewFile + uRet, PASSPORT_DIRECTORY);
if (!CreateDirectory(wszNewFile, NULL) && (GetLastError() != ERROR_ALREADY_EXISTS))
{
goto Cleanup;
}
//
// Now, copy the file over -- don't fail if there's already a copy
// there but don't overwrite the existing file in that case.
//
wcscpy(wszOldFile + uRet, NT_PARTNER_FILE);
wszNewFile[uRet++ + PASSPORT_DIRECTORY_LEN] = L'\\';
wcscpy(wszNewFile + uRet + PASSPORT_DIRECTORY_LEN, WEB_PARTNER_FILE);
if (!CopyFile(wszOldFile, wszNewFile, TRUE) && (GetLastError() != ERROR_FILE_EXISTS))
{
goto Cleanup;
}
//
// The copy succeeded -- update CCDLocalFile to point at the new file
//
RegSetValueEx(hKey,
L"CCDLocalFile",
0,
REG_SZ,
(LPBYTE) wszNewFile,
(uRet + PASSPORT_DIRECTORY_LEN + 1 + WEB_PARTNER_FILE_LEN) * sizeof(WCHAR));
//
// In this case PP is assumed to have not been installed on the machine previously,
// so we want to set the secure level to 10 in this case. If PP is already on the
// box then we don't do this so we don't break upgrade cases.
//
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Passport",
0,
KEY_SET_VALUE,
&hPPKey)
!= ERROR_SUCCESS)
{
goto Cleanup;
}
//
// The copy succeeded -- update CCDLocalFile to point at the new file
//
dwSecureLevel = 10;
RegSetValueEx(hPPKey,
L"SecureLevel",
0,
REG_DWORD,
(LPBYTE)&dwSecureLevel,
sizeof(dwSecureLevel));
}
Cleanup:
if (hPPKey)
{
RegCloseKey(hPPKey);
}
if (hKey)
{
RegCloseKey(hKey);
}
if (pIPassportManager)
{
pIPassportManager->Release();
}
if (fCoInitialized)
{
::CoUninitialize();
}
g_bRegistering = FALSE;
return hr;
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// GetMyVersion - return a version string for use in query strings.
LPWSTR
GetVersionString(void)
{
static LONG s_lCallersIn = 0;
static WCHAR s_achVersionString[44] = L"";
static LPWSTR s_pszVersionString = NULL;
static PassportEvent s_Event;
TCHAR achFileBuf[_MAX_PATH];
LONG lCurrentCaller;
DWORD dwSize;
LPVOID lpVersionBuf = NULL;
VS_FIXEDFILEINFO* lpRoot;
UINT nRootLen;
if(s_pszVersionString == NULL)
{
lCurrentCaller = InterlockedIncrement(&s_lCallersIn);
if(lCurrentCaller == 1)
{
if (IS_DOT_NET_SERVER())
{
//
// The NT build uses different versioning for the binaries. Return the
// appropriate version for these sources as checked by the server.
//
wcscpy(s_achVersionString, L"2.1.6000.1");
}
else
{
//
// Pull the version off of the DLL itself -- first get the full path
//
if(GetModuleFileName(hInst, achFileBuf, sizeof(achFileBuf)/sizeof(TCHAR)) == 0)
goto Cleanup;
achFileBuf[_MAX_PATH - 1] = TEXT('\0');
if((dwSize = GetFileVersionInfoSize(achFileBuf, &dwSize)) == 0)
goto Cleanup;
lpVersionBuf = new BYTE[dwSize];
if(lpVersionBuf == NULL)
goto Cleanup;
if(GetFileVersionInfo(achFileBuf, 0, dwSize, lpVersionBuf) == 0)
goto Cleanup;
if(VerQueryValue(lpVersionBuf, TEXT("\\"), (LPVOID*)&lpRoot, &nRootLen) == 0)
goto Cleanup;
wsprintfW(s_achVersionString, L"%d.%d.%04d.%d",
(lpRoot->dwProductVersionMS & 0xFFFF0000) >> 16,
lpRoot->dwProductVersionMS & 0xFFFF,
(lpRoot->dwProductVersionLS & 0xFFFF0000) >> 16,
lpRoot->dwProductVersionLS & 0xFFFF);
}
s_pszVersionString = s_achVersionString;
s_Event.Set();
}
else
{
// Just wait to be signaled that we have the string.
WaitForSingleObject(s_Event, INFINITE);
}
InterlockedDecrement(&s_lCallersIn);
}
Cleanup:
if(lpVersionBuf)
delete [] lpVersionBuf;
return s_pszVersionString;
}