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.

978 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: gettrst.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "global.hxx"
  11. #include <dbgdef.h>
  12. #include "wintrustp.h"
  13. #include "crypthlp.h"
  14. extern HINSTANCE HinstDll;
  15. extern HMODULE HmodRichEdit;
  16. //////////////////////////////////////////////////////////////////////////////////////
  17. //
  18. //////////////////////////////////////////////////////////////////////////////////////
  19. static BOOL IsUntrustedRootProblem(WINTRUST_DATA *pWTD)
  20. {
  21. CRYPT_PROVIDER_DATA *pProvData = NULL;
  22. CRYPT_PROVIDER_SGNR *pProvSigner = NULL;
  23. CRYPT_PROVIDER_CERT *pCryptProviderCert;
  24. DWORD i;
  25. pProvData = WTHelperProvDataFromStateData(pWTD->hWVTStateData);
  26. pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0);
  27. if (pProvSigner)
  28. {
  29. // get all certs in the chain
  30. for (i=0; i<pProvSigner->csCertChain; i++)
  31. {
  32. pCryptProviderCert = WTHelperGetProvCertFromChain(pProvSigner, i);
  33. if (pCryptProviderCert != NULL)
  34. {
  35. if (pCryptProviderCert->dwError != ERROR_SUCCESS)
  36. {
  37. return FALSE;
  38. }
  39. }
  40. else
  41. {
  42. return FALSE;
  43. }
  44. }
  45. }
  46. else
  47. {
  48. return FALSE;
  49. }
  50. return TRUE;
  51. }
  52. //////////////////////////////////////////////////////////////////////////////////////
  53. //
  54. //////////////////////////////////////////////////////////////////////////////////////
  55. static DWORD GetFinalErrorFromChain(PCERT_VIEW_HELPER pviewhelp)
  56. {
  57. int i;
  58. DWORD dwErr = 0;
  59. for (i=((int)pviewhelp->cpCryptProviderCerts)-1; i>= 0; i--)
  60. {
  61. dwErr = pviewhelp->rgpCryptProviderCerts[i]->dwError;
  62. if (((dwErr == CERT_E_UNTRUSTEDROOT) || (dwErr == CERT_E_UNTRUSTEDTESTROOT)) &&
  63. (pviewhelp->fIgnoreUntrustedRoot))
  64. {
  65. dwErr = 0;
  66. }
  67. else if (dwErr != 0)
  68. {
  69. break;
  70. }
  71. }
  72. return dwErr;
  73. }
  74. //////////////////////////////////////////////////////////////////////////////////////
  75. //
  76. //////////////////////////////////////////////////////////////////////////////////////
  77. static void GetCertChainErrorString(PCERT_VIEW_HELPER pviewhelp)
  78. {
  79. WCHAR szErrorString[CRYPTUI_MAX_STRING_SIZE];
  80. DWORD i;
  81. DWORD dwChainError;
  82. //
  83. // free the error string if one already exists
  84. //
  85. if (pviewhelp->pwszErrorString != NULL)
  86. {
  87. free(pviewhelp->pwszErrorString);
  88. pviewhelp->pwszErrorString = NULL;
  89. }
  90. // If they ask to be warned about local/remote differences,
  91. // always display this warning
  92. if (pviewhelp->fWarnRemoteTrust)
  93. {
  94. LoadStringU(HinstDll, IDS_WARNREMOTETRUST_ERROR, szErrorString, ARRAYSIZE(szErrorString));
  95. goto StringLoaded;
  96. }
  97. //
  98. // if there was no over all chain error, then the only problem,
  99. // is if there are no usages
  100. //
  101. if (pviewhelp->dwChainError == 0)
  102. {
  103. if (pviewhelp->cUsages == NULL)
  104. {
  105. LoadStringU(HinstDll, IDS_NOVALIDUSAGES_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  106. }
  107. else
  108. {
  109. return;
  110. }
  111. }
  112. if ((pviewhelp->dwChainError == CERT_E_UNTRUSTEDROOT) ||
  113. (pviewhelp->dwChainError == CERT_E_UNTRUSTEDTESTROOT))
  114. {
  115. //
  116. // if we are ignoring untrusted roots, then just return
  117. //
  118. if (pviewhelp->fIgnoreUntrustedRoot)
  119. {
  120. return;
  121. }
  122. //
  123. // if we are just warning the user about untrusted root AND the root
  124. // cert is in the remote root store then load that string
  125. //
  126. if (pviewhelp->fWarnUntrustedRoot && pviewhelp->fRootInRemoteStore)
  127. {
  128. //
  129. // if this is a root cert then show the error for a root
  130. //
  131. if (pviewhelp->cpCryptProviderCerts == 1 && (pviewhelp->rgpCryptProviderCerts[0])->fSelfSigned)
  132. {
  133. LoadStringU(HinstDll, IDS_WARNUNTRUSTEDROOT_ERROR_ROOTCERT, szErrorString, ARRAYSIZE(szErrorString));
  134. }
  135. else
  136. {
  137. LoadStringU(HinstDll, IDS_WARNUNTRUSTEDROOT_ERROR, szErrorString, ARRAYSIZE(szErrorString));
  138. }
  139. }
  140. else
  141. {
  142. //
  143. // if this is a root cert then show the error for a root
  144. //
  145. if (pviewhelp->cpCryptProviderCerts == 1 && (pviewhelp->rgpCryptProviderCerts[0])->fSelfSigned)
  146. {
  147. LoadStringU(HinstDll, IDS_UNTRUSTEDROOT_ROOTCERT_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  148. }
  149. else
  150. {
  151. LoadStringU(HinstDll, IDS_UNTRUSTEDROOT_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  152. }
  153. }
  154. }
  155. else if (pviewhelp->dwChainError == CERT_E_REVOKED)
  156. {
  157. LoadStringU(HinstDll, IDS_CERTREVOKED_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  158. }
  159. else if (pviewhelp->dwChainError == TRUST_E_CERT_SIGNATURE)
  160. {
  161. LoadStringU(HinstDll, IDS_CERTBADSIGNATURE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  162. }
  163. else if (pviewhelp->dwChainError == CERT_E_EXPIRED)
  164. {
  165. LoadStringU(HinstDll, IDS_CERTEXPIRED_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  166. }
  167. else if (pviewhelp->dwChainError == CERT_E_VALIDITYPERIODNESTING)
  168. {
  169. LoadStringU(HinstDll, IDS_TIMENESTING_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  170. }
  171. else if (pviewhelp->dwChainError == CERT_E_WRONG_USAGE)
  172. {
  173. LoadStringU(HinstDll, IDS_WRONG_USAGE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  174. }
  175. else if (pviewhelp->dwChainError == TRUST_E_BASIC_CONSTRAINTS)
  176. {
  177. LoadStringU(HinstDll, IDS_BASIC_CONSTRAINTS_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  178. }
  179. else if (pviewhelp->dwChainError == CERT_E_PURPOSE)
  180. {
  181. LoadStringU(HinstDll, IDS_PURPOSE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  182. }
  183. else if (pviewhelp->dwChainError == CERT_E_REVOCATION_FAILURE)
  184. {
  185. LoadStringU(HinstDll, IDS_REVOCATION_FAILURE_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  186. }
  187. else if (pviewhelp->dwChainError == CERT_E_CHAINING)
  188. {
  189. LoadStringU(HinstDll, IDS_CANTBUILDCHAIN_ERROR_TREE, szErrorString, ARRAYSIZE(szErrorString));
  190. }
  191. else if (pviewhelp->dwChainError == TRUST_E_EXPLICIT_DISTRUST)
  192. {
  193. LoadStringU(HinstDll, IDS_EXPLICITDISTRUST_ERROR, szErrorString, ARRAYSIZE(szErrorString));
  194. }
  195. else if (pviewhelp->dwChainError != 0)
  196. {
  197. //
  198. // this is not an error we know about, so call the general
  199. // error string function
  200. //
  201. GetUnknownErrorString(&(pviewhelp->pwszErrorString), pviewhelp->dwChainError);
  202. }
  203. StringLoaded:
  204. if (pviewhelp->pwszErrorString == NULL)
  205. {
  206. pviewhelp->pwszErrorString = AllocAndCopyWStr(szErrorString);
  207. }
  208. }
  209. // Returned string must be freed via LocalFree()
  210. LPWSTR
  211. FormatRevocationStatus(
  212. IN PCERT_CHAIN_ELEMENT pElement
  213. )
  214. {
  215. LPWSTR pwszRevStatus = NULL;
  216. UINT ids = IDS_REV_STATUS_UNKNOWN_ERROR;
  217. static const WCHAR wszNoTime[] = L"...";
  218. LPWSTR pwszArg1 = (LPWSTR) wszNoTime;
  219. LPWSTR pwszArg2 = (LPWSTR) wszNoTime;
  220. LPWSTR pwszTime1 = NULL;
  221. LPWSTR pwszTime2 = NULL;
  222. LPWSTR pwszErrStr = NULL;
  223. DWORD dwRevResult;
  224. PCERT_REVOCATION_INFO pRevInfo;
  225. PCERT_REVOCATION_CRL_INFO pCrlInfo;
  226. pRevInfo = pElement->pRevocationInfo;
  227. if (NULL == pRevInfo)
  228. return NULL;
  229. dwRevResult = pRevInfo->dwRevocationResult;
  230. pCrlInfo = pRevInfo->pCrlInfo;
  231. switch (dwRevResult) {
  232. case ERROR_SUCCESS:
  233. ids = IDS_REV_STATUS_OK;
  234. // Fall through
  235. case CRYPT_E_REVOCATION_OFFLINE:
  236. if (pCrlInfo) {
  237. PCCRL_CONTEXT pCrl;
  238. pCrl = pCrlInfo->pDeltaCrlContext;
  239. if (NULL == pCrl)
  240. pCrl = pCrlInfo->pBaseCrlContext;
  241. if (pCrl) {
  242. BOOL fFormatDate;
  243. fFormatDate = FormatDateString(
  244. &pwszTime1,
  245. pCrl->pCrlInfo->ThisUpdate,
  246. TRUE, // fIncludeTime
  247. TRUE, // fLongFormat
  248. NULL // hwnd
  249. );
  250. if (fFormatDate) {
  251. pwszArg1 = pwszTime1;
  252. if (I_CryptIsZeroFileTime(&pCrl->pCrlInfo->NextUpdate))
  253. pwszArg2 = (LPWSTR) wszNoTime;
  254. else {
  255. fFormatDate = FormatDateString(
  256. &pwszTime2,
  257. pCrl->pCrlInfo->NextUpdate,
  258. TRUE, // fIncludeTime
  259. TRUE, // fLongFormat
  260. NULL // hwnd
  261. );
  262. if (fFormatDate)
  263. pwszArg2 = pwszTime2;
  264. }
  265. }
  266. if (fFormatDate) {
  267. switch (dwRevResult) {
  268. case ERROR_SUCCESS:
  269. ids = IDS_REV_STATUS_OK_WITH_CRL;
  270. break;
  271. case CRYPT_E_REVOCATION_OFFLINE:
  272. ids = IDS_REV_STATUS_OFFLINE_WITH_CRL;
  273. break;
  274. }
  275. }
  276. }
  277. }
  278. break;
  279. case CRYPT_E_REVOKED:
  280. if (pCrlInfo && pCrlInfo->pCrlEntry) {
  281. if (FormatDateString(
  282. &pwszTime1,
  283. pCrlInfo->pCrlEntry->RevocationDate,
  284. TRUE, // fIncludeTime
  285. TRUE, // fLongFormat
  286. NULL // hwnd
  287. )) {
  288. ids = IDS_REV_STATUS_REVOKED_ON;
  289. pwszArg1 = pwszTime1;
  290. }
  291. }
  292. break;
  293. default:
  294. break;
  295. }
  296. if (IDS_REV_STATUS_UNKNOWN_ERROR == ids) {
  297. GetUnknownErrorString(&pwszErrStr, dwRevResult);
  298. if (NULL == pwszErrStr)
  299. goto CommonReturn;
  300. pwszArg1 = pwszErrStr;
  301. }
  302. pwszRevStatus = FormatMessageUnicodeIds(ids, pwszArg1, pwszArg2);
  303. CommonReturn:
  304. if (pwszTime1)
  305. free(pwszTime1);
  306. if (pwszTime2)
  307. free(pwszTime2);
  308. if (pwszErrStr)
  309. free(pwszErrStr);
  310. return pwszRevStatus;
  311. }
  312. //////////////////////////////////////////////////////////////////////////////////////
  313. //
  314. //////////////////////////////////////////////////////////////////////////////////////
  315. BOOL BuildChain(
  316. PCERT_VIEW_HELPER pviewhelp,
  317. LPSTR pszUsage)
  318. {
  319. CRYPT_PROVIDER_DATA const * pProvData = NULL;
  320. CRYPT_PROVIDER_SGNR * pProvSigner = NULL;
  321. DWORD i;
  322. GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
  323. HRESULT hr = ERROR_SUCCESS;
  324. BOOL fInternalError = FALSE;
  325. DWORD dwStartIndex;
  326. BOOL fRet = TRUE;
  327. PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pcvp = pviewhelp->pcvp;
  328. WCHAR szErrorString[CRYPTUI_MAX_STRING_SIZE];
  329. //
  330. // if there was previous chain state then free that before building
  331. // the new chain
  332. //
  333. if (pviewhelp->fFreeWTD)
  334. {
  335. pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
  336. WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
  337. }
  338. pviewhelp->cpCryptProviderCerts = 0;
  339. pviewhelp->fFreeWTD = FALSE;
  340. //
  341. // initialize structs that are used with WinVerifyTrust()
  342. //
  343. memset(&(pviewhelp->sWTD), 0x00, sizeof(WINTRUST_DATA));
  344. pviewhelp->sWTD.cbStruct = sizeof(WINTRUST_DATA);
  345. pviewhelp->sWTD.dwUIChoice = WTD_UI_NONE;
  346. pviewhelp->sWTD.dwUnionChoice = WTD_CHOICE_CERT;
  347. pviewhelp->sWTD.pCert = &(pviewhelp->sWTCI);
  348. pviewhelp->sWTD.dwProvFlags = (pszUsage == NULL) ? WTD_NO_POLICY_USAGE_FLAG : 0;
  349. if ((pcvp->dwFlags & CRYPTUI_ENABLE_REVOCATION_CHECKING) == 0)
  350. {
  351. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_NONE;
  352. }
  353. else
  354. {
  355. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_CHAIN;
  356. }
  357. memset(&(pviewhelp->sWTCI), 0x00, sizeof(WINTRUST_CERT_INFO));
  358. pviewhelp->sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO);
  359. pviewhelp->sWTCI.pcwszDisplayName = L"CryptUI";
  360. pviewhelp->sWTCI.psCertContext = (CERT_CONTEXT *)pcvp->pCertContext;
  361. pviewhelp->sWTCI.chStores = pcvp->cStores;
  362. pviewhelp->sWTCI.pahStores = pcvp->rghStores;
  363. pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_DONT_OPEN_STORES) ? WTCI_DONT_OPEN_STORES : 0;
  364. pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_ONLY_OPEN_ROOT_STORE) ? WTCI_OPEN_ONLY_ROOT : 0;
  365. //
  366. // if a provider was passed in, then use it to build the chain,
  367. // otherwise use the default provider to build the chain
  368. //
  369. if (pcvp->pCryptProviderData != NULL)
  370. {
  371. pProvData = pcvp->pCryptProviderData;
  372. }
  373. else
  374. {
  375. pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_VERIFY;
  376. //
  377. // the default default provider requires the policycallback data to point
  378. // to the usage oid you are validating for, so set it to the usage passed in
  379. //
  380. pviewhelp->sWTD.pPolicyCallbackData = pszUsage;
  381. pviewhelp->sWTD.pSIPClientData = NULL;
  382. hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
  383. pProvData = WTHelperProvDataFromStateData(pviewhelp->sWTD.hWVTStateData);
  384. if (WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0) != NULL)
  385. {
  386. pviewhelp->fFreeWTD = TRUE;
  387. fInternalError = FALSE;
  388. }
  389. else
  390. {
  391. pviewhelp->fFreeWTD = FALSE;
  392. pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
  393. WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
  394. fInternalError = TRUE;
  395. }
  396. }
  397. if (pProvData && !fInternalError)
  398. {
  399. //
  400. // set the chain error in the helper struct
  401. //
  402. pviewhelp->dwChainError = pProvData->dwFinalError;
  403. //
  404. // This is to catch internal WinVerifyTrust errors
  405. //
  406. if ((pviewhelp->dwChainError == 0) && (FAILED(hr)))
  407. {
  408. pviewhelp->dwChainError = (DWORD) hr;
  409. }
  410. //
  411. // if the WinTrust state was passed into the certUI then use that for
  412. // the chain, else, get it from the state that was just built
  413. //
  414. if (pcvp->pCryptProviderData != NULL)
  415. {
  416. pProvSigner = WTHelperGetProvSignerFromChain(
  417. (PCRYPT_PROVIDER_DATA) pProvData,
  418. pcvp->idxSigner,
  419. pcvp->fCounterSigner,
  420. pcvp->idxCounterSigner);
  421. dwStartIndex = pcvp->idxCert;
  422. }
  423. else
  424. {
  425. pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0);
  426. dwStartIndex = 0;
  427. }
  428. if (pProvSigner)
  429. {
  430. //
  431. // get all certs in the chain
  432. //
  433. for (i=dwStartIndex; i<pProvSigner->csCertChain && (i<dwStartIndex+MAX_CERT_CHAIN_LENGTH); i++)
  434. {
  435. pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] = WTHelperGetProvCertFromChain(pProvSigner, i);
  436. if (pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] != NULL)
  437. {
  438. // Note, only modify this property when creating the
  439. // chain for the original end cert. Subsequent CA
  440. // chains won't have the ExtendedErrorInfo.
  441. if ((pcvp->dwFlags & CRYPTUI_TREEVIEW_PAGE_FLAG) == 0)
  442. {
  443. // Either delete or set the
  444. // CERT_EXTENDED_ERROR_INFO_PROP_ID
  445. // This is used in cvdetail.cpp when displaying
  446. // property details
  447. PCRYPT_PROVIDER_CERT pProvCert =
  448. pviewhelp->rgpCryptProviderCerts[
  449. pviewhelp->cpCryptProviderCerts];
  450. LPWSTR pwszExtErrorInfo = NULL; // not allocated
  451. LPWSTR pwszRevStatus = NULL; // LocalAlloc()'ed
  452. if (pProvCert->cbStruct >
  453. offsetof(CRYPT_PROVIDER_CERT, pChainElement)
  454. &&
  455. NULL != pProvCert->pChainElement)
  456. {
  457. pwszExtErrorInfo = (LPWSTR)
  458. pProvCert->pChainElement->pwszExtendedErrorInfo;
  459. pwszRevStatus = FormatRevocationStatus(
  460. pProvCert->pChainElement);
  461. if (NULL == pwszExtErrorInfo)
  462. {
  463. pwszExtErrorInfo = pwszRevStatus;
  464. }
  465. else if (pwszRevStatus)
  466. {
  467. LPWSTR pwszReAlloc;
  468. DWORD cchRevStatus;
  469. DWORD cchExtErrorInfo;
  470. cchRevStatus = wcslen(pwszRevStatus);
  471. cchExtErrorInfo = wcslen(pwszExtErrorInfo);
  472. pwszReAlloc = (LPWSTR) LocalReAlloc(
  473. pwszRevStatus,
  474. (cchRevStatus + cchExtErrorInfo + 1) *
  475. sizeof(WCHAR),
  476. LMEM_MOVEABLE);
  477. if (pwszReAlloc)
  478. {
  479. memcpy(&pwszReAlloc[cchRevStatus],
  480. pwszExtErrorInfo,
  481. (cchExtErrorInfo + 1) * sizeof(WCHAR));
  482. pwszExtErrorInfo = pwszRevStatus =
  483. pwszReAlloc;
  484. }
  485. }
  486. }
  487. if (pwszExtErrorInfo)
  488. {
  489. CRYPT_DATA_BLOB ExtErrorInfoBlob;
  490. ExtErrorInfoBlob.pbData = (BYTE *) pwszExtErrorInfo;
  491. ExtErrorInfoBlob.cbData =
  492. (wcslen(pwszExtErrorInfo) + 1) * sizeof(WCHAR);
  493. CertSetCertificateContextProperty(
  494. pProvCert->pCert,
  495. CERT_EXTENDED_ERROR_INFO_PROP_ID,
  496. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  497. &ExtErrorInfoBlob
  498. );
  499. }
  500. else
  501. {
  502. CertSetCertificateContextProperty(
  503. pProvCert->pCert,
  504. CERT_EXTENDED_ERROR_INFO_PROP_ID,
  505. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  506. NULL // pvData, NULL implies delete
  507. );
  508. }
  509. if (pwszRevStatus)
  510. LocalFree(pwszRevStatus);
  511. }
  512. pviewhelp->cpCryptProviderCerts++;
  513. }
  514. }
  515. }
  516. }
  517. CalculateUsages(pviewhelp);
  518. //
  519. // if the cert we are looking at is not the leaf cert, then we can't just take the
  520. // dwFinalError as the overall chain error, so find the over all chain error by
  521. // walking the chain and looking at the errors
  522. //
  523. if ((pcvp->pCryptProviderData != NULL) && (pcvp->idxCert != 0))
  524. {
  525. pviewhelp->dwChainError = GetFinalErrorFromChain(pviewhelp);
  526. }
  527. //
  528. // if we are in the fWarnUntrustedRoot then check to see if the root cert is in the
  529. // remote machine's root store
  530. //
  531. if (pviewhelp->fWarnUntrustedRoot)
  532. {
  533. PCCERT_CONTEXT pCertContext = NULL;
  534. CRYPT_HASH_BLOB cryptHashBlob;
  535. BYTE hash[20];
  536. DWORD cb = 20;
  537. pviewhelp->fRootInRemoteStore = FALSE;
  538. cryptHashBlob.cbData = 20;
  539. cryptHashBlob.pbData = &(hash[0]);
  540. if (CertGetCertificateContextProperty(
  541. pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts-1]->pCert,
  542. CERT_SHA1_HASH_PROP_ID,
  543. &(hash[0]),
  544. &cb))
  545. {
  546. pCertContext = CertFindCertificateInStore(
  547. pviewhelp->pcvp->rghStores[0],
  548. X509_ASN_ENCODING || PKCS_7_ASN_ENCODING,
  549. 0,
  550. CERT_FIND_SHA1_HASH,
  551. &cryptHashBlob,
  552. NULL);
  553. if (pCertContext != NULL)
  554. {
  555. CertFreeCertificateContext(pCertContext);
  556. pviewhelp->fRootInRemoteStore = TRUE;
  557. }
  558. }
  559. }
  560. //
  561. // get the error string for the whole cert chain
  562. //
  563. if (!fInternalError)
  564. {
  565. GetCertChainErrorString(pviewhelp);
  566. }
  567. else
  568. {
  569. LoadStringU(HinstDll, IDS_INTERNAL_ERROR, szErrorString, ARRAYSIZE(szErrorString));
  570. pviewhelp->pwszErrorString = AllocAndCopyWStr(szErrorString);
  571. }
  572. return TRUE;
  573. }
  574. //////////////////////////////////////////////////////////////////////////////////////
  575. //
  576. //////////////////////////////////////////////////////////////////////////////////////
  577. BOOL CalculateUsages(PCERT_VIEW_HELPER pviewhelp)
  578. {
  579. DWORD cLocalArrayOfUsages = 0;
  580. LPSTR * localArrayOfUsages = NULL;
  581. BOOL fLocalUsagesAllocated = FALSE;
  582. DWORD i;
  583. HRESULT hr;
  584. BOOL fRet = TRUE;
  585. PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pcvp = pviewhelp->pcvp;
  586. void *pTemp;
  587. //
  588. // if there are already usages, then clean them up before recalculating them,
  589. // or just return if state was passed into CertUI
  590. //
  591. if (pviewhelp->cUsages != 0)
  592. {
  593. //
  594. // state was passed into the CertUI, so just return
  595. //
  596. if (pcvp->pCryptProviderData != NULL)
  597. {
  598. return TRUE;
  599. }
  600. //
  601. // cleanup usages that were generated prior to this call
  602. //
  603. for (i=0; i<pviewhelp->cUsages; i++)
  604. {
  605. free(pviewhelp->rgUsages[i]);
  606. }
  607. free(pviewhelp->rgUsages);
  608. }
  609. //
  610. // initialize usage variables
  611. //
  612. pviewhelp->cUsages = 0;
  613. pviewhelp->rgUsages = NULL;
  614. //
  615. // if a provider was passed in, then we just look at it for the usage and structure
  616. // passed in for the trust of that usage,
  617. // otherwise we need to look at each usage and validate trust for all of them
  618. //
  619. if (pcvp->pCryptProviderData != NULL)
  620. {
  621. //
  622. // allocate an array of 1 LPSTR
  623. //
  624. if (NULL == (pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR))))
  625. {
  626. SetLastError(E_OUTOFMEMORY);
  627. return FALSE;
  628. }
  629. //
  630. // copy either the 1 purpose that was passed in, or the purpose out of WinTrust state
  631. //
  632. if (pcvp->cPurposes == 1)
  633. {
  634. if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[0])+1)))
  635. {
  636. SetLastError(E_OUTOFMEMORY);
  637. return FALSE;
  638. }
  639. strcpy(pviewhelp->rgUsages[0], pcvp->rgszPurposes[0]);
  640. }
  641. else
  642. {
  643. if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->pCryptProviderData->pszUsageOID)+1)))
  644. {
  645. SetLastError(E_OUTOFMEMORY);
  646. return FALSE;
  647. }
  648. strcpy(pviewhelp->rgUsages[0], pcvp->pCryptProviderData->pszUsageOID);
  649. }
  650. pviewhelp->cUsages = 1;
  651. }
  652. else
  653. {
  654. //
  655. // check to see if usages where passed in, if so, then intersect those with
  656. // available usages in the cert, otherwise, get the available usages in the cert
  657. // and use them as is
  658. //
  659. if (pcvp->cPurposes != 0)
  660. {
  661. //
  662. // get the array of possible usages for the cert chain
  663. //
  664. // DSIE: Switch over to using pChainElement from philh's new chain building code.
  665. AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &localArrayOfUsages, &cLocalArrayOfUsages);
  666. if (cLocalArrayOfUsages != 0)
  667. fLocalUsagesAllocated = TRUE;
  668. //
  669. // for each usage that was passed in check to see if it is in the list of possible usages
  670. //
  671. for (i=0; i<pcvp->cPurposes; i++)
  672. {
  673. if (OIDinArray(pcvp->rgszPurposes[i], localArrayOfUsages, cLocalArrayOfUsages))
  674. {
  675. //
  676. // if an array hasn't yet been allocated, then allocate space for an array of
  677. // 1 LPSTR, otherwise use realloc to add one more element
  678. //
  679. if (pviewhelp->rgUsages == NULL)
  680. {
  681. pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR));
  682. }
  683. else
  684. {
  685. pTemp = realloc(pviewhelp->rgUsages, sizeof(LPSTR) * (pviewhelp->cUsages+1));
  686. if (pTemp == NULL)
  687. {
  688. free(pviewhelp->rgUsages);
  689. pviewhelp->rgUsages = NULL;
  690. }
  691. else
  692. {
  693. pviewhelp->rgUsages = (LPSTR *) pTemp;
  694. }
  695. }
  696. if (pviewhelp->rgUsages == NULL)
  697. {
  698. goto ErrorCleanUp;
  699. }
  700. //
  701. // allocate space for the usage string, then copy it, and increment number of usages
  702. //
  703. if (NULL == (pviewhelp->rgUsages[pviewhelp->cUsages] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[i])+1)))
  704. {
  705. SetLastError(E_OUTOFMEMORY);
  706. goto ErrorCleanUp;
  707. }
  708. strcpy(pviewhelp->rgUsages[pviewhelp->cUsages], pcvp->rgszPurposes[i]);
  709. pviewhelp->cUsages++;
  710. }
  711. }
  712. }
  713. else
  714. {
  715. AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &(pviewhelp->rgUsages), &(pviewhelp->cUsages));
  716. }
  717. }
  718. CleanUp:
  719. if (fLocalUsagesAllocated)
  720. {
  721. i = 0;
  722. while ((i < cLocalArrayOfUsages) && (localArrayOfUsages[i] != NULL))
  723. {
  724. free(localArrayOfUsages[i]);
  725. i++;
  726. }
  727. free(localArrayOfUsages);
  728. }
  729. return fRet;
  730. ErrorCleanUp:
  731. if (pviewhelp->rgUsages != NULL)
  732. {
  733. i = 0;
  734. while ((i < pviewhelp->cUsages) && (pviewhelp->rgUsages[i] != NULL))
  735. {
  736. free(pviewhelp->rgUsages[i]);
  737. i++;
  738. }
  739. free(pviewhelp->rgUsages);
  740. }
  741. fRet = FALSE;
  742. goto CleanUp;
  743. }
  744. //////////////////////////////////////////////////////////////////////////////////////
  745. //
  746. //////////////////////////////////////////////////////////////////////////////////////
  747. BOOL BuildWinVTrustState(
  748. LPCWSTR szFileName,
  749. CMSG_SIGNER_INFO const *pSignerInfo,
  750. DWORD cStores,
  751. HCERTSTORE *rghStores,
  752. LPCSTR pszOID,
  753. PCERT_VIEWSIGNERINFO_PRIVATE pcvsiPrivate,
  754. CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
  755. WINTRUST_DATA *pWTD)
  756. {
  757. WINTRUST_FILE_INFO WTFI;
  758. WINTRUST_SGNR_INFO WTSI;
  759. HRESULT hr;
  760. GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
  761. //
  762. // initialize structs that are used locally with WinVerifyTrust()
  763. //
  764. memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
  765. pWTD->cbStruct = sizeof(WINTRUST_DATA);
  766. pWTD->dwUIChoice = WTD_UI_NONE;
  767. //
  768. // if the szFileName parameter is non NULL then this for a file,
  769. // otherwise it is for a signer info
  770. //
  771. if (szFileName != NULL)
  772. {
  773. pWTD->dwUnionChoice = WTD_CHOICE_FILE;
  774. pWTD->pFile = &WTFI;
  775. pWTD->pPolicyCallbackData = (void *) pszOID;
  776. memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
  777. WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
  778. WTFI.pcwszFilePath = szFileName;
  779. }
  780. else
  781. {
  782. pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
  783. pWTD->pSgnr = &WTSI;
  784. pWTD->pPolicyCallbackData = (void *) pszOID;
  785. memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
  786. WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
  787. WTSI.pcwszDisplayName = L"CryptUI";
  788. WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
  789. WTSI.chStores = cStores;
  790. WTSI.pahStores = rghStores;
  791. //WTSI.pszOID = pszOID;
  792. }
  793. pWTD->pSIPClientData = NULL;
  794. pWTD->dwStateAction = WTD_STATEACTION_VERIFY;
  795. hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
  796. if (hr == ERROR_SUCCESS)
  797. {
  798. pcvsiPrivate->fpCryptProviderDataTrustedUsage = TRUE;
  799. }
  800. else
  801. {
  802. pcvsiPrivate->fpCryptProviderDataTrustedUsage = FALSE;
  803. }
  804. pcvsiPrivate->pCryptProviderData = WTHelperProvDataFromStateData(pWTD->hWVTStateData);
  805. return TRUE;
  806. }
  807. //////////////////////////////////////////////////////////////////////////////////////
  808. //
  809. //////////////////////////////////////////////////////////////////////////////////////
  810. BOOL FreeWinVTrustState(
  811. LPCWSTR szFileName,
  812. CMSG_SIGNER_INFO const *pSignerInfo,
  813. DWORD cStores,
  814. HCERTSTORE *rghStores,
  815. LPCSTR pszOID,
  816. CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
  817. WINTRUST_DATA *pWTD)//,
  818. //BOOL *pfUseDefaultProvider)
  819. {
  820. WINTRUST_FILE_INFO WTFI;
  821. WINTRUST_SGNR_INFO WTSI;
  822. HRESULT hr;
  823. GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
  824. // initialize structs that are used locally with WinVerifyTrust()
  825. memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
  826. pWTD->cbStruct = sizeof(WINTRUST_DATA);
  827. pWTD->dwUIChoice = WTD_UI_NONE;
  828. //
  829. // if the szFileName parameter is non NULL then this for a file,
  830. // otherwise it is for a signer info
  831. //
  832. if (szFileName != NULL)
  833. {
  834. pWTD->dwUnionChoice = WTD_CHOICE_FILE;
  835. pWTD->pFile = &WTFI;
  836. memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
  837. WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
  838. WTFI.pcwszFilePath = szFileName;
  839. }
  840. else
  841. {
  842. pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
  843. pWTD->pSgnr = &WTSI;
  844. memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
  845. WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
  846. WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
  847. WTSI.chStores = cStores;
  848. WTSI.pahStores = rghStores;
  849. }
  850. /*if (*pfUseDefaultProvider)
  851. {
  852. pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
  853. WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
  854. }
  855. else
  856. {*/
  857. pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
  858. WinVerifyTrustEx(NULL, &(pCryptProviderDefUsage->gActionID), pWTD);
  859. WintrustGetDefaultForUsage(DWACTION_FREE, pszOID, pCryptProviderDefUsage);
  860. //}
  861. return TRUE;
  862. }