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.

789 lines
23 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998,1999,2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // SYSTEM: Windows Update Critical Fix Notification
  6. //
  7. // CLASS: N/A
  8. // MODULE: MS Cab Trusting Function Implementation
  9. // FILE: Newtrust.CPP
  10. //
  11. /////////////////////////////////////////////////////////////////////
  12. //
  13. // DESC: this file implements the functions used by class CTrust
  14. // these function are copied from inseng.dll of IE5 Active Setup.
  15. //
  16. //
  17. // AUTHOR: Alessandro Muti, Windows Update Team
  18. // DATE: 3/11/1999
  19. //
  20. /////////////////////////////////////////////////////////////////////
  21. //
  22. // Revision History:
  23. //
  24. // Date Author Description
  25. // ~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  26. // 10/17/2000 Nick Dallett Porting Charlma's new cert-checking code from SLM tree:
  27. // (8/28/00 Charles Ma Rewrite CheckMSCert() function to handle certs with MS root and special cases )
  28. //
  29. /////////////////////////////////////////////////////////////////////
  30. //
  31. // (c) Copyrights: 1998, 1999, 2000 Microsoft Corporation
  32. //
  33. // All rights reserved.
  34. //
  35. // No portion of this source code may be reproduced
  36. // without express written permission of Microsoft Corporation.
  37. //
  38. // This source code is proprietary and confidential.
  39. /////////////////////////////////////////////////////////////////////
  40. #include <windows.h>
  41. #include <urlmon.h>
  42. #include <wintrust.h>
  43. #include <wincrypt.h>
  44. #include <softpub.h>
  45. //#include <atlconv.h>
  46. #include <tchar.h>
  47. #include <wustl.h>
  48. #include "cdmlibp.h"
  49. #include "newtrust.h"
  50. #define LOGGING_LEVEL 3
  51. #include <log.h>
  52. //*********************************************************************************//
  53. // Global UNICODE<>ANSI translation helpers
  54. //*********************************************************************************//
  55. #include <malloc.h> // for _alloca
  56. #define USES_CONVERSION int _convert = 0; _convert; UINT _acp = CP_ACP; _acp; LPCWSTR _lpw = NULL; _lpw; LPCSTR _lpa = NULL; _lpa
  57. inline LPWSTR WINAPI AtlA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars, UINT acp)
  58. {
  59. //
  60. // verify that no illegal character present
  61. // since lpw was allocated based on the size of lpa
  62. // don't worry about the number of chars
  63. //
  64. lpw[0] = '\0';
  65. MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars);
  66. return lpw;
  67. }
  68. inline LPSTR WINAPI AtlW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars, UINT acp)
  69. {
  70. //
  71. // verify that no illegal character present
  72. // since lpa was allocated based on the size of lpw
  73. // don't worry about the number of chars
  74. //
  75. lpa[0] = '\0';
  76. WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL);
  77. return lpa;
  78. }
  79. #define A2W(lpa) (\
  80. ((_lpa = lpa) == NULL) ? NULL : (\
  81. _convert = (lstrlenA(_lpa)+1),\
  82. AtlA2WHelper((LPWSTR)_alloca(_convert*2), _lpa, _convert, CP_ACP)))
  83. #define W2A(lpw) (\
  84. ((_lpw = lpw) == NULL) ? NULL : (\
  85. _convert = (lstrlenW(_lpw)+1)*2,\
  86. AtlW2AHelper((LPSTR)_alloca(_convert), _lpw, _convert, CP_ACP)))
  87. #define A2CW(lpa) ((LPCWSTR)A2W(lpa))
  88. #define W2CA(lpw) ((LPCSTR)W2A(lpw))
  89. #ifdef _UNICODE
  90. #define T2A W2A
  91. #define A2T A2W
  92. inline LPWSTR T2W(LPTSTR lp) { return lp; }
  93. inline LPTSTR W2T(LPWSTR lp) { return lp; }
  94. #define T2CA W2CA
  95. #define A2CT A2CW
  96. inline LPCWSTR T2CW(LPCTSTR lp) { return lp; }
  97. inline LPCTSTR W2CT(LPCWSTR lp) { return lp; }
  98. #else
  99. #define T2W A2W
  100. #define W2T W2A
  101. inline LPSTR T2A(LPTSTR lp) { return lp; }
  102. inline LPTSTR A2T(LPSTR lp) { return lp; }
  103. #define T2CW A2CW
  104. #define W2CT W2CA
  105. inline LPCSTR T2CA(LPCTSTR lp) { return lp; }
  106. inline LPCTSTR A2CT(LPCSTR lp) { return lp; }
  107. #endif
  108. #define OLE2T(p) W2T(p)
  109. #define T2OLE(p) T2W(p)
  110. /////////////////////////////////////////////////////////////////////////////
  111. //
  112. // typedefs for APIs used in the CheckTrust() function
  113. //
  114. // Since some of these APIs are new and only available on IE5 we have to
  115. // try to dynamicaly use them when available and do without the extra checks
  116. // when we are on an OS that has not been upgraded to the new crypto code.
  117. //
  118. /////////////////////////////////////////////////////////////////////////////
  119. const TCHAR WINTRUST[] = _T("wintrust.dll");
  120. const TCHAR CRYPT32[] = _T("crypt32.dll");
  121. //
  122. // declare a global crypt32.dll library handler, so we don't
  123. // need to load the library every time these functions are called.
  124. // NOTE: we do not release the library though. When the process of
  125. // calling this feature exits, the library is released.
  126. // same as wintrust.dll
  127. //
  128. static HINSTANCE shWinTrustDllInst = NULL;
  129. static HINSTANCE shCrypt32DllInst = NULL;
  130. //
  131. // define prototype for function WinVerifyTrust()
  132. // and declare a global variable to point to this function
  133. //
  134. typedef HRESULT
  135. (WINAPI * PFNWinVerifyTrust)(
  136. HWND hwnd, GUID *ActionID, LPVOID ActionData);
  137. PFNWinVerifyTrust pfnWinVerifyTrust = NULL;
  138. //
  139. // define prototype for function WTHelperProvDataFromStateData()
  140. // and declare a global variable to point to this function
  141. //
  142. typedef CRYPT_PROVIDER_DATA *
  143. (WINAPI * PFNWTHelperProvDataFromStateData)(
  144. HANDLE hStateData);
  145. PFNWTHelperProvDataFromStateData pfnWTHelperProvDataFromStateData = NULL;
  146. //
  147. // define prototype for function WTHelperGetProvSignerFromChain()
  148. // and declare a global variable to point to this function
  149. //
  150. typedef CRYPT_PROVIDER_SGNR *
  151. (WINAPI * PFNWTHelperGetProvSignerFromChain)(
  152. CRYPT_PROVIDER_DATA *pProvData,
  153. DWORD idxSigner,
  154. BOOL fCounterSigner,
  155. DWORD idxCounterSigner);
  156. PFNWTHelperGetProvSignerFromChain pfnWTHelperGetProvSignerFromChain = NULL;
  157. //
  158. // define prototype for function PFNWTHelperGetProvCertFromChain()
  159. // and declare a global variable to point to this function
  160. //
  161. typedef CRYPT_PROVIDER_CERT *
  162. (WINAPI * PFNWTHelperGetProvCertFromChain)(
  163. CRYPT_PROVIDER_SGNR *pSgnr,
  164. DWORD idxCert);
  165. PFNWTHelperGetProvCertFromChain pfnWTHelperGetProvCertFromChain = NULL;
  166. //
  167. // define prototype for function CryptHashPublicKeyInfo()
  168. // and declare a global variable to point to this function
  169. //
  170. typedef BOOL
  171. (WINAPI * PFNCryptHashPublicKeyInfo)(
  172. HCRYPTPROV hCryptProv,
  173. ALG_ID Algid,
  174. DWORD dwFlags,
  175. DWORD dwCertEncodingType,
  176. PCERT_PUBLIC_KEY_INFO pInfo,
  177. BYTE *pbComputedHash,
  178. DWORD *pcbComputedHash);
  179. PFNCryptHashPublicKeyInfo pfnCryptHashPublicKeyInfo = NULL;
  180. //
  181. // define prototype for function CertGetCertificateContextProperty()
  182. // and declare a global variable to point to this function
  183. //
  184. typedef BOOL
  185. (WINAPI * PFNCertGetCertificateContextProperty)(
  186. PCCERT_CONTEXT pCertContext,
  187. DWORD dwPropId,
  188. void *pvData,
  189. DWORD *pcbData);
  190. PFNCertGetCertificateContextProperty pfnCertGetCertificateContextProperty = NULL;
  191. /////////////////////////////////////////////////////////////////////////////
  192. //
  193. // pre-defined cert data to check against
  194. //
  195. /////////////////////////////////////////////////////////////////////////////
  196. //
  197. // The following is the sha1 key identifier for the Microsoft root
  198. //
  199. static BYTE rgbSignerRootKeyId[20] = {
  200. 0x4A, 0x5C, 0x75, 0x22, 0xAA, 0x46, 0xBF, 0xA4, 0x08, 0x9D,
  201. 0x39, 0x97, 0x4E, 0xBD, 0xB4, 0xA3, 0x60, 0xF7, 0xA0, 0x1D
  202. };
  203. //
  204. // define the size of each hash values in the known id buffer
  205. // for special certs.
  206. //
  207. //static size_t rgbSpecialCertIdSize[5] = {20, 20, 20, 20, 20};
  208. //
  209. // this is the size of buffer to receive the cert hash value
  210. // it must be not less than the largest number in the
  211. // above-defined array
  212. //
  213. const size_t ShaBufSize = 20;
  214. //
  215. // id buffer to store hash values of all special certs
  216. // Warning: the size of this buffer should match the sum
  217. // of size_t values defined above.
  218. //
  219. static BYTE rgbSpecialCertId[200] = {
  220. 0xB1,0x59,0xA5,0x2E,0x3D,0xD8,0xCE,0xCD,0x3A,0x9A,0x4A,0x7A,0x73,0x92,0xAA,0x8D,0xA7,0xE7,0xD6,0x7F, // MS cert
  221. 0xB1,0xC7,0x75,0xE0,0x4A,0x9D,0xFD,0x23,0xB6,0x18,0x97,0x11,0x5E,0xF6,0xEA,0x6B,0x99,0xEC,0x76,0x1D, // MSN cert
  222. 0x11,0xC7,0x10,0xF3,0xCB,0x6C,0x43,0xE1,0x66,0xEC,0x64,0x1C,0x7C,0x01,0x17,0xC4,0xB4,0x10,0x35,0x30, // MSNBC cert
  223. 0x95,0x25,0x58,0xD4,0x07,0xDE,0x4A,0xFD,0xAE,0xBA,0x13,0x72,0x83,0xC2,0xB3,0x37,0x04,0x90,0xC9,0x8A, // MSN Europe
  224. 0x72,0x54,0x14,0x91,0x1D,0x6E,0x10,0x84,0x8E,0x0F,0xFA,0xA0,0xB0,0xA1,0x65,0xBF,0x44,0x8F,0x9F,0x6D, // MS Europe
  225. 0x20,0x5E,0x48,0x43,0xAB,0xAD,0x54,0x77,0x71,0xBD,0x8D,0x1A,0x3C,0xE0,0xE5,0x9D,0xF5,0xBD,0x25,0xF9, // Old MS cert: 97~98
  226. 0xD6,0xCD,0x01,0x90,0xB3,0x1B,0x31,0x85,0x81,0x12,0x23,0x14,0xB5,0x17,0xA0,0xAA,0xCE,0xF2,0x7B,0xD5, // Old MS cert: 98~99
  227. 0x8A,0xA1,0x37,0xF5,0x03,0x9F,0xE0,0x28,0xC9,0x26,0xAA,0x55,0x90,0x14,0x19,0x68,0xFA,0xFF,0xE8,0x1A, // Old MS cert: 99~00
  228. 0xF3,0x25,0xF8,0x67,0x07,0x29,0xE5,0x27,0xF3,0x77,0x52,0x34,0xE0,0x51,0x57,0x69,0x0F,0x40,0xC6,0x1C, // Old MS Europe cert: 99~00
  229. 0x6A,0x71,0xFE,0x54,0x8A,0x51,0x08,0x70,0xF9,0x8A,0x56,0xCA,0x11,0x55,0xF6,0x76,0x45,0x92,0x02,0x5A // Old MS Europe cert: 98~99
  230. };
  231. /////////////////////////////////////////////////////////////////////////////
  232. //
  233. // Private Function ULONG CompareMem(PVOID pBlock1, PVOID pBlock2, ULONG Length)
  234. //
  235. // This function acts in the same way as RtlCompareMemory()
  236. //
  237. //
  238. // Input: two pointers to two memory blocks, and a byte size to compare
  239. // Return: the number of bytes that compared as equal.
  240. // If all bytes compare as equal, the input Length is returned.
  241. // If any pointer is NULL, 0 is returned.
  242. //
  243. /////////////////////////////////////////////////////////////////////////////
  244. ULONG CompareMem(const BYTE* pBlock1, const BYTE* pBlock2, ULONG Length)
  245. {
  246. ULONG uLen = 0L;
  247. if (pBlock1 != NULL && pBlock2 != NULL)
  248. {
  249. for (; uLen < Length; uLen++, pBlock1++, pBlock2++)
  250. {
  251. if (*pBlock1 != *pBlock2) return uLen;
  252. }
  253. }
  254. return uLen;
  255. }
  256. /////////////////////////////////////////////////////////////////////////////
  257. //
  258. // Private Function VerifyMSRoot()
  259. //
  260. // This function takes the passed-in certificate as a root cert,
  261. // and verifies its public key hash value is the same as
  262. // known "Microsoft Root Authority" cert value.
  263. //
  264. //
  265. // Input: hCrypt32DllInst - handle point to loaded crypt32.dll library
  266. // pRootCert - the certificate context of the root cert
  267. //
  268. // Return: HRESULT - result of execution, S_OK if matched.
  269. // the result code, in case of error, are code retuned by
  270. // crypt32.dll, with these the exception of E_INVALIDARG if
  271. // the passed-in parameters are NULL.
  272. //
  273. /////////////////////////////////////////////////////////////////////////////
  274. HRESULT VerifyMSRoot(
  275. HINSTANCE hCrypt32DllInst, // handle point to loaded crypt32.dll librar
  276. PCCERT_CONTEXT pRootCert
  277. )
  278. {
  279. HRESULT hr = S_OK;
  280. BYTE rgbKeyId[sizeof(rgbSignerRootKeyId)];
  281. DWORD cbKeyId = sizeof(rgbSignerRootKeyId);
  282. LOG_block("VerifyMSRoot()");
  283. //
  284. // valid parameter values
  285. //
  286. if (NULL == hCrypt32DllInst || NULL == pRootCert)
  287. {
  288. hr = E_INVALIDARG;
  289. goto ErrHandler;
  290. }
  291. //
  292. // get the function we need from the passed in library handle
  293. // If not available, return error
  294. //
  295. if (NULL == (pfnCryptHashPublicKeyInfo = (PFNCryptHashPublicKeyInfo)
  296. GetProcAddress(hCrypt32DllInst, "CryptHashPublicKeyInfo")))
  297. {
  298. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  299. goto ErrHandler;
  300. }
  301. //
  302. // get the public key hash value of this cert
  303. //
  304. ZeroMemory(rgbKeyId, sizeof(rgbKeyId));
  305. if (!pfnCryptHashPublicKeyInfo(
  306. 0, // use default crypto svc provider
  307. CALG_SHA1, // use SHA algorithm
  308. 0, // dwFlags
  309. X509_ASN_ENCODING,
  310. &pRootCert->pCertInfo->SubjectPublicKeyInfo,
  311. rgbKeyId,
  312. &cbKeyId
  313. ))
  314. {
  315. hr = HRESULT_FROM_WIN32(GetLastError());
  316. goto ErrHandler;
  317. }
  318. //
  319. // compare the hash value of public key of this root cert with the known MS root cert value
  320. //
  321. if (sizeof(rgbSignerRootKeyId) != cbKeyId || cbKeyId != CompareMem(rgbSignerRootKeyId, rgbKeyId, cbKeyId))
  322. {
  323. hr = S_FALSE;
  324. }
  325. ErrHandler:
  326. if (FAILED(hr))
  327. {
  328. LOG_out("Faied inside function VerifyMSRoot() with HRESULT 0x%0x", hr);
  329. }
  330. else
  331. {
  332. LOG_out("Exit VerifyMSRoot() with %s", (S_OK == hr) ? "S_OK" : "S_FALSE");
  333. }
  334. return hr;
  335. }
  336. /////////////////////////////////////////////////////////////////////////////
  337. //
  338. // Private Function VerifySpecialMSCerts()
  339. //
  340. // This function takes the passed-in certificate as a leaf cert,
  341. // and verifies its hash value matches the hash value of one of
  342. // known Microsoft special certs that does not have MS root.
  343. //
  344. // The known certs are, in comparing order:
  345. // Microsoft Corporation
  346. // Microsoft Corporation MSN
  347. // MSNBC Interactive News LLC
  348. // Microsoft Corporation MSN (Europe)
  349. // Microsoft Corporation (Europe)
  350. //
  351. //
  352. // Input: hCrypt32DllInst - handle point to loaded crypt32.dll library
  353. // pRootCert - the certificate context of the root cert
  354. //
  355. // Return: HRESULT - result of execution, S_OK if matched.
  356. // if not matched, CERT_E_UNTRUSTEDROOT, or
  357. // E_INVALIDARG if arguments not right, or
  358. // crypt32.dll error returned by API calls
  359. //
  360. /////////////////////////////////////////////////////////////////////////////
  361. HRESULT VerifySpecialMSCerts(
  362. HINSTANCE hCrypt32DllInst, // handle point to loaded crypt32.dll librar
  363. PCCERT_CONTEXT pLeafCert
  364. )
  365. {
  366. HRESULT hr = S_FALSE;
  367. BYTE btShaBuffer[ShaBufSize];
  368. DWORD dwSize = sizeof(btShaBuffer);
  369. LPBYTE pId;
  370. int i;
  371. LOG_block("VerifySpecialMSCerts()");
  372. //
  373. // valid parameter values
  374. //
  375. if (NULL == hCrypt32DllInst || NULL == pLeafCert)
  376. {
  377. hr = E_INVALIDARG;
  378. goto ErrHandler;
  379. }
  380. //
  381. // get the function we need from the passed in library handle
  382. // If not available, return error
  383. //
  384. if (NULL == (pfnCertGetCertificateContextProperty = (PFNCertGetCertificateContextProperty)
  385. GetProcAddress(hCrypt32DllInst, "CertGetCertificateContextProperty")))
  386. {
  387. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  388. goto ErrHandler;
  389. }
  390. //
  391. // find out the id hash of leaf cert
  392. //
  393. ZeroMemory(btShaBuffer, dwSize);
  394. if (!pfnCertGetCertificateContextProperty(
  395. pLeafCert, // pCertContext
  396. CERT_SHA1_HASH_PROP_ID, // dwPropId
  397. btShaBuffer,
  398. &dwSize
  399. ))
  400. {
  401. hr = GetLastError();
  402. goto ErrHandler;
  403. }
  404. //
  405. // iterrate through all known id hash values to see if this file is signed
  406. // with any of these special certs.
  407. //
  408. if (ShaBufSize == dwSize)
  409. {
  410. for (i = 0,pId = rgbSpecialCertId; i < sizeof(rgbSpecialCertId)/ShaBufSize; i++, pId += ShaBufSize)
  411. {
  412. if (CompareMem(btShaBuffer, pId, ShaBufSize) == ShaBufSize)
  413. {
  414. //
  415. // found a matching known cert!
  416. //
  417. hr = S_OK;
  418. break;
  419. }
  420. }
  421. }
  422. ErrHandler:
  423. if (FAILED(hr))
  424. {
  425. LOG_out("Faied inside function VerifySpecialMSCerts() with HRESULT 0x%0x", hr);
  426. }
  427. else
  428. {
  429. LOG_out("Exit VerifySpecialMSCerts() with %s", (S_OK == hr) ? "S_OK" : "S_FALSE");
  430. }
  431. return hr;
  432. }
  433. /////////////////////////////////////////////////////////////////////////////
  434. //
  435. // Private Function CheckWinTrust()
  436. //
  437. // This function will return the HRESULT for the trust state on the
  438. // specified file. The file can be pointing to any URL or local file.
  439. // The verification will be done by the wintrust.dll.
  440. //
  441. //
  442. // Input: Fully qualified filename, UIChoice
  443. // Return: HRESULT - result of execution
  444. //
  445. /////////////////////////////////////////////////////////////////////////////
  446. HRESULT CheckWinTrust(LPCTSTR pszFileName, DWORD dwUIChoice)
  447. {
  448. LOG_block("CheckWinTrust()");
  449. USES_CONVERSION;
  450. // Now verify the file
  451. WINTRUST_DATA winData;
  452. WINTRUST_FILE_INFO winFile;
  453. GUID gAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  454. CRYPT_PROVIDER_DATA const *pProvData = NULL;
  455. CRYPT_PROVIDER_SGNR *pProvSigner = NULL;
  456. CRYPT_PROVIDER_CERT *pProvCert = NULL;
  457. HRESULT hr = S_OK;
  458. #ifdef _WUV3TEST
  459. //
  460. // handling test case:
  461. // if a reg key value is set to 1, then we will see if we need to pop up ALL certs
  462. //
  463. // NOTE:
  464. //
  465. // for the certs that user has checked "Always trust this provider..." previously,
  466. // WinCheckTrust() API will still NOT show any UI even if we signal Show-ALL flag
  467. //
  468. HKEY hkey;
  469. DWORD dwWinTrustUI = 0;
  470. DWORD dwSize = sizeof(dwWinTrustUI);
  471. if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey))
  472. {
  473. RegQueryValueEx(hkey, _T("WinTrustUI"), 0, 0, (LPBYTE)&dwWinTrustUI, &dwSize);
  474. RegCloseKey(hkey);
  475. }
  476. if (1 == dwWinTrustUI && WTD_UI_NONE != dwUIChoice)
  477. {
  478. //
  479. // if there is a WinTrustUI reg key exist, and value is 1
  480. // and caller does not request silence, then we
  481. // pop up all certs
  482. //
  483. dwUIChoice = WTD_UI_ALL;
  484. }
  485. #endif
  486. //
  487. // dynamically load the wintrust.dll
  488. //
  489. if (NULL == shWinTrustDllInst)
  490. {
  491. if (NULL == (shWinTrustDllInst = LoadLibrary(WINTRUST)))
  492. {
  493. LOG_error("Failed to load libary %s, exit function.", WINTRUST);
  494. hr = HRESULT_FROM_WIN32(GetLastError());
  495. goto Done;
  496. }
  497. }
  498. //
  499. // dynamically load the crypt32.dll, which will be used by the two
  500. // helper functions to verify the cert is MS cert
  501. //
  502. if (NULL == shCrypt32DllInst)
  503. {
  504. if (NULL == (shCrypt32DllInst = LoadLibrary(CRYPT32)))
  505. {
  506. LOG_error("Failed to load libary %s, exit function.", CRYPT32);
  507. hr = HRESULT_FROM_WIN32(GetLastError());
  508. goto Done;
  509. }
  510. }
  511. //
  512. // find the functions we need
  513. //
  514. if (NULL == (pfnWinVerifyTrust = (PFNWinVerifyTrust)
  515. GetProcAddress(shWinTrustDllInst, "WinVerifyTrust")) ||
  516. NULL == (pfnWTHelperProvDataFromStateData = (PFNWTHelperProvDataFromStateData)
  517. GetProcAddress(shWinTrustDllInst, "WTHelperProvDataFromStateData")) ||
  518. NULL == (pfnWTHelperGetProvSignerFromChain = (PFNWTHelperGetProvSignerFromChain)
  519. GetProcAddress(shWinTrustDllInst, "WTHelperGetProvSignerFromChain")) ||
  520. NULL == (pfnWTHelperGetProvCertFromChain = (PFNWTHelperGetProvCertFromChain)
  521. GetProcAddress(shWinTrustDllInst, "WTHelperGetProvCertFromChain")))
  522. {
  523. //
  524. // at least one function was not found in the loaded cryp32.dll libary.
  525. // we can not continue, jsut quit.
  526. // NOTE: this shouldn't happen since we have tried to get
  527. // the least common denomination of different version of this dll
  528. // on both IE4 and IE5
  529. //
  530. LOG_error("CheckWinTrust() did not find functions needed from %s", CRYPT32);
  531. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  532. goto Done;
  533. }
  534. //
  535. // initialize the data structure used to verify trust
  536. //
  537. winFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
  538. winFile.hFile = INVALID_HANDLE_VALUE;
  539. winFile.pcwszFilePath = T2OLE((LPTSTR)pszFileName);
  540. winFile.pgKnownSubject = NULL;
  541. winData.cbStruct = sizeof(WINTRUST_DATA);
  542. winData.pPolicyCallbackData = NULL;
  543. winData.pSIPClientData = NULL;
  544. winData.dwUIChoice = (WTD_UI_ALL == dwUIChoice) ? dwUIChoice : WTD_UI_NONE;
  545. winData.fdwRevocationChecks = 0;
  546. winData.dwUnionChoice = WTD_CHOICE_FILE;
  547. winData.dwStateAction = WTD_STATEACTION_VERIFY;
  548. winData.hWVTStateData = 0;
  549. winData.dwProvFlags = 0x00000010;
  550. winData.pFile = &winFile;
  551. //
  552. // verify the signature
  553. //
  554. hr = pfnWinVerifyTrust( (HWND)0, &gAction, &winData);
  555. if (FAILED(hr))
  556. {
  557. //
  558. // The object isn't even trusted so just get out here
  559. //
  560. LOG_error("WinVerifyTrust(%s) found error 0x%0x.", pszFileName, hr);
  561. goto Return;
  562. }
  563. //
  564. // the real usage should never pass in WTD_UI_ALL. If this is the case,
  565. // then we are calling this recursively in order to force the show
  566. // a good but non-MS cert only, so no need to check MS cert again.
  567. //
  568. // or, in test mode, we always do this part
  569. //
  570. if (WTD_UI_ALL != dwUIChoice)
  571. {
  572. //
  573. // the rset of code is used to verify the signed cert is
  574. // a valid MS cert.
  575. //
  576. pProvData = pfnWTHelperProvDataFromStateData(winData.hWVTStateData);
  577. pProvSigner = pfnWTHelperGetProvSignerFromChain(
  578. (PCRYPT_PROVIDER_DATA) pProvData,
  579. 0, // first signer
  580. FALSE, // not a counter signer
  581. 0);
  582. //
  583. // check root cert then check leaf (signing) cert if that fails
  584. //
  585. // 0 is signing cert, csCertChain-1 is root cert
  586. //
  587. pProvCert = pfnWTHelperGetProvCertFromChain(pProvSigner, pProvSigner->csCertChain - 1);
  588. hr = VerifyMSRoot(shCrypt32DllInst, pProvCert->pCert);
  589. if (S_OK != hr)
  590. {
  591. pProvCert = pfnWTHelperGetProvCertFromChain(pProvSigner, 0);
  592. hr = VerifySpecialMSCerts(shCrypt32DllInst, pProvCert->pCert);
  593. }
  594. }
  595. Return:
  596. //
  597. // free the wintrust state that was used to get the cert in the chain
  598. //
  599. winData.dwStateAction = WTD_STATEACTION_CLOSE;
  600. pfnWinVerifyTrust( (HWND)0, &gAction, &winData);
  601. //#ifndef _WUV3TEST
  602. //
  603. // recursively call this function if not in test mode so we can show
  604. // UI for this non-MS but good cert.
  605. // Only the two functions checking MS cert will return S_FALSE
  606. //
  607. if (S_OK != hr)
  608. {
  609. if (WTD_UI_NOGOOD == dwUIChoice)
  610. {
  611. //
  612. // we need to show UI, so we will have to call this thing again
  613. // in case this is not a MS cert. From UI, if user clicks YES
  614. // then the return value will be S_OK;
  615. //
  616. hr = CheckWinTrust(pszFileName, WTD_UI_ALL);
  617. LOG_error("CheckWinTrust() found file not signed by a known MS cert. If user has not checked \"Always trust this\", UI should be shown, and user selected %s",
  618. SUCCEEDED(hr) ? "YES" : "NO");
  619. }
  620. else
  621. {
  622. LOG_error("CheckWinTrust() found file not signed by a known MS cert!");
  623. hr = TRUST_E_SUBJECT_NOT_TRUSTED;
  624. }
  625. }
  626. //#endif
  627. if (WTD_UI_ALL != dwUIChoice)
  628. {
  629. if (FAILED(hr))
  630. {
  631. LOG_error("CheckWinTrust(%s) returns 0x%0x", T2CA(pszFileName), hr);
  632. }
  633. else
  634. {
  635. LOG_out("CheckWinTrust(%s) returns S_OK", T2CA(pszFileName));
  636. }
  637. }
  638. Done:
  639. if (NULL != shWinTrustDllInst)
  640. {
  641. FreeLibrary(shWinTrustDllInst);
  642. shWinTrustDllInst = NULL;
  643. }
  644. if (NULL != shCrypt32DllInst)
  645. {
  646. FreeLibrary(shCrypt32DllInst);
  647. shCrypt32DllInst = NULL;
  648. }
  649. return (hr);
  650. }
  651. /////////////////////////////////////////////////////////////////////////////
  652. //
  653. // Public Function VerifyFile()
  654. //
  655. // This is a wrapper function for CheckWinTrust that both Whistler
  656. // and WU classic code should use.
  657. //
  658. // Input: szFileName - the file with complete path
  659. // fShowBadUI - whether pop up UI in cases
  660. // (1) inproperly signed signature,
  661. // (2) properly signed but not Microsoft signature
  662. //
  663. // Return: HRESULT - S_OK the file is signed with a valid MS cert
  664. // or error code.
  665. //
  666. // Note: If _WUV3TEST flag is set (for test build), then fShowBadUI is
  667. // ignored:
  668. // if reg key SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\wuv3test\WinTrustUI
  669. // is set to 1, then no UI is shown, and this function always return S_OK;
  670. // otherwise, UI always show no matter what cert, and return value is same
  671. // as the live build.
  672. //
  673. /////////////////////////////////////////////////////////////////////////////
  674. HRESULT VerifyFile(
  675. IN LPCTSTR szFileName,
  676. BOOL fShowBadUI /* = TRUE */
  677. )
  678. {
  679. DWORD dwUIChoice = WTD_UI_NOGOOD;
  680. if (!fShowBadUI)
  681. {
  682. dwUIChoice = WTD_UI_NONE;
  683. }
  684. return CheckWinTrust(szFileName, dwUIChoice);
  685. }