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.

786 lines
26 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // No portion of this source code may be reproduced
  6. // without express written permission of Microsoft Corporation.
  7. //
  8. // This source code is proprietary and confidential.
  9. //
  10. // SYSTEM: Industry Update
  11. //
  12. // CLASS: N/A
  13. // MODULE: TRUST.LIB
  14. // FILE: Trust.CPP
  15. //
  16. /////////////////////////////////////////////////////////////////////
  17. //
  18. // DESC: this file implements the functions used to make cabs
  19. // signed by certain providers trusted.
  20. //
  21. //
  22. // AUTHOR: Charles Ma, converted from WU CDMLIB
  23. // DATE: 10/4/2000
  24. //
  25. /////////////////////////////////////////////////////////////////////
  26. //
  27. // This file is copied from the Windows AutoUpdate sources at \nt\enduser\windows.com\lib\trust\trust.cpp,
  28. // modified to use BITS logging and remove UI.
  29. //
  30. #include "qmgrlib.h"
  31. #include <wintrust.h>
  32. #include <softpub.h>
  33. #include "trust.h"
  34. #if !defined(BITS_V12_ON_NT4)
  35. #include "trust.tmh"
  36. #endif
  37. HMODULE WINAPI LoadLibraryFromSystemDir(LPCTSTR szModule);
  38. /////////////////////////////////////////////////////////////////////////////
  39. //
  40. // typedefs for APIs used in the CheckTrust() function
  41. //
  42. // Since some of these APIs are new and only available on IE5 we have to
  43. // try to dynamically use them when available and do without the extra checks
  44. // when we are on an OS that has not been upgraded to the new crypto code.
  45. //
  46. /////////////////////////////////////////////////////////////////////////////
  47. #define WINTRUST _T("wintrust.dll")
  48. #define CRYPT32 _T("crypt32.dll")
  49. #if !defined(USES_IU_CONVERSION) && defined(USES_CONVERSION)
  50. #define USES_IU_CONVERSION USES_CONVERSION
  51. #endif
  52. //
  53. // declare a global crypt32.dll library handler, so we don't
  54. // need to load the library every time these functions are called.
  55. // NOTE: we do not release the library though. When the process of
  56. // calling this feature exits, the library is released.
  57. // same as wintrust.dll
  58. //
  59. static HINSTANCE shWinTrustDllInst = NULL;
  60. static HINSTANCE shCrypt32DllInst = NULL;
  61. //
  62. // define prototype for function WinVerifyTrust()
  63. // and declare a global variable to point to this function
  64. //
  65. typedef HRESULT
  66. (WINAPI * PFNWinVerifyTrust)(
  67. HWND hwnd, GUID *ActionID, LPVOID ActionData);
  68. PFNWinVerifyTrust pfnWinVerifyTrust = NULL;
  69. //
  70. // define prototype for function WTHelperProvDataFromStateData()
  71. // and declare a global variable to point to this function
  72. //
  73. typedef CRYPT_PROVIDER_DATA *
  74. (WINAPI * PFNWTHelperProvDataFromStateData)(
  75. HANDLE hStateData);
  76. PFNWTHelperProvDataFromStateData pfnWTHelperProvDataFromStateData = NULL;
  77. //
  78. // define prototype for function WTHelperGetProvSignerFromChain()
  79. // and declare a global variable to point to this function
  80. //
  81. typedef CRYPT_PROVIDER_SGNR *
  82. (WINAPI * PFNWTHelperGetProvSignerFromChain)(
  83. CRYPT_PROVIDER_DATA *pProvData,
  84. DWORD idxSigner,
  85. BOOL fCounterSigner,
  86. DWORD idxCounterSigner);
  87. PFNWTHelperGetProvSignerFromChain pfnWTHelperGetProvSignerFromChain = NULL;
  88. //
  89. // define prototype for function PFNWTHelperGetProvCertFromChain()
  90. // and declare a global variable to point to this function
  91. //
  92. typedef CRYPT_PROVIDER_CERT *
  93. (WINAPI * PFNWTHelperGetProvCertFromChain)(
  94. CRYPT_PROVIDER_SGNR *pSgnr,
  95. DWORD idxCert);
  96. PFNWTHelperGetProvCertFromChain pfnWTHelperGetProvCertFromChain = NULL;
  97. //
  98. // define prototype for function CryptHashPublicKeyInfo()
  99. // and declare a global variable to point to this function
  100. //
  101. typedef BOOL
  102. (WINAPI * PFNCryptHashPublicKeyInfo)(
  103. HCRYPTPROV hCryptProv,
  104. ALG_ID Algid,
  105. DWORD dwFlags,
  106. DWORD dwCertEncodingType,
  107. PCERT_PUBLIC_KEY_INFO pInfo,
  108. BYTE *pbComputedHash,
  109. DWORD *pcbComputedHash);
  110. PFNCryptHashPublicKeyInfo pfnCryptHashPublicKeyInfo = NULL;
  111. //
  112. // define prototype for function CertGetCertificateContextProperty()
  113. // and declare a global variable to point to this function
  114. //
  115. typedef BOOL
  116. (WINAPI * PFNCertGetCertificateContextProperty)(
  117. PCCERT_CONTEXT pCertContext,
  118. DWORD dwPropId,
  119. void *pvData,
  120. DWORD *pcbData);
  121. PFNCertGetCertificateContextProperty pfnCertGetCertificateContextProperty = NULL;
  122. /////////////////////////////////////////////////////////////////////////////
  123. //
  124. // pre-defined cert data to check against
  125. //
  126. /////////////////////////////////////////////////////////////////////////////
  127. //
  128. // The following are sha1 key identifier for two Microsoft root certificates.
  129. // Note that they are "subject" hashes, not thumbprints or serial numbers.
  130. //
  131. static const BYTE rgbSignerRootKeyIds[40] = {
  132. 0x4A, 0x5C, 0x75, 0x22, 0xAA, 0x46, 0xBF, 0xA4, 0x08, 0x9D, // the original MS root
  133. 0x39, 0x97, 0x4E, 0xBD, 0xB4, 0xA3, 0x60, 0xF7, 0xA0, 0x1D, // don't know its validity period
  134. 0x0E, 0xAC, 0x82, 0x60, 0x40, 0x56, 0x27, 0x97, 0xE5, 0x25, // the new "son of MS root". For reference,
  135. 0x13, 0xFC, 0x2A, 0xE1, 0x0A, 0x53, 0x95, 0x59, 0xE4, 0xA4 // subject is "Microsoft Root Certificate Authority", valid from May 2001 to May 2021
  136. };
  137. //
  138. // define the size of each hash values in the known id buffer
  139. // for special certs.
  140. //
  141. const size_t ExpectedKnownCertHashSize = 20;
  142. //
  143. // this is the size of buffer to receive the cert hash value
  144. // it must be not less than the largest number in the
  145. // above-defined array
  146. //
  147. const size_t ShaBufSize = 20;
  148. //
  149. // id buffer to store SH1 hashing values of known Microsoft
  150. // certs (signature) that we should recognize.
  151. // Warning: the size of this buffer should match the sum
  152. // of size_t values defined above.
  153. //
  154. // The AutoUpdate code allowed MSNBC and MSN certificates but BITS does not.
  155. //
  156. static const BYTE rgbSpecialCertId[140] = {
  157. 0xB1,0x59,0xA5,0x2E,0x3D,0xD8,0xCE,0xCD,0x3A,0x9A,0x4A,0x7A,0x73,0x92,0xAA,0x8D,0xA7,0xE7,0xD6,0x7F, // MS cert
  158. // 0xB1,0xC7,0x75,0xE0,0x4A,0x9D,0xFD,0x23,0xB6,0x18,0x97,0x11,0x5E,0xF6,0xEA,0x6B,0x99,0xEC,0x76,0x1D, // MSN cert
  159. // 0x11,0xC7,0x10,0xF3,0xCB,0x6C,0x43,0xE1,0x66,0xEC,0x64,0x1C,0x7C,0x01,0x17,0xC4,0xB4,0x10,0x35,0x30, // MSNBC cert
  160. // 0x95,0x25,0x58,0xD4,0x07,0xDE,0x4A,0xFD,0xAE,0xBA,0x13,0x72,0x83,0xC2,0xB3,0x37,0x04,0x90,0xC9,0x8A, // MSN Europe
  161. 0x72,0x54,0x14,0x91,0x1D,0x6E,0x10,0x84,0x8E,0x0F,0xFA,0xA0,0xB0,0xA1,0x65,0xBF,0x44,0x8F,0x9F,0x6D, // MS Europe
  162. 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
  163. 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
  164. 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
  165. 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
  166. 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
  167. };
  168. /////////////////////////////////////////////////////////////////////////////
  169. //
  170. // Private Function ULONG CompareMem(PVOID pBlock1, PVOID pBlock2, ULONG Length)
  171. //
  172. // This function acts in the same way as RtlCompareMemory()
  173. //
  174. //
  175. // Input: two pointers to two memory blocks, and a byte size to compare
  176. // Return: the number of bytes that compared as equal.
  177. // If all bytes compare as equal, the input Length is returned.
  178. // If any pointer is NULL, 0 is returned.
  179. //
  180. /////////////////////////////////////////////////////////////////////////////
  181. ULONG CompareMem(const BYTE* pBlock1, const BYTE* pBlock2, ULONG Length)
  182. {
  183. ULONG uLen = 0L;
  184. if (pBlock1 != NULL && pBlock2 != NULL)
  185. {
  186. for (; uLen < Length; uLen++, pBlock1++, pBlock2++)
  187. {
  188. if (*pBlock1 != *pBlock2) return uLen;
  189. }
  190. }
  191. return uLen;
  192. }
  193. /////////////////////////////////////////////////////////////////////////////
  194. //
  195. // Private Function VerifyMSRoot()
  196. //
  197. // This function takes the passed-in certificate as a root cert,
  198. // and verifies its public key hash value is the same as one of the
  199. // known "Microsoft Root Authority" cert values.
  200. //
  201. //
  202. // Input: hCrypt32DllInst - handle point to loaded crypt32.dll library
  203. // pRootCert - the certificate context of the root cert
  204. //
  205. // Return: HRESULT - result of execution, S_OK if matched.
  206. // the result code, in case of error, are code retuned by
  207. // crypt32.dll, with these the exception of E_INVALIDARG if
  208. // the passed-in parameters are NULL.
  209. //
  210. /////////////////////////////////////////////////////////////////////////////
  211. HRESULT VerifyMSRoot(
  212. HINSTANCE hCrypt32DllInst, // handle points to loaded crypt32.dll library
  213. PCCERT_CONTEXT pRootCert
  214. )
  215. {
  216. HRESULT hr = S_OK;
  217. BYTE rgbKeyId[ExpectedKnownCertHashSize];
  218. DWORD cbKeyId = sizeof(rgbKeyId);
  219. LogInfo("VerifyMSRoot()");
  220. //
  221. // valid parameter values
  222. //
  223. if (NULL == hCrypt32DllInst || NULL == pRootCert)
  224. {
  225. hr = E_INVALIDARG;
  226. goto ErrHandler;
  227. }
  228. //
  229. // get the function we need from the passed in library handle
  230. // If not available, return error
  231. //
  232. if (NULL == (pfnCryptHashPublicKeyInfo = (PFNCryptHashPublicKeyInfo)
  233. GetProcAddress(hCrypt32DllInst, "CryptHashPublicKeyInfo")))
  234. {
  235. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  236. goto ErrHandler;
  237. }
  238. //
  239. // get the public key hash value of this cert
  240. //
  241. ZeroMemory(rgbKeyId, sizeof(rgbKeyId));
  242. if (!pfnCryptHashPublicKeyInfo(
  243. 0, // use default crypto svc provider
  244. CALG_SHA1, // use SHA algorithm
  245. 0, // dwFlags
  246. X509_ASN_ENCODING,
  247. &pRootCert->pCertInfo->SubjectPublicKeyInfo,
  248. rgbKeyId,
  249. &cbKeyId
  250. ))
  251. {
  252. hr = HRESULT_FROM_WIN32(GetLastError());
  253. goto ErrHandler;
  254. }
  255. //
  256. // compare the hash value of public key of this root cert with the known MS root cert values
  257. //
  258. if (ExpectedKnownCertHashSize != cbKeyId ||
  259. (cbKeyId != CompareMem(rgbSignerRootKeyIds, rgbKeyId, cbKeyId) &&
  260. cbKeyId != CompareMem(rgbSignerRootKeyIds + ExpectedKnownCertHashSize, rgbKeyId, cbKeyId)
  261. )
  262. )
  263. {
  264. hr = S_FALSE;
  265. }
  266. ErrHandler:
  267. if (FAILED(hr))
  268. {
  269. LogError("returning %x", hr);
  270. }
  271. else
  272. {
  273. LogInfo("returning %x", hr);
  274. }
  275. return hr;
  276. }
  277. /////////////////////////////////////////////////////////////////////////////
  278. //
  279. // Private Function VerifySpecialMSCerts()
  280. //
  281. // This function takes the passed-in certificate as a leaf cert,
  282. // and verifies its hash value matches the hash value of one of
  283. // known Microsoft special certs that does not have MS root.
  284. //
  285. // See definition of rgbSpecialCertId[] for a complete list of certs to match.
  286. //
  287. // Input: hCrypt32DllInst - handle point to loaded crypt32.dll library
  288. // pRootCert - the certificate context of the root cert
  289. // pbSha1HashVal - if not NULL, compare to this one, instead of
  290. // hard-coded hash values. this is the case
  291. // of working on 3rd party package
  292. //
  293. // Return: HRESULT - result of execution, S_OK if matched.
  294. // if not matched, CERT_E_UNTRUSTEDROOT, or
  295. // E_INVALIDARG if arguments not right, or
  296. // crypt32.dll error returned by API calls
  297. //
  298. /////////////////////////////////////////////////////////////////////////////
  299. HRESULT VerifyKnownCerts(
  300. HINSTANCE hCrypt32DllInst, // handle point to loaded crypt32.dll librar
  301. PCCERT_CONTEXT pLeafCert,
  302. pCERT_HASH_ARRAY pKnownCertsData
  303. )
  304. {
  305. HRESULT hr = S_FALSE;
  306. BYTE btShaBuffer[ShaBufSize];
  307. DWORD dwSize = sizeof(btShaBuffer);
  308. BYTE const * pId;
  309. LogInfo("VerifyKnownCerts()");
  310. //
  311. // valid parameter values
  312. //
  313. if (NULL == hCrypt32DllInst || NULL == pLeafCert)
  314. {
  315. hr = E_INVALIDARG;
  316. goto ErrHandler;
  317. }
  318. //
  319. // get the function we need from the passed in library handle
  320. // If not available, return error
  321. //
  322. if (NULL == (pfnCertGetCertificateContextProperty = (PFNCertGetCertificateContextProperty)
  323. GetProcAddress(hCrypt32DllInst, "CertGetCertificateContextProperty")))
  324. {
  325. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  326. goto ErrHandler;
  327. }
  328. //
  329. // find out the id hash of leaf cert
  330. //
  331. ZeroMemory(btShaBuffer, dwSize);
  332. if (!pfnCertGetCertificateContextProperty(
  333. pLeafCert, // pCertContext
  334. CERT_SHA1_HASH_PROP_ID, // dwPropId
  335. btShaBuffer,
  336. &dwSize
  337. ))
  338. {
  339. hr = GetLastError();
  340. goto ErrHandler;
  341. }
  342. if (NULL == pKnownCertsData)
  343. {
  344. int i;
  345. //
  346. // iterrate through all known id hash values to see if this file is signed
  347. // with any of these special certs.
  348. //
  349. hr = S_FALSE;
  350. for (i = 0,pId = rgbSpecialCertId;
  351. i < sizeof(rgbSpecialCertId)/ExpectedKnownCertHashSize;
  352. i++, pId += ExpectedKnownCertHashSize)
  353. {
  354. if (ExpectedKnownCertHashSize == dwSize &&
  355. dwSize == CompareMem(btShaBuffer, pId, dwSize))
  356. {
  357. //
  358. // found a matching known cert!
  359. //
  360. hr = S_OK;
  361. LogInfo("Found hash matching on #%d of %d MS certs!", i, sizeof(rgbSpecialCertId)/ExpectedKnownCertHashSize);
  362. break;
  363. }
  364. }
  365. }
  366. else
  367. {
  368. //
  369. // check if the retrieved hashing value matches the one passed in.
  370. //
  371. UINT i;
  372. LogInfo("Comparing retrieved hash value with passed-in key");
  373. hr = S_FALSE;
  374. for (i = 0, pId = pKnownCertsData->pCerts; i < pKnownCertsData->uiCount;
  375. i++, pId += HASH_VAL_SIZE)
  376. {
  377. if (dwSize == HASH_VAL_SIZE &&
  378. HASH_VAL_SIZE == CompareMem(btShaBuffer, pId, HASH_VAL_SIZE))
  379. {
  380. hr = S_OK;
  381. LogInfo("Found hash matching #%d of %d passed-in certs!",
  382. i, pKnownCertsData->uiCount);
  383. break;
  384. }
  385. }
  386. }
  387. ErrHandler:
  388. if (FAILED(hr))
  389. {
  390. LogError("returning %x", hr);
  391. }
  392. else
  393. {
  394. LogInfo("returning %x", hr);
  395. }
  396. return hr;
  397. }
  398. /////////////////////////////////////////////////////////////////////////////
  399. //
  400. // Private Function CheckWinTrust()
  401. //
  402. // This function will return the HRESULT for the trust state on the
  403. // specified file. The file can be pointing to any URL or local file.
  404. // The verification will be done by the wintrust.dll.
  405. //
  406. // dwCheckRevocation is WTD_REVOKE_NONE (default) or WTD_REVOKE_WHOLE_CHAIN.
  407. //
  408. // Input: Fully qualified filename, dwCheckRevocation
  409. // Return: HRESULT - result of execution
  410. //
  411. /////////////////////////////////////////////////////////////////////////////
  412. HRESULT CheckWinTrust(LPCTSTR pszFileName, pCERT_HASH_ARRAY pCertsData, DWORD dwCheckRevocation)
  413. {
  414. LogInfo("CheckWinTrust()");
  415. // Now verify the file
  416. WINTRUST_DATA winData;
  417. WINTRUST_FILE_INFO winFile;
  418. GUID gAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  419. CRYPT_PROVIDER_DATA const *pProvData = NULL;
  420. CRYPT_PROVIDER_SGNR *pProvSigner = NULL; // recursively call this function if not in test mode so we can show
  421. // UI for this non-MS but good cert.
  422. CRYPT_PROVIDER_CERT *pProvCert = NULL;
  423. HRESULT hr = S_OK;
  424. //
  425. // dynamically load the wintrust.dll
  426. //
  427. if (NULL == shWinTrustDllInst)
  428. {
  429. if (NULL == (shWinTrustDllInst = LoadLibraryFromSystemDir(WINTRUST)))
  430. {
  431. hr = HRESULT_FROM_WIN32(GetLastError());
  432. LogError("Failed to load library " WINTRUST ", hr %x.", hr);
  433. goto Done;
  434. }
  435. }
  436. //
  437. // dynamically load the crypt32.dll, which will be used by the two
  438. // helper functions to verify the cert is MS cert
  439. //
  440. if (NULL == shCrypt32DllInst)
  441. {
  442. if (NULL == (shCrypt32DllInst = LoadLibraryFromSystemDir(CRYPT32)))
  443. {
  444. hr = HRESULT_FROM_WIN32(GetLastError());
  445. LogError("Failed to load library " CRYPT32 ", hr %x.", hr);
  446. goto Done;
  447. }
  448. }
  449. //
  450. // find the functions we need
  451. //
  452. if (NULL == (pfnWinVerifyTrust = (PFNWinVerifyTrust)
  453. GetProcAddress(shWinTrustDllInst, "WinVerifyTrust")) ||
  454. NULL == (pfnWTHelperProvDataFromStateData = (PFNWTHelperProvDataFromStateData)
  455. GetProcAddress(shWinTrustDllInst, "WTHelperProvDataFromStateData")) ||
  456. NULL == (pfnWTHelperGetProvSignerFromChain = (PFNWTHelperGetProvSignerFromChain)
  457. GetProcAddress(shWinTrustDllInst, "WTHelperGetProvSignerFromChain")) ||
  458. NULL == (pfnWTHelperGetProvCertFromChain = (PFNWTHelperGetProvCertFromChain)
  459. GetProcAddress(shWinTrustDllInst, "WTHelperGetProvCertFromChain")))
  460. {
  461. //
  462. // at least one function was not found in the loaded cryp32.dll libary.
  463. // we can not continue, jsut quit.
  464. // NOTE: this shouldn't happen since we have tried to get
  465. // the least common denomination of different version of this dll
  466. // on both IE4 and IE5
  467. //
  468. hr = HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION);
  469. LogError("Failed to load procs from " CRYPT32 ", hr %x.", hr);
  470. goto Done;
  471. }
  472. //
  473. // initialize the data structure used to verify trust
  474. //
  475. winFile.cbStruct = sizeof(WINTRUST_FILE_INFO);
  476. winFile.hFile = INVALID_HANDLE_VALUE;
  477. winFile.pcwszFilePath = pszFileName;
  478. winFile.pgKnownSubject = NULL;
  479. winData.cbStruct = sizeof(WINTRUST_DATA);
  480. winData.pPolicyCallbackData = NULL;
  481. winData.pSIPClientData = NULL;
  482. winData.dwUIChoice = WTD_UI_NONE;
  483. winData.fdwRevocationChecks = WTD_REVOKE_NONE;
  484. winData.dwUnionChoice = WTD_CHOICE_FILE;
  485. winData.dwStateAction = WTD_STATEACTION_VERIFY;
  486. winData.hWVTStateData = 0;
  487. winData.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
  488. winData.pFile = &winFile;
  489. if (dwCheckRevocation == WTD_REVOKE_WHOLECHAIN)
  490. {
  491. winData.fdwRevocationChecks = WTD_REVOKE_WHOLECHAIN;
  492. winData.dwProvFlags = WTD_REVOCATION_CHECK_CHAIN;
  493. }
  494. //
  495. // verify the signature
  496. //
  497. hr = pfnWinVerifyTrust( (HWND)0, &gAction, &winData);
  498. //
  499. // Ignore errors when retrieving Cert Revocation List (CRL). This
  500. // just means the list itself couldn't be retrieved, not that the
  501. // current cert was invalid or revoked. (KenSh, 2002/01/17)
  502. //
  503. if (hr == CERT_E_REVOCATION_FAILURE)
  504. {
  505. hr = S_OK;
  506. }
  507. if (FAILED(hr))
  508. {
  509. //
  510. // The object isn't signed, so just leave.
  511. //
  512. LogError("WinVerifyTrust on '%S' found error 0x%0x.", pszFileName, hr);
  513. goto Return;
  514. }
  515. //
  516. // if come to here, it means all above verified okay.
  517. //
  518. // the rest of code is used to verify the signed cert is a known cert.
  519. //
  520. hr = S_FALSE;
  521. pProvData = pfnWTHelperProvDataFromStateData(winData.hWVTStateData);
  522. pProvSigner = pfnWTHelperGetProvSignerFromChain(
  523. (PCRYPT_PROVIDER_DATA) pProvData,
  524. 0, // first signer
  525. FALSE, // not a counter signer
  526. 0);
  527. //
  528. // check root cert then check leaf (signing) cert if that fails
  529. //
  530. // 0 is signing cert, csCertChain-1 is root cert
  531. //
  532. if (NULL == pCertsData)
  533. {
  534. //
  535. // if caller does not specify a hash value, then it means we want
  536. // to verify if this cert is known MS cert. We will first
  537. // try to find out if it is signed with a cert that has MS as root.
  538. //
  539. pProvCert = pfnWTHelperGetProvCertFromChain(pProvSigner, pProvSigner->csCertChain - 1);
  540. hr = VerifyMSRoot(shCrypt32DllInst, pProvCert->pCert);
  541. }
  542. if (S_OK != hr)
  543. {
  544. pProvCert = pfnWTHelperGetProvCertFromChain(pProvSigner, 0);
  545. hr = VerifyKnownCerts(shCrypt32DllInst, pProvCert->pCert, pCertsData);
  546. }
  547. Return:
  548. //
  549. // free the wintrust state that was used to get the cert in the chain
  550. //
  551. winData.dwStateAction = WTD_STATEACTION_CLOSE;
  552. pfnWinVerifyTrust( (HWND)0, &gAction, &winData);
  553. //
  554. // Only the two functions checking MS cert will return S_FALSE
  555. //
  556. if (S_OK != hr)
  557. {
  558. LogError("CheckWinTrust() found file not signed by a known cert!");
  559. LogError("Digital Signatures on file %S are not trusted, hr %x", pszFileName, hr);
  560. hr = TRUST_E_SUBJECT_NOT_TRUSTED;
  561. }
  562. else
  563. {
  564. LogInfo("CheckWinTrust(%S) returns S_OK", pszFileName);
  565. }
  566. Done:
  567. if (NULL != shWinTrustDllInst)
  568. {
  569. FreeLibrary(shWinTrustDllInst);
  570. shWinTrustDllInst = NULL;
  571. }
  572. if (NULL != shCrypt32DllInst)
  573. {
  574. FreeLibrary(shCrypt32DllInst);
  575. shCrypt32DllInst = NULL;
  576. }
  577. return (hr);
  578. }
  579. /////////////////////////////////////////////////////////////////////////////
  580. //
  581. // Public Function VerifyFileTrust()
  582. //
  583. // This is a wrapper function for CheckWinTrust that both Whistler
  584. // and WU classic code should use.
  585. //
  586. // Input:
  587. // szFileName - the file with complete path
  588. // pCertsData - hash value of a known good cert, or NULL to use the default list
  589. // fCheckRevocation - TRUE to check against a CRL, FALSE to skip the CRL check
  590. //
  591. // Return: HRESULT - S_OK the file is signed with a valid known cert
  592. // or error code.
  593. //
  594. /////////////////////////////////////////////////////////////////////////////
  595. HRESULT VerifyFileTrust(
  596. IN LPCTSTR szFileName,
  597. IN pCERT_HASH_ARRAY pCertsData,
  598. BOOL fCheckRevocation /*=FALSE*/
  599. )
  600. {
  601. DWORD dwCheckRevocation = fCheckRevocation ? WTD_REVOKE_WHOLECHAIN : WTD_REVOKE_NONE;
  602. return CheckWinTrust(szFileName, pCertsData, dwCheckRevocation);
  603. }
  604. // **************************************************************************
  605. static
  606. BOOL UseFullPath(void)
  607. {
  608. static BOOL s_fUseFullPath = TRUE;
  609. static BOOL s_fInit = FALSE;
  610. OSVERSIONINFO osvi;
  611. if (s_fInit)
  612. return s_fUseFullPath;
  613. ZeroMemory(&osvi, sizeof(osvi));
  614. osvi.dwOSVersionInfoSize = sizeof(osvi);
  615. if (GetVersionEx(&osvi))
  616. {
  617. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
  618. (osvi.dwMajorVersion > 5 ||
  619. (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion >= 1)))
  620. {
  621. s_fUseFullPath = FALSE;
  622. }
  623. s_fInit = TRUE;
  624. }
  625. return s_fUseFullPath;
  626. }
  627. // **************************************************************************
  628. HMODULE WINAPI LoadLibraryFromSystemDir(LPCTSTR szModule)
  629. /*
  630. Loads a module in a safe way, immune to fake DLLs placed in the current directory or other
  631. parts of the default search path.
  632. */
  633. {
  634. HRESULT hr = NOERROR;
  635. HMODULE hmod = NULL;
  636. TCHAR szModulePath[MAX_PATH + 1];
  637. if (szModule == NULL)
  638. {
  639. SetLastError(ERROR_INVALID_PARAMETER);
  640. goto done;
  641. }
  642. if (UseFullPath())
  643. {
  644. DWORD cch;
  645. // if the function call fails, make the buffer an empty string, so
  646. // we will just use the dll name in the append below.
  647. cch = GetSystemDirectory(szModulePath, RTL_NUMBER_OF(szModulePath));
  648. if (cch == 0 || cch >= RTL_NUMBER_OF(szModulePath))
  649. {
  650. szModulePath[0] = _T('\0');
  651. }
  652. else
  653. {
  654. hr = StringCchCat( szModulePath, RTL_NUMBER_OF(szModulePath), _T("\\") );
  655. if (FAILED(hr))
  656. {
  657. SetLastError(HRESULT_CODE(hr));
  658. goto done;
  659. }
  660. }
  661. }
  662. else
  663. {
  664. szModulePath[0] = _T('\0');
  665. }
  666. hr = StringCchCat( szModulePath, RTL_NUMBER_OF(szModulePath), szModule );
  667. if (FAILED(hr))
  668. {
  669. SetLastError(HRESULT_CODE(hr));
  670. goto done;
  671. }
  672. hmod = LoadLibraryEx(szModulePath, NULL, 0);
  673. if (hmod == NULL)
  674. goto done;
  675. done:
  676. return hmod;
  677. }