Source code of Windows XP (NT5)
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.

663 lines
19 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1996 - 1999
  6. //
  7. // File: wvtver1.cpp
  8. //
  9. // Contents: Microsoft Internet Security WinVerifyTrust v1 support
  10. //
  11. // Functions: WintrustIsVersion1ActionID
  12. // ConvertDataFromVersion1
  13. //
  14. // *** local functions ***
  15. //
  16. // History: 30-May-1997 pberkman created
  17. //
  18. //--------------------------------------------------------------------------
  19. #include "global.hxx"
  20. #include "wvtver1.h"
  21. BOOL WintrustIsVersion1ActionID(GUID *pgActionID)
  22. {
  23. GUID gV1UISup = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
  24. GUID gV1UINoBad = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI;
  25. if ((memcmp(pgActionID, &gV1UISup, sizeof(GUID)) == 0) ||
  26. (memcmp(pgActionID, &gV1UINoBad, sizeof(GUID)) == 0))
  27. {
  28. return(TRUE);
  29. }
  30. return(FALSE);
  31. }
  32. WINTRUST_DATA *ConvertDataFromVersion1(HWND hWnd,
  33. GUID *pgActionID,
  34. WINTRUST_DATA *pWTDNew,
  35. WINTRUST_FILE_INFO *pWTFINew,
  36. LPVOID pWTDOld)
  37. {
  38. GUID gV1UINoBad = V1_WIN_SPUB_ACTION_PUBLISHED_SOFTWARE_NOBADUI;
  39. WCHAR *pwszFile;
  40. WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT *pActData;
  41. pActData = (WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT *)pWTDOld;
  42. memset(pWTDNew, 0x00, sizeof(WINTRUST_DATA));
  43. pWTDNew->cbStruct = sizeof(WINTRUST_DATA);
  44. pWTDNew->dwUnionChoice = WTD_CHOICE_FILE;
  45. pWTDNew->pFile = pWTFINew;
  46. memset(pWTFINew, 0x00, sizeof(WINTRUST_FILE_INFO));
  47. pWTFINew->cbStruct = sizeof(WINTRUST_FILE_INFO);
  48. if (!(pWTDOld))
  49. {
  50. return(pWTDNew);
  51. }
  52. pWTDNew->dwUIChoice = WTD_UI_ALL;
  53. pWTDNew->pPolicyCallbackData = pActData->hClientToken;
  54. pWTFINew->hFile = ((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->hFile;
  55. if (memcmp(&gV1UINoBad, pgActionID, sizeof(GUID)) == 0)
  56. {
  57. pWTDNew->dwUIChoice = WTD_UI_NOBAD;
  58. }
  59. if (hWnd == (HWND)(-1))
  60. {
  61. pWTDNew->dwUIChoice = WTD_UI_NONE;
  62. }
  63. pwszFile = (WCHAR *)((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->lpPath;
  64. while ((*pwszFile) && (*pwszFile != '|'))
  65. {
  66. ++pwszFile;
  67. }
  68. if (*pwszFile)
  69. {
  70. *pwszFile = NULL;
  71. }
  72. pWTFINew->pcwszFilePath = (WCHAR *)((WIN_TRUST_SUBJECT_FILE *)pActData->Subject)->lpPath;
  73. return(pWTDNew);
  74. }
  75. //////////////////////////////////////////////////////////////////////////////////////////////////
  76. //////////////////////////////////////////////////////////////////////////////////////////////////
  77. //
  78. // the following code implements the version 1 style of calling trust providers.
  79. //
  80. // this code is ONLY implemented when a trust provider registers itself in the
  81. // old location!
  82. //
  83. //////////////////////////////////////////////////////////////////////////////////////////////////
  84. //////////////////////////////////////////////////////////////////////////////////////////////////
  85. #define WIN_TRUST_MAJOR_REVISION_MASK 0xFFFF0000
  86. #define WIN_TRUST_MINOR_REVISION_MASK 0x0000FFFF
  87. #define WIN_TRUST_REVISION_1_0 0x00010000
  88. #define REGISTRY_TRUSTPROVIDERS TEXT("System\\CurrentControlSet\\Services\\WinTrust\\TrustProviders")
  89. #define REGISTRY_ROOT HKEY_LOCAL_MACHINE
  90. #define ACTION_IDS TEXT("$ActionIDs")
  91. #define DLL_NAME TEXT("$DLL")
  92. #define IsEqualActionID( id1, id2) (!memcmp(id1, id2, sizeof(GUID)))
  93. typedef struct _WINTRUST_CLIENT_TP_INFO {
  94. DWORD dwRevision;
  95. //LPWINTRUST_CLIENT_TP_DISPATCH_TABLE lpServices;
  96. LPVOID lpServices;
  97. } WINTRUST_CLIENT_TP_INFO, *LPWINTRUST_CLIENT_TP_INFO;
  98. typedef LONG
  99. (*LPWINTRUST_PROVIDER_VERIFY_TRUST) (
  100. IN HWND hwnd,
  101. IN GUID * ActionID,
  102. IN LPVOID ActionData
  103. );
  104. typedef VOID
  105. (*LPWINTRUST_PROVIDER_SUBMIT_CERTIFICATE) (
  106. IN LPWIN_CERTIFICATE lpCertificate
  107. );
  108. typedef VOID
  109. (*LPWINTRUST_PROVIDER_CLIENT_UNLOAD) (
  110. IN LPVOID lpTrustProviderInfo
  111. );
  112. typedef BOOL
  113. (*LPWINTRUST_PROVIDER_CLIENT_INITIALIZE)(
  114. IN DWORD dwWinTrustRevision,
  115. IN LPWINTRUST_CLIENT_TP_INFO lpWinTrustInfo,
  116. IN LPWSTR lpProviderName,
  117. LPVOID *lpTrustProviderInfo
  118. // OUT LPWINTRUST_PROVIDER_CLIENT_INFO *lpTrustProviderInfo
  119. );
  120. typedef struct _WINTRUST_PROVIDER_CLIENT_SERVICES
  121. {
  122. LPWINTRUST_PROVIDER_CLIENT_UNLOAD Unload;
  123. LPWINTRUST_PROVIDER_VERIFY_TRUST VerifyTrust;
  124. LPWINTRUST_PROVIDER_SUBMIT_CERTIFICATE SubmitCertificate;
  125. } WINTRUST_PROVIDER_CLIENT_SERVICES, *LPWINTRUST_PROVIDER_CLIENT_SERVICES;
  126. typedef struct _WINTRUST_PROVIDER_CLIENT_INFO {
  127. DWORD dwRevision;
  128. LPWINTRUST_PROVIDER_CLIENT_SERVICES lpServices;
  129. DWORD dwActionIdCount;
  130. GUID * lpActionIdArray;
  131. } WINTRUST_PROVIDER_CLIENT_INFO, *LPWINTRUST_PROVIDER_CLIENT_INFO;
  132. typedef struct _LOADED_PROVIDER_V1 {
  133. struct _LOADED_PROVIDER_V1 *Next;
  134. struct _LOADED_PROVIDER_V1 *Prev;
  135. HANDLE ModuleHandle;
  136. LPTSTR ModuleName;
  137. LPTSTR SubKeyName;
  138. LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo;
  139. DWORD RefCount;
  140. DWORD ProviderInitialized;
  141. } LOADED_PROVIDER_V1, *PLOADED_PROVIDER_V1;
  142. #define PROVIDER_INITIALIZATION_SUCCESS (1)
  143. #define PROVIDER_INITIALIZATION_IN_PROGRESS (2)
  144. #define PROVIDER_INITIALIZATION_FAILED (3)
  145. PLOADED_PROVIDER_V1 WinTrustFindActionID(IN GUID * dwActionID);
  146. PLOADED_PROVIDER_V1 Version1_RegLoadProvider(HKEY hKey, LPTSTR KeyName, GUID *ActionID);
  147. PLOADED_PROVIDER_V1 Version1_LoadProvider(GUID *pgActionID);
  148. PLOADED_PROVIDER_V1 Version1_TestProviderForAction(HKEY hKey, LPTSTR KeyName, GUID * ActionID);
  149. void Version1_UnloadProvider(PLOADED_PROVIDER_V1 Provider);
  150. LONG Version1_WinVerifyTrust(HWND hwnd, GUID *ActionID, LPVOID ActionData)
  151. {
  152. PLOADED_PROVIDER_V1 Provider;
  153. HRESULT rc;
  154. if (!(Provider = Version1_LoadProvider(ActionID)))
  155. {
  156. return( TRUST_E_PROVIDER_UNKNOWN );
  157. }
  158. rc = (*Provider->ClientInfo->lpServices->VerifyTrust)( hwnd,
  159. ActionID,
  160. ActionData
  161. );
  162. Version1_UnloadProvider(Provider);
  163. return( rc );
  164. }
  165. PLOADED_PROVIDER_V1 Version1_LoadProvider(GUID *pgActionID)
  166. {
  167. HKEY hKey; // Handle to the base of the provider information.
  168. HKEY hSubKey; // Handle to the provider currently being examined.
  169. LONG Result; // Returned by registry API.
  170. DWORD cSubKeys; // Number of providers under the root key.
  171. DWORD cbMaxSubKeyLen; // Maximum provider name length.
  172. ULONG i; // Indicies for iterating through providers and action IDs.
  173. LPTSTR SubKeyName; // Points to the name of the current provider.
  174. GUID * ActionIds;
  175. PLOADED_PROVIDER_V1 FoundProvider = NULL;
  176. //
  177. // Open the registry and get a list of installed trust providers
  178. //
  179. Result = RegOpenKeyEx(
  180. REGISTRY_ROOT,
  181. REGISTRY_TRUSTPROVIDERS,
  182. 0L,
  183. GENERIC_READ,
  184. &hKey
  185. );
  186. if (Result != ERROR_SUCCESS) {
  187. return( NULL );
  188. }
  189. //
  190. // Find out how many subkeys there are.
  191. //
  192. Result = RegQueryInfoKey ( hKey, // handle of key to query
  193. NULL, // address of buffer for class string
  194. NULL, // address of size of class string buffer
  195. NULL, // reserved
  196. &cSubKeys, // address of buffer for number of subkeys
  197. &cbMaxSubKeyLen, // address of buffer for longest subkey name length
  198. NULL, // address of buffer for longest class string length
  199. NULL, // address of buffer for number of value entries
  200. NULL, // address of buffer for longest value name length
  201. NULL, // address of buffer for longest value data length
  202. NULL, // address of buffer for security descriptor length
  203. NULL // address of buffer for last write time
  204. );
  205. if (ERROR_SUCCESS != Result) {
  206. RegCloseKey( hKey );
  207. return( NULL );
  208. }
  209. //
  210. // Iterate through the subkeys, looking for ones with hint information.
  211. //
  212. cbMaxSubKeyLen += sizeof( WCHAR );
  213. SubKeyName = new char[cbMaxSubKeyLen + 1];
  214. if (NULL == SubKeyName) {
  215. RegCloseKey( hKey );
  216. return(NULL);
  217. }
  218. for (i=0; i<cSubKeys; i++) {
  219. DWORD KeyNameLength;
  220. KeyNameLength = cbMaxSubKeyLen;
  221. Result = RegEnumKeyEx( hKey, // handle of key to enumerate
  222. i, // index of subkey to enumerate
  223. SubKeyName, // address of buffer for subkey name
  224. &KeyNameLength, // address for size of subkey buffer
  225. NULL, // reserved
  226. NULL, // address of buffer for class string
  227. NULL, // address for size of class buffer
  228. NULL // address for time key last written to
  229. );
  230. //
  231. // Not much to do if this fails, try enumerating the rest of them and see
  232. // what happens.
  233. //
  234. if (Result != ERROR_SUCCESS) {
  235. continue;
  236. }
  237. Result = RegOpenKeyEx(
  238. hKey,
  239. SubKeyName,
  240. 0L,
  241. GENERIC_READ | MAXIMUM_ALLOWED,
  242. &hSubKey
  243. );
  244. if (ERROR_SUCCESS != Result)
  245. {
  246. continue;
  247. }
  248. FoundProvider = Version1_TestProviderForAction( hSubKey, SubKeyName, pgActionID );
  249. RegCloseKey( hSubKey );
  250. if (NULL != FoundProvider)
  251. {
  252. //
  253. // Got one. Clean up and return.
  254. //
  255. delete SubKeyName;
  256. RegCloseKey( hKey );
  257. return( FoundProvider );
  258. }
  259. continue;
  260. }
  261. delete SubKeyName;
  262. RegCloseKey( hKey );
  263. return( NULL );
  264. }
  265. WINTRUST_CLIENT_TP_INFO WinTrustClientTPInfo = {
  266. WIN_TRUST_REVISION_1_0,
  267. NULL
  268. };
  269. PLOADED_PROVIDER_V1 Version1_TestProviderForAction(HKEY hKey, LPTSTR KeyName, GUID * ActionID)
  270. {
  271. PLOADED_PROVIDER_V1 Provider;
  272. LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo;
  273. GUID * ActionIds;
  274. DWORD i;
  275. Provider = Version1_RegLoadProvider( hKey, KeyName, ActionID);
  276. if (NULL == Provider) {
  277. return( NULL );
  278. }
  279. ClientInfo = Provider->ClientInfo;
  280. ActionIds = ClientInfo->lpActionIdArray;
  281. for (i=0; i<ClientInfo->dwActionIdCount; i++) {
  282. if (IsEqualActionID(ActionID, &ActionIds[i])) {
  283. return( Provider );
  284. }
  285. }
  286. return(NULL);
  287. }
  288. PLOADED_PROVIDER_V1 Version1_RegLoadProvider(HKEY hKey, LPTSTR KeyName, GUID *ActionID)
  289. {
  290. LPTSTR ModuleName = NULL;
  291. HINSTANCE LibraryHandle = NULL;
  292. LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo = NULL;
  293. PLOADED_PROVIDER_V1 Provider = NULL;
  294. PLOADED_PROVIDER_V1 FoundProvider = NULL;
  295. LPWSTR ProviderName = NULL;
  296. LPTSTR SubKeyName = NULL;
  297. GUID gBuffer[10]; // Assume no more than 10 action ids in a provider
  298. DWORD Type;
  299. DWORD cbData = 0;
  300. LONG Result;
  301. LPWINTRUST_PROVIDER_CLIENT_INITIALIZE ProcAddr;
  302. BOOL Referenced = FALSE;
  303. DWORD size;
  304. BOOL Inited;
  305. //
  306. // get the guids
  307. //
  308. cbData = sizeof(GUID) * 10;
  309. Result = RegQueryValueEx( hKey, // handle of key to query
  310. TEXT("$ActionIDs"),
  311. NULL, // reserved
  312. &Type, // address of buffer for value type
  313. (BYTE *)&gBuffer[0],
  314. &cbData // address of data buffer size
  315. );
  316. if (Result != ERROR_SUCCESS)
  317. {
  318. return(NULL);
  319. }
  320. //
  321. // check the guids
  322. //
  323. Inited = FALSE;
  324. for (int j = 0; j < (int)(cbData / sizeof(GUID)); j++)
  325. {
  326. if (memcmp(&gBuffer[j], ActionID, sizeof(GUID)) == 0)
  327. {
  328. Inited = TRUE;
  329. break;
  330. }
  331. }
  332. if (!(Inited))
  333. {
  334. return(NULL);
  335. }
  336. //
  337. // Extract the dll name from the $DLL value
  338. //
  339. Result = RegQueryValueEx( hKey, // handle of key to query
  340. TEXT("$DLL"), // address of name of value to query
  341. NULL, // reserved
  342. &Type, // address of buffer for value type
  343. NULL, // address of data buffer
  344. &cbData // address of data buffer size
  345. );
  346. // if (ERROR_MORE_DATA != Result) {
  347. // goto error_cleanup;
  348. // }
  349. if (ERROR_SUCCESS != Result) {
  350. goto error_cleanup;
  351. }
  352. cbData += sizeof( TCHAR );
  353. ModuleName = new char[cbData];
  354. if (NULL == ModuleName) {
  355. goto error_cleanup;
  356. }
  357. ModuleName[cbData - 1] = TEXT('\0');
  358. Result = RegQueryValueEx( hKey, // handle of key to query
  359. TEXT("$DLL"), // address of name of value to query
  360. NULL, // reserved
  361. &Type, // address of buffer for value type
  362. (LPBYTE)ModuleName, // address of data buffer
  363. &cbData // address of data buffer size
  364. );
  365. if (ERROR_SUCCESS != Result) {
  366. goto error_cleanup;
  367. }
  368. //
  369. // Expand environment strings if necessary
  370. //
  371. if (Type == REG_EXPAND_SZ) {
  372. DWORD ExpandedLength = 0;
  373. LPTSTR ExpandedModuleName = NULL;
  374. ExpandedLength = ExpandEnvironmentStrings( ModuleName, NULL, 0 );
  375. if (0 == ExpandedLength) {
  376. goto error_cleanup;
  377. }
  378. ExpandedModuleName = new char[ExpandedLength];
  379. if (NULL == ExpandedModuleName) {
  380. goto error_cleanup;
  381. }
  382. ExpandedLength = ExpandEnvironmentStrings( ModuleName, ExpandedModuleName, ExpandedLength );
  383. if (0 == ExpandedLength) {
  384. delete ExpandedModuleName;
  385. goto error_cleanup;
  386. }
  387. //
  388. // Free the old module name, use the new one
  389. //
  390. delete ModuleName;
  391. ModuleName = ExpandedModuleName;
  392. }
  393. size = (lstrlen( KeyName ) + 1) * sizeof( WCHAR );
  394. ProviderName = new WCHAR[size / sizeof(WCHAR)];
  395. if (NULL == ProviderName) {
  396. goto error_cleanup;
  397. }
  398. #ifdef UNICODE
  399. //
  400. // If we've been compiled as unicode, the KeyName we got from
  401. // the registry consists of WCHARs, so we can just copy it into
  402. // the Name buffer.
  403. //
  404. lstrcpy( ProviderName, KeyName );
  405. #else
  406. //
  407. // If we've been compiled as ANSI, then KeyName is an ANSI string,
  408. // and we need to convert it to WCHARs.
  409. //
  410. MultiByteToWideChar ( CP_ACP, 0, KeyName, -1, ProviderName, size );
  411. #endif // !UNICODE
  412. //
  413. // ModuleName now contains the module name, attempt to load it
  414. // and ask it to initialize itself.
  415. //
  416. LibraryHandle = LoadLibrary( (LPTSTR)ModuleName );
  417. if (NULL == LibraryHandle) {
  418. DWORD Error;
  419. Error = GetLastError();
  420. goto error_cleanup;
  421. }
  422. ProcAddr = (LPWINTRUST_PROVIDER_CLIENT_INITIALIZE) GetProcAddress( LibraryHandle, (LPCSTR)"WinTrustProviderClientInitialize");
  423. if (NULL == ProcAddr) {
  424. goto error_cleanup;
  425. }
  426. SubKeyName = new char[(lstrlen(KeyName) + 1) * sizeof(TCHAR)];
  427. if (NULL == SubKeyName) {
  428. goto error_cleanup;
  429. }
  430. lstrcpy( SubKeyName, KeyName );
  431. Provider = new LOADED_PROVIDER_V1;
  432. if (NULL == Provider) {
  433. delete SubKeyName;
  434. goto error_cleanup;
  435. }
  436. //
  437. // Ready to call init routine.
  438. //
  439. Provider->RefCount = 1;
  440. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_IN_PROGRESS;
  441. //
  442. // Set the subkey name so anyone else looking for this provider will
  443. // find this one and wait.
  444. //
  445. // Note that we don't want to use the ProviderName as will be passed into
  446. // the init routine here, because we've forced that to WCHARs regardless
  447. // of whether we're ANSI or Unicode, and we want this string to reflect
  448. // the base system for efficiency.
  449. //
  450. Provider->SubKeyName = SubKeyName;
  451. Provider->Next = NULL;
  452. Provider->Prev = NULL;
  453. Inited = (*ProcAddr)( WIN_TRUST_REVISION_1_0, &WinTrustClientTPInfo, ProviderName, (void **)&ClientInfo );
  454. if (TRUE != Inited) {
  455. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_FAILED;
  456. //
  457. // We could release the lock now, because we're either going to
  458. // do nothing to this provider, or we've removed it from
  459. // the list and no one else can get to it.
  460. //
  461. goto error_cleanup;
  462. }
  463. //
  464. // Since we have a write lock, it doesn't matter what order we
  465. // do this in, since there are no readers. Just be sure to signal
  466. // the event under the write lock.
  467. //
  468. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_SUCCESS;
  469. Provider->ModuleHandle = LibraryHandle;
  470. Provider->ModuleName = ModuleName;
  471. Provider->ClientInfo = ClientInfo;
  472. return( Provider );
  473. error_cleanup:
  474. if (NULL != LibraryHandle) {
  475. FreeLibrary( LibraryHandle );
  476. }
  477. if (NULL != ModuleName) {
  478. delete ModuleName;
  479. }
  480. if (NULL != ProviderName) {
  481. delete ProviderName;
  482. }
  483. if (NULL != Provider)
  484. {
  485. delete Provider;
  486. }
  487. return( NULL );
  488. }
  489. void Version1_UnloadProvider(PLOADED_PROVIDER_V1 Provider)
  490. {
  491. if (Provider)
  492. {
  493. if (Provider->ModuleHandle)
  494. {
  495. FreeLibrary((HINSTANCE)Provider->ModuleHandle);
  496. }
  497. if (Provider->ModuleName)
  498. {
  499. delete Provider->ModuleName;
  500. }
  501. }
  502. delete Provider;
  503. }