|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: wvtver1.cpp
//
// Contents: Microsoft Internet Security WinVerifyTrust v1 support
//
// Functions: WintrustIsVersion1ActionID
// ConvertDataFromVersion1
//
// *** local functions ***
//
// History: 30-May-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "wvtver1.h"
BOOL WintrustIsVersion1ActionID(GUID *pgActionID) { GUID gV1UISup = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE; GUID gV1UINoBad = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI;
if ((memcmp(pgActionID, &gV1UISup, sizeof(GUID)) == 0) || (memcmp(pgActionID, &gV1UINoBad, sizeof(GUID)) == 0)) { return(TRUE); }
return(FALSE); }
WINTRUST_DATA *ConvertDataFromVersion1(HWND hWnd, GUID *pgActionID, WINTRUST_DATA *pWTDNew, WINTRUST_FILE_INFO *pWTFINew, LPVOID pWTDOld) { GUID gV1UINoBad = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI;
WCHAR *pwszFile; WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT *pActData;
pActData = (WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT *)pWTDOld;
memset(pWTDNew, 0x00, sizeof(WINTRUST_DATA)); pWTDNew->cbStruct = sizeof(WINTRUST_DATA); pWTDNew->dwUnionChoice = WTD_CHOICE_FILE; pWTDNew->pFile = pWTFINew;
memset(pWTFINew, 0x00, sizeof(WINTRUST_FILE_INFO)); pWTFINew->cbStruct = sizeof(WINTRUST_FILE_INFO);
if (!(pWTDOld)) { return(pWTDNew); }
pWTDNew->dwUIChoice = WTD_UI_ALL; pWTDNew->pPolicyCallbackData = pActData->hClientToken; pWTFINew->hFile = ((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->hFile;
if (memcmp(&gV1UINoBad, pgActionID, sizeof(GUID)) == 0) { pWTDNew->dwUIChoice = WTD_UI_NOBAD; }
if (hWnd == (HWND)(-1)) { pWTDNew->dwUIChoice = WTD_UI_NONE; }
pwszFile = (WCHAR *)((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->lpPath;
while ((*pwszFile) && (*pwszFile != '|')) { ++pwszFile; }
if (*pwszFile) { *pwszFile = NULL; }
pWTFINew->pcwszFilePath = (WCHAR *)((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->lpPath;
return(pWTDNew); }
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// the following code implements the version 1 style of calling trust providers.
//
// this code is ONLY implemented when a trust provider registers itself in the
// old location!
//
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
#define WIN_TRUST_MAJOR_REVISION_MASK 0xFFFF0000
#define WIN_TRUST_MINOR_REVISION_MASK 0x0000FFFF
#define WIN_TRUST_REVISION_1_0 0x00010000
#define REGISTRY_TRUSTPROVIDERS TEXT("System\\CurrentControlSet\\Services\\WinTrust\\TrustProviders")
#define REGISTRY_ROOT HKEY_LOCAL_MACHINE
#define ACTION_IDS TEXT("$ActionIDs")
#define DLL_NAME TEXT("$DLL")
#define IsEqualActionID( id1, id2) (!memcmp(id1, id2, sizeof(GUID)))
typedef struct _WINTRUST_CLIENT_TP_INFO { DWORD dwRevision; //LPWINTRUST_CLIENT_TP_DISPATCH_TABLE lpServices;
LPVOID lpServices; } WINTRUST_CLIENT_TP_INFO, *LPWINTRUST_CLIENT_TP_INFO;
typedef LONG (*LPWINTRUST_PROVIDER_VERIFY_TRUST) ( IN HWND hwnd, IN GUID * ActionID, IN LPVOID ActionData );
typedef VOID (*LPWINTRUST_PROVIDER_SUBMIT_CERTIFICATE) ( IN LPWIN_CERTIFICATE lpCertificate );
typedef VOID (*LPWINTRUST_PROVIDER_CLIENT_UNLOAD) ( IN LPVOID lpTrustProviderInfo );
typedef BOOL (*LPWINTRUST_PROVIDER_CLIENT_INITIALIZE)( IN DWORD dwWinTrustRevision, IN LPWINTRUST_CLIENT_TP_INFO lpWinTrustInfo, IN LPWSTR lpProviderName, LPVOID *lpTrustProviderInfo // OUT LPWINTRUST_PROVIDER_CLIENT_INFO *lpTrustProviderInfo
);
typedef struct _WINTRUST_PROVIDER_CLIENT_SERVICES { LPWINTRUST_PROVIDER_CLIENT_UNLOAD Unload; LPWINTRUST_PROVIDER_VERIFY_TRUST VerifyTrust; LPWINTRUST_PROVIDER_SUBMIT_CERTIFICATE SubmitCertificate;
} WINTRUST_PROVIDER_CLIENT_SERVICES, *LPWINTRUST_PROVIDER_CLIENT_SERVICES;
typedef struct _WINTRUST_PROVIDER_CLIENT_INFO { DWORD dwRevision; LPWINTRUST_PROVIDER_CLIENT_SERVICES lpServices; DWORD dwActionIdCount; GUID * lpActionIdArray; } WINTRUST_PROVIDER_CLIENT_INFO, *LPWINTRUST_PROVIDER_CLIENT_INFO;
typedef struct _LOADED_PROVIDER_V1 {
struct _LOADED_PROVIDER_V1 *Next; struct _LOADED_PROVIDER_V1 *Prev; HANDLE ModuleHandle; LPTSTR ModuleName; LPTSTR SubKeyName; LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo; DWORD RefCount; DWORD ProviderInitialized;
} LOADED_PROVIDER_V1, *PLOADED_PROVIDER_V1;
#define PROVIDER_INITIALIZATION_SUCCESS (1)
#define PROVIDER_INITIALIZATION_IN_PROGRESS (2)
#define PROVIDER_INITIALIZATION_FAILED (3)
PLOADED_PROVIDER_V1 WinTrustFindActionID(IN GUID * dwActionID); PLOADED_PROVIDER_V1 Version1_RegLoadProvider(HKEY hKey, LPTSTR KeyName, GUID *ActionID); PLOADED_PROVIDER_V1 Version1_LoadProvider(GUID *pgActionID); PLOADED_PROVIDER_V1 Version1_TestProviderForAction(HKEY hKey, LPTSTR KeyName, GUID * ActionID); void Version1_UnloadProvider(PLOADED_PROVIDER_V1 Provider);
LONG Version1_WinVerifyTrust(HWND hwnd, GUID *ActionID, LPVOID ActionData)
{ PLOADED_PROVIDER_V1 Provider; HRESULT rc;
if (!(Provider = Version1_LoadProvider(ActionID))) { return( TRUST_E_PROVIDER_UNKNOWN ); }
rc = (*Provider->ClientInfo->lpServices->VerifyTrust)( hwnd, ActionID, ActionData );
Version1_UnloadProvider(Provider);
return( rc ); }
PLOADED_PROVIDER_V1 Version1_LoadProvider(GUID *pgActionID) { HKEY hKey; // Handle to the base of the provider information.
HKEY hSubKey; // Handle to the provider currently being examined.
LONG Result; // Returned by registry API.
DWORD cSubKeys; // Number of providers under the root key.
DWORD cbMaxSubKeyLen; // Maximum provider name length.
ULONG i; // Indicies for iterating through providers and action IDs.
LPTSTR SubKeyName; // Points to the name of the current provider.
PLOADED_PROVIDER_V1 FoundProvider = NULL;
//
// Open the registry and get a list of installed trust providers
//
Result = RegOpenKeyEx( REGISTRY_ROOT, REGISTRY_TRUSTPROVIDERS, 0L, GENERIC_READ, &hKey );
if (Result != ERROR_SUCCESS) { return( NULL ); }
//
// Find out how many subkeys there are.
//
Result = RegQueryInfoKey ( hKey, // handle of key to query
NULL, // address of buffer for class string
NULL, // address of size of class string buffer
NULL, // reserved
&cSubKeys, // address of buffer for number of subkeys
&cbMaxSubKeyLen, // address of buffer for longest subkey name length
NULL, // address of buffer for longest class string length
NULL, // address of buffer for number of value entries
NULL, // address of buffer for longest value name length
NULL, // address of buffer for longest value data length
NULL, // address of buffer for security descriptor length
NULL // address of buffer for last write time
);
if (ERROR_SUCCESS != Result) { RegCloseKey( hKey ); return( NULL ); }
//
// Iterate through the subkeys, looking for ones with hint information.
//
cbMaxSubKeyLen += sizeof( WCHAR );
SubKeyName = new char[cbMaxSubKeyLen + 1];
if (NULL == SubKeyName) { RegCloseKey( hKey ); return(NULL); }
for (i=0; i<cSubKeys; i++) {
DWORD KeyNameLength;
KeyNameLength = cbMaxSubKeyLen;
Result = RegEnumKeyEx( hKey, // handle of key to enumerate
i, // index of subkey to enumerate
SubKeyName, // address of buffer for subkey name
&KeyNameLength, // address for size of subkey buffer
NULL, // reserved
NULL, // address of buffer for class string
NULL, // address for size of class buffer
NULL // address for time key last written to
);
//
// Not much to do if this fails, try enumerating the rest of them and see
// what happens.
//
if (Result != ERROR_SUCCESS) { continue; }
Result = RegOpenKeyEx( hKey, SubKeyName, 0L, GENERIC_READ | MAXIMUM_ALLOWED, &hSubKey );
if (ERROR_SUCCESS != Result) { continue; }
FoundProvider = Version1_TestProviderForAction( hSubKey, SubKeyName, pgActionID );
RegCloseKey( hSubKey );
if (NULL != FoundProvider) {
//
// Got one. Clean up and return.
//
delete SubKeyName; RegCloseKey( hKey ); return( FoundProvider ); }
continue; }
delete SubKeyName; RegCloseKey( hKey ); return( NULL ); }
WINTRUST_CLIENT_TP_INFO WinTrustClientTPInfo = { WIN_TRUST_REVISION_1_0, NULL };
PLOADED_PROVIDER_V1 Version1_TestProviderForAction(HKEY hKey, LPTSTR KeyName, GUID * ActionID) { PLOADED_PROVIDER_V1 Provider; LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo; GUID * ActionIds; DWORD i;
Provider = Version1_RegLoadProvider( hKey, KeyName, ActionID);
if (NULL == Provider) { return( NULL ); }
ClientInfo = Provider->ClientInfo;
ActionIds = ClientInfo->lpActionIdArray;
for (i=0; i<ClientInfo->dwActionIdCount; i++) {
if (IsEqualActionID(ActionID, &ActionIds[i])) { return( Provider ); } }
return(NULL); }
PLOADED_PROVIDER_V1 Version1_RegLoadProvider(HKEY hKey, LPTSTR KeyName, GUID *ActionID) { LPTSTR ModuleName = NULL; HINSTANCE LibraryHandle = NULL; LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo = NULL; PLOADED_PROVIDER_V1 Provider = NULL; LPWSTR ProviderName = NULL; LPTSTR SubKeyName = NULL;
GUID gBuffer[10]; // Assume no more than 10 action ids in a provider
DWORD Type; DWORD cbData = 0; LONG Result; LPWINTRUST_PROVIDER_CLIENT_INITIALIZE ProcAddr; DWORD size; BOOL Inited;
//
// get the guids
//
cbData = sizeof(GUID) * 10; Result = RegQueryValueEx( hKey, // handle of key to query
TEXT("$ActionIDs"), NULL, // reserved
&Type, // address of buffer for value type
(BYTE *)&gBuffer[0], &cbData // address of data buffer size
);
if (Result != ERROR_SUCCESS) { return(NULL); }
//
// check the guids
//
Inited = FALSE; for (int j = 0; j < (int)(cbData / sizeof(GUID)); j++) { if (memcmp(&gBuffer[j], ActionID, sizeof(GUID)) == 0) { Inited = TRUE; break; } }
if (!(Inited)) { return(NULL); }
//
// Extract the dll name from the $DLL value
//
Result = RegQueryValueEx( hKey, // handle of key to query
TEXT("$DLL"), // address of name of value to query
NULL, // reserved
&Type, // address of buffer for value type
NULL, // address of data buffer
&cbData // address of data buffer size
);
// if (ERROR_MORE_DATA != Result) {
// goto error_cleanup;
// }
if (ERROR_SUCCESS != Result) { goto error_cleanup; }
cbData += sizeof( TCHAR );
ModuleName = new char[cbData];
if (NULL == ModuleName) { goto error_cleanup; }
ModuleName[cbData - 1] = TEXT('\0');
Result = RegQueryValueEx( hKey, // handle of key to query
TEXT("$DLL"), // address of name of value to query
NULL, // reserved
&Type, // address of buffer for value type
(LPBYTE)ModuleName, // address of data buffer
&cbData // address of data buffer size
);
if (ERROR_SUCCESS != Result) { goto error_cleanup; }
//
// Expand environment strings if necessary
//
if (Type == REG_EXPAND_SZ) {
DWORD ExpandedLength = 0; LPTSTR ExpandedModuleName = NULL;
ExpandedLength = ExpandEnvironmentStrings( ModuleName, NULL, 0 );
if (0 == ExpandedLength) { goto error_cleanup; }
ExpandedModuleName = new char[ExpandedLength];
if (NULL == ExpandedModuleName) { goto error_cleanup; }
ExpandedLength = ExpandEnvironmentStrings( ModuleName, ExpandedModuleName, ExpandedLength );
if (0 == ExpandedLength) { delete ExpandedModuleName; goto error_cleanup; }
//
// Free the old module name, use the new one
//
delete ModuleName;
ModuleName = ExpandedModuleName; }
size = (lstrlen( KeyName ) + 1) * sizeof( WCHAR );
ProviderName = new WCHAR[size / sizeof(WCHAR)];
if (NULL == ProviderName) { goto error_cleanup; }
#ifdef UNICODE
//
// If we've been compiled as unicode, the KeyName we got from
// the registry consists of WCHARs, so we can just copy it into
// the Name buffer.
//
lstrcpy( ProviderName, KeyName );
#else
//
// If we've been compiled as ANSI, then KeyName is an ANSI string,
// and we need to convert it to WCHARs.
//
MultiByteToWideChar ( CP_ACP, 0, KeyName, -1, ProviderName, size );
#endif // !UNICODE
//
// ModuleName now contains the module name, attempt to load it
// and ask it to initialize itself.
//
LibraryHandle = LoadLibrary( (LPTSTR)ModuleName );
if (NULL == LibraryHandle) { DWORD Error;
Error = GetLastError();
goto error_cleanup; }
ProcAddr = (LPWINTRUST_PROVIDER_CLIENT_INITIALIZE) GetProcAddress( LibraryHandle, (LPCSTR)"WinTrustProviderClientInitialize");
if (NULL == ProcAddr) { goto error_cleanup; }
SubKeyName = new char[(lstrlen(KeyName) + 1) * sizeof(TCHAR)];
if (NULL == SubKeyName) { goto error_cleanup; }
lstrcpy( SubKeyName, KeyName );
Provider = new LOADED_PROVIDER_V1;
if (NULL == Provider) { delete SubKeyName; goto error_cleanup; }
//
// Ready to call init routine.
//
Provider->RefCount = 1; Provider->ProviderInitialized = PROVIDER_INITIALIZATION_IN_PROGRESS;
//
// Set the subkey name so anyone else looking for this provider will
// find this one and wait.
//
// Note that we don't want to use the ProviderName as will be passed into
// the init routine here, because we've forced that to WCHARs regardless
// of whether we're ANSI or Unicode, and we want this string to reflect
// the base system for efficiency.
//
Provider->SubKeyName = SubKeyName;
Provider->Next = NULL; Provider->Prev = NULL;
Inited = (*ProcAddr)( WIN_TRUST_REVISION_1_0, &WinTrustClientTPInfo, ProviderName, (void **)&ClientInfo );
if (TRUE != Inited) {
Provider->ProviderInitialized = PROVIDER_INITIALIZATION_FAILED;
//
// We could release the lock now, because we're either going to
// do nothing to this provider, or we've removed it from
// the list and no one else can get to it.
//
goto error_cleanup; }
//
// Since we have a write lock, it doesn't matter what order we
// do this in, since there are no readers. Just be sure to signal
// the event under the write lock.
//
Provider->ProviderInitialized = PROVIDER_INITIALIZATION_SUCCESS; Provider->ModuleHandle = LibraryHandle; Provider->ModuleName = ModuleName; Provider->ClientInfo = ClientInfo;
return( Provider );
error_cleanup:
if (NULL != LibraryHandle) { FreeLibrary( LibraryHandle ); }
if (NULL != ModuleName) { delete ModuleName; }
if (NULL != ProviderName) { delete ProviderName; }
if (NULL != Provider) { delete Provider; }
return( NULL ); }
void Version1_UnloadProvider(PLOADED_PROVIDER_V1 Provider) { if (Provider) { if (Provider->ModuleHandle) { FreeLibrary((HINSTANCE)Provider->ModuleHandle); } if (Provider->ModuleName) { delete Provider->ModuleName; } }
delete Provider; }
|