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.

660 lines
20 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. PLOADED_PROVIDER_V1 FoundProvider = NULL;
  175. //
  176. // Open the registry and get a list of installed trust providers
  177. //
  178. Result = RegOpenKeyEx(
  179. REGISTRY_ROOT,
  180. REGISTRY_TRUSTPROVIDERS,
  181. 0L,
  182. GENERIC_READ,
  183. &hKey
  184. );
  185. if (Result != ERROR_SUCCESS) {
  186. return( NULL );
  187. }
  188. //
  189. // Find out how many subkeys there are.
  190. //
  191. Result = RegQueryInfoKey ( hKey, // handle of key to query
  192. NULL, // address of buffer for class string
  193. NULL, // address of size of class string buffer
  194. NULL, // reserved
  195. &cSubKeys, // address of buffer for number of subkeys
  196. &cbMaxSubKeyLen, // address of buffer for longest subkey name length
  197. NULL, // address of buffer for longest class string length
  198. NULL, // address of buffer for number of value entries
  199. NULL, // address of buffer for longest value name length
  200. NULL, // address of buffer for longest value data length
  201. NULL, // address of buffer for security descriptor length
  202. NULL // address of buffer for last write time
  203. );
  204. if (ERROR_SUCCESS != Result) {
  205. RegCloseKey( hKey );
  206. return( NULL );
  207. }
  208. //
  209. // Iterate through the subkeys, looking for ones with hint information.
  210. //
  211. cbMaxSubKeyLen += sizeof( WCHAR );
  212. SubKeyName = new char[cbMaxSubKeyLen + 1];
  213. if (NULL == SubKeyName) {
  214. RegCloseKey( hKey );
  215. return(NULL);
  216. }
  217. for (i=0; i<cSubKeys; i++) {
  218. DWORD KeyNameLength;
  219. KeyNameLength = cbMaxSubKeyLen;
  220. Result = RegEnumKeyEx( hKey, // handle of key to enumerate
  221. i, // index of subkey to enumerate
  222. SubKeyName, // address of buffer for subkey name
  223. &KeyNameLength, // address for size of subkey buffer
  224. NULL, // reserved
  225. NULL, // address of buffer for class string
  226. NULL, // address for size of class buffer
  227. NULL // address for time key last written to
  228. );
  229. //
  230. // Not much to do if this fails, try enumerating the rest of them and see
  231. // what happens.
  232. //
  233. if (Result != ERROR_SUCCESS) {
  234. continue;
  235. }
  236. Result = RegOpenKeyEx(
  237. hKey,
  238. SubKeyName,
  239. 0L,
  240. GENERIC_READ | MAXIMUM_ALLOWED,
  241. &hSubKey
  242. );
  243. if (ERROR_SUCCESS != Result)
  244. {
  245. continue;
  246. }
  247. FoundProvider = Version1_TestProviderForAction( hSubKey, SubKeyName, pgActionID );
  248. RegCloseKey( hSubKey );
  249. if (NULL != FoundProvider)
  250. {
  251. //
  252. // Got one. Clean up and return.
  253. //
  254. delete SubKeyName;
  255. RegCloseKey( hKey );
  256. return( FoundProvider );
  257. }
  258. continue;
  259. }
  260. delete SubKeyName;
  261. RegCloseKey( hKey );
  262. return( NULL );
  263. }
  264. WINTRUST_CLIENT_TP_INFO WinTrustClientTPInfo = {
  265. WIN_TRUST_REVISION_1_0,
  266. NULL
  267. };
  268. PLOADED_PROVIDER_V1 Version1_TestProviderForAction(HKEY hKey, LPTSTR KeyName, GUID * ActionID)
  269. {
  270. PLOADED_PROVIDER_V1 Provider;
  271. LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo;
  272. GUID * ActionIds;
  273. DWORD i;
  274. Provider = Version1_RegLoadProvider( hKey, KeyName, ActionID);
  275. if (NULL == Provider) {
  276. return( NULL );
  277. }
  278. ClientInfo = Provider->ClientInfo;
  279. ActionIds = ClientInfo->lpActionIdArray;
  280. for (i=0; i<ClientInfo->dwActionIdCount; i++) {
  281. if (IsEqualActionID(ActionID, &ActionIds[i])) {
  282. return( Provider );
  283. }
  284. }
  285. return(NULL);
  286. }
  287. PLOADED_PROVIDER_V1 Version1_RegLoadProvider(HKEY hKey, LPTSTR KeyName, GUID *ActionID)
  288. {
  289. LPTSTR ModuleName = NULL;
  290. HINSTANCE LibraryHandle = NULL;
  291. LPWINTRUST_PROVIDER_CLIENT_INFO ClientInfo = NULL;
  292. PLOADED_PROVIDER_V1 Provider = NULL;
  293. LPWSTR ProviderName = NULL;
  294. LPTSTR SubKeyName = NULL;
  295. GUID gBuffer[10]; // Assume no more than 10 action ids in a provider
  296. DWORD Type;
  297. DWORD cbData = 0;
  298. LONG Result;
  299. LPWINTRUST_PROVIDER_CLIENT_INITIALIZE ProcAddr;
  300. DWORD size;
  301. BOOL Inited;
  302. //
  303. // get the guids
  304. //
  305. cbData = sizeof(GUID) * 10;
  306. Result = RegQueryValueEx( hKey, // handle of key to query
  307. TEXT("$ActionIDs"),
  308. NULL, // reserved
  309. &Type, // address of buffer for value type
  310. (BYTE *)&gBuffer[0],
  311. &cbData // address of data buffer size
  312. );
  313. if (Result != ERROR_SUCCESS)
  314. {
  315. return(NULL);
  316. }
  317. //
  318. // check the guids
  319. //
  320. Inited = FALSE;
  321. for (int j = 0; j < (int)(cbData / sizeof(GUID)); j++)
  322. {
  323. if (memcmp(&gBuffer[j], ActionID, sizeof(GUID)) == 0)
  324. {
  325. Inited = TRUE;
  326. break;
  327. }
  328. }
  329. if (!(Inited))
  330. {
  331. return(NULL);
  332. }
  333. //
  334. // Extract the dll name from the $DLL value
  335. //
  336. Result = RegQueryValueEx( hKey, // handle of key to query
  337. TEXT("$DLL"), // address of name of value to query
  338. NULL, // reserved
  339. &Type, // address of buffer for value type
  340. NULL, // address of data buffer
  341. &cbData // address of data buffer size
  342. );
  343. // if (ERROR_MORE_DATA != Result) {
  344. // goto error_cleanup;
  345. // }
  346. if (ERROR_SUCCESS != Result) {
  347. goto error_cleanup;
  348. }
  349. cbData += sizeof( TCHAR );
  350. ModuleName = new char[cbData];
  351. if (NULL == ModuleName) {
  352. goto error_cleanup;
  353. }
  354. ModuleName[cbData - 1] = TEXT('\0');
  355. Result = RegQueryValueEx( hKey, // handle of key to query
  356. TEXT("$DLL"), // address of name of value to query
  357. NULL, // reserved
  358. &Type, // address of buffer for value type
  359. (LPBYTE)ModuleName, // address of data buffer
  360. &cbData // address of data buffer size
  361. );
  362. if (ERROR_SUCCESS != Result) {
  363. goto error_cleanup;
  364. }
  365. //
  366. // Expand environment strings if necessary
  367. //
  368. if (Type == REG_EXPAND_SZ) {
  369. DWORD ExpandedLength = 0;
  370. LPTSTR ExpandedModuleName = NULL;
  371. ExpandedLength = ExpandEnvironmentStrings( ModuleName, NULL, 0 );
  372. if (0 == ExpandedLength) {
  373. goto error_cleanup;
  374. }
  375. ExpandedModuleName = new char[ExpandedLength];
  376. if (NULL == ExpandedModuleName) {
  377. goto error_cleanup;
  378. }
  379. ExpandedLength = ExpandEnvironmentStrings( ModuleName, ExpandedModuleName, ExpandedLength );
  380. if (0 == ExpandedLength) {
  381. delete ExpandedModuleName;
  382. goto error_cleanup;
  383. }
  384. //
  385. // Free the old module name, use the new one
  386. //
  387. delete ModuleName;
  388. ModuleName = ExpandedModuleName;
  389. }
  390. size = (lstrlen( KeyName ) + 1) * sizeof( WCHAR );
  391. ProviderName = new WCHAR[size / sizeof(WCHAR)];
  392. if (NULL == ProviderName) {
  393. goto error_cleanup;
  394. }
  395. #ifdef UNICODE
  396. //
  397. // If we've been compiled as unicode, the KeyName we got from
  398. // the registry consists of WCHARs, so we can just copy it into
  399. // the Name buffer.
  400. //
  401. lstrcpy( ProviderName, KeyName );
  402. #else
  403. //
  404. // If we've been compiled as ANSI, then KeyName is an ANSI string,
  405. // and we need to convert it to WCHARs.
  406. //
  407. MultiByteToWideChar ( CP_ACP, 0, KeyName, -1, ProviderName, size );
  408. #endif // !UNICODE
  409. //
  410. // ModuleName now contains the module name, attempt to load it
  411. // and ask it to initialize itself.
  412. //
  413. LibraryHandle = LoadLibrary( (LPTSTR)ModuleName );
  414. if (NULL == LibraryHandle) {
  415. DWORD Error;
  416. Error = GetLastError();
  417. goto error_cleanup;
  418. }
  419. ProcAddr = (LPWINTRUST_PROVIDER_CLIENT_INITIALIZE) GetProcAddress( LibraryHandle, (LPCSTR)"WinTrustProviderClientInitialize");
  420. if (NULL == ProcAddr) {
  421. goto error_cleanup;
  422. }
  423. SubKeyName = new char[(lstrlen(KeyName) + 1) * sizeof(TCHAR)];
  424. if (NULL == SubKeyName) {
  425. goto error_cleanup;
  426. }
  427. lstrcpy( SubKeyName, KeyName );
  428. Provider = new LOADED_PROVIDER_V1;
  429. if (NULL == Provider) {
  430. delete SubKeyName;
  431. goto error_cleanup;
  432. }
  433. //
  434. // Ready to call init routine.
  435. //
  436. Provider->RefCount = 1;
  437. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_IN_PROGRESS;
  438. //
  439. // Set the subkey name so anyone else looking for this provider will
  440. // find this one and wait.
  441. //
  442. // Note that we don't want to use the ProviderName as will be passed into
  443. // the init routine here, because we've forced that to WCHARs regardless
  444. // of whether we're ANSI or Unicode, and we want this string to reflect
  445. // the base system for efficiency.
  446. //
  447. Provider->SubKeyName = SubKeyName;
  448. Provider->Next = NULL;
  449. Provider->Prev = NULL;
  450. Inited = (*ProcAddr)( WIN_TRUST_REVISION_1_0, &WinTrustClientTPInfo, ProviderName, (void **)&ClientInfo );
  451. if (TRUE != Inited) {
  452. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_FAILED;
  453. //
  454. // We could release the lock now, because we're either going to
  455. // do nothing to this provider, or we've removed it from
  456. // the list and no one else can get to it.
  457. //
  458. goto error_cleanup;
  459. }
  460. //
  461. // Since we have a write lock, it doesn't matter what order we
  462. // do this in, since there are no readers. Just be sure to signal
  463. // the event under the write lock.
  464. //
  465. Provider->ProviderInitialized = PROVIDER_INITIALIZATION_SUCCESS;
  466. Provider->ModuleHandle = LibraryHandle;
  467. Provider->ModuleName = ModuleName;
  468. Provider->ClientInfo = ClientInfo;
  469. return( Provider );
  470. error_cleanup:
  471. if (NULL != LibraryHandle) {
  472. FreeLibrary( LibraryHandle );
  473. }
  474. if (NULL != ModuleName) {
  475. delete ModuleName;
  476. }
  477. if (NULL != ProviderName) {
  478. delete ProviderName;
  479. }
  480. if (NULL != Provider)
  481. {
  482. delete Provider;
  483. }
  484. return( NULL );
  485. }
  486. void Version1_UnloadProvider(PLOADED_PROVIDER_V1 Provider)
  487. {
  488. if (Provider)
  489. {
  490. if (Provider->ModuleHandle)
  491. {
  492. FreeLibrary((HINSTANCE)Provider->ModuleHandle);
  493. }
  494. if (Provider->ModuleName)
  495. {
  496. delete Provider->ModuleName;
  497. }
  498. }
  499. delete Provider;
  500. }