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.

986 lines
34 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_CHECK_CHAIN_EXCLUDE_ROOT)
  350. {
  351. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
  352. }
  353. else if (pcvp->dwFlags & CRYPTUI_ENABLE_REVOCATION_CHECK_END_CERT)
  354. {
  355. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_END_CERT;
  356. }
  357. else if (pcvp->dwFlags & CRYPTUI_ENABLE_REVOCATION_CHECK_CHAIN)
  358. {
  359. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_CHAIN;
  360. }
  361. else
  362. {
  363. pviewhelp->sWTD.dwProvFlags |= WTD_REVOCATION_CHECK_NONE;
  364. }
  365. memset(&(pviewhelp->sWTCI), 0x00, sizeof(WINTRUST_CERT_INFO));
  366. pviewhelp->sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO);
  367. pviewhelp->sWTCI.pcwszDisplayName = L"CryptUI";
  368. pviewhelp->sWTCI.psCertContext = (CERT_CONTEXT *)pcvp->pCertContext;
  369. pviewhelp->sWTCI.chStores = pcvp->cStores;
  370. pviewhelp->sWTCI.pahStores = pcvp->rghStores;
  371. pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_DONT_OPEN_STORES) ? WTCI_DONT_OPEN_STORES : 0;
  372. pviewhelp->sWTCI.dwFlags |= (pcvp->dwFlags & CRYPTUI_ONLY_OPEN_ROOT_STORE) ? WTCI_OPEN_ONLY_ROOT : 0;
  373. //
  374. // if a provider was passed in, then use it to build the chain,
  375. // otherwise use the default provider to build the chain
  376. //
  377. if (pcvp->pCryptProviderData != NULL)
  378. {
  379. pProvData = pcvp->pCryptProviderData;
  380. }
  381. else
  382. {
  383. pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_VERIFY;
  384. //
  385. // the default default provider requires the policycallback data to point
  386. // to the usage oid you are validating for, so set it to the usage passed in
  387. //
  388. pviewhelp->sWTD.pPolicyCallbackData = pszUsage;
  389. pviewhelp->sWTD.pSIPClientData = NULL;
  390. hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
  391. pProvData = WTHelperProvDataFromStateData(pviewhelp->sWTD.hWVTStateData);
  392. if (WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0) != NULL)
  393. {
  394. pviewhelp->fFreeWTD = TRUE;
  395. fInternalError = FALSE;
  396. }
  397. else
  398. {
  399. pviewhelp->fFreeWTD = FALSE;
  400. pviewhelp->sWTD.dwStateAction = WTD_STATEACTION_CLOSE;
  401. WinVerifyTrustEx(NULL, &defaultProviderGUID, &(pviewhelp->sWTD));
  402. fInternalError = TRUE;
  403. }
  404. }
  405. if (pProvData && !fInternalError)
  406. {
  407. //
  408. // set the chain error in the helper struct
  409. //
  410. pviewhelp->dwChainError = pProvData->dwFinalError;
  411. //
  412. // This is to catch internal WinVerifyTrust errors
  413. //
  414. if ((pviewhelp->dwChainError == 0) && (FAILED(hr)))
  415. {
  416. pviewhelp->dwChainError = (DWORD) hr;
  417. }
  418. //
  419. // if the WinTrust state was passed into the certUI then use that for
  420. // the chain, else, get it from the state that was just built
  421. //
  422. if (pcvp->pCryptProviderData != NULL)
  423. {
  424. pProvSigner = WTHelperGetProvSignerFromChain(
  425. (PCRYPT_PROVIDER_DATA) pProvData,
  426. pcvp->idxSigner,
  427. pcvp->fCounterSigner,
  428. pcvp->idxCounterSigner);
  429. dwStartIndex = pcvp->idxCert;
  430. }
  431. else
  432. {
  433. pProvSigner = WTHelperGetProvSignerFromChain((PCRYPT_PROVIDER_DATA) pProvData, 0, FALSE, 0);
  434. dwStartIndex = 0;
  435. }
  436. if (pProvSigner)
  437. {
  438. //
  439. // get all certs in the chain
  440. //
  441. for (i=dwStartIndex; i<pProvSigner->csCertChain && (i<dwStartIndex+MAX_CERT_CHAIN_LENGTH); i++)
  442. {
  443. pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] = WTHelperGetProvCertFromChain(pProvSigner, i);
  444. if (pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts] != NULL)
  445. {
  446. // Note, only modify this property when creating the
  447. // chain for the original end cert. Subsequent CA
  448. // chains won't have the ExtendedErrorInfo.
  449. if ((pcvp->dwFlags & CRYPTUI_TREEVIEW_PAGE_FLAG) == 0)
  450. {
  451. // Either delete or set the
  452. // CERT_EXTENDED_ERROR_INFO_PROP_ID
  453. // This is used in cvdetail.cpp when displaying
  454. // property details
  455. PCRYPT_PROVIDER_CERT pProvCert =
  456. pviewhelp->rgpCryptProviderCerts[
  457. pviewhelp->cpCryptProviderCerts];
  458. LPWSTR pwszExtErrorInfo = NULL; // not allocated
  459. LPWSTR pwszRevStatus = NULL; // LocalAlloc()'ed
  460. if (pProvCert->cbStruct >
  461. offsetof(CRYPT_PROVIDER_CERT, pChainElement)
  462. &&
  463. NULL != pProvCert->pChainElement)
  464. {
  465. pwszExtErrorInfo = (LPWSTR)
  466. pProvCert->pChainElement->pwszExtendedErrorInfo;
  467. pwszRevStatus = FormatRevocationStatus(
  468. pProvCert->pChainElement);
  469. if (NULL == pwszExtErrorInfo)
  470. {
  471. pwszExtErrorInfo = pwszRevStatus;
  472. }
  473. else if (pwszRevStatus)
  474. {
  475. LPWSTR pwszReAlloc;
  476. DWORD cchRevStatus;
  477. DWORD cchExtErrorInfo;
  478. cchRevStatus = wcslen(pwszRevStatus);
  479. cchExtErrorInfo = wcslen(pwszExtErrorInfo);
  480. pwszReAlloc = (LPWSTR) LocalReAlloc(
  481. pwszRevStatus,
  482. (cchRevStatus + cchExtErrorInfo + 1) *
  483. sizeof(WCHAR),
  484. LMEM_MOVEABLE);
  485. if (pwszReAlloc)
  486. {
  487. memcpy(&pwszReAlloc[cchRevStatus],
  488. pwszExtErrorInfo,
  489. (cchExtErrorInfo + 1) * sizeof(WCHAR));
  490. pwszExtErrorInfo = pwszRevStatus =
  491. pwszReAlloc;
  492. }
  493. }
  494. }
  495. if (pwszExtErrorInfo)
  496. {
  497. CRYPT_DATA_BLOB ExtErrorInfoBlob;
  498. ExtErrorInfoBlob.pbData = (BYTE *) pwszExtErrorInfo;
  499. ExtErrorInfoBlob.cbData =
  500. (wcslen(pwszExtErrorInfo) + 1) * sizeof(WCHAR);
  501. CertSetCertificateContextProperty(
  502. pProvCert->pCert,
  503. CERT_EXTENDED_ERROR_INFO_PROP_ID,
  504. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  505. &ExtErrorInfoBlob
  506. );
  507. }
  508. else
  509. {
  510. CertSetCertificateContextProperty(
  511. pProvCert->pCert,
  512. CERT_EXTENDED_ERROR_INFO_PROP_ID,
  513. CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG,
  514. NULL // pvData, NULL implies delete
  515. );
  516. }
  517. if (pwszRevStatus)
  518. LocalFree(pwszRevStatus);
  519. }
  520. pviewhelp->cpCryptProviderCerts++;
  521. }
  522. }
  523. }
  524. }
  525. CalculateUsages(pviewhelp);
  526. //
  527. // if the cert we are looking at is not the leaf cert, then we can't just take the
  528. // dwFinalError as the overall chain error, so find the over all chain error by
  529. // walking the chain and looking at the errors
  530. //
  531. if ((pcvp->pCryptProviderData != NULL) && (pcvp->idxCert != 0))
  532. {
  533. pviewhelp->dwChainError = GetFinalErrorFromChain(pviewhelp);
  534. }
  535. //
  536. // if we are in the fWarnUntrustedRoot then check to see if the root cert is in the
  537. // remote machine's root store
  538. //
  539. if (pviewhelp->fWarnUntrustedRoot)
  540. {
  541. PCCERT_CONTEXT pCertContext = NULL;
  542. CRYPT_HASH_BLOB cryptHashBlob;
  543. BYTE hash[20];
  544. DWORD cb = 20;
  545. pviewhelp->fRootInRemoteStore = FALSE;
  546. cryptHashBlob.cbData = 20;
  547. cryptHashBlob.pbData = &(hash[0]);
  548. if (CertGetCertificateContextProperty(
  549. pviewhelp->rgpCryptProviderCerts[pviewhelp->cpCryptProviderCerts-1]->pCert,
  550. CERT_SHA1_HASH_PROP_ID,
  551. &(hash[0]),
  552. &cb))
  553. {
  554. pCertContext = CertFindCertificateInStore(
  555. pviewhelp->pcvp->rghStores[0],
  556. X509_ASN_ENCODING || PKCS_7_ASN_ENCODING,
  557. 0,
  558. CERT_FIND_SHA1_HASH,
  559. &cryptHashBlob,
  560. NULL);
  561. if (pCertContext != NULL)
  562. {
  563. CertFreeCertificateContext(pCertContext);
  564. pviewhelp->fRootInRemoteStore = TRUE;
  565. }
  566. }
  567. }
  568. //
  569. // get the error string for the whole cert chain
  570. //
  571. if (!fInternalError)
  572. {
  573. GetCertChainErrorString(pviewhelp);
  574. }
  575. else
  576. {
  577. LoadStringU(HinstDll, IDS_INTERNAL_ERROR, szErrorString, ARRAYSIZE(szErrorString));
  578. pviewhelp->pwszErrorString = AllocAndCopyWStr(szErrorString);
  579. }
  580. return TRUE;
  581. }
  582. //////////////////////////////////////////////////////////////////////////////////////
  583. //
  584. //////////////////////////////////////////////////////////////////////////////////////
  585. BOOL CalculateUsages(PCERT_VIEW_HELPER pviewhelp)
  586. {
  587. DWORD cLocalArrayOfUsages = 0;
  588. LPSTR * localArrayOfUsages = NULL;
  589. BOOL fLocalUsagesAllocated = FALSE;
  590. DWORD i;
  591. HRESULT hr;
  592. BOOL fRet = TRUE;
  593. PCCRYPTUI_VIEWCERTIFICATE_STRUCTW pcvp = pviewhelp->pcvp;
  594. void *pTemp;
  595. //
  596. // if there are already usages, then clean them up before recalculating them,
  597. // or just return if state was passed into CertUI
  598. //
  599. if (pviewhelp->cUsages != 0)
  600. {
  601. //
  602. // state was passed into the CertUI, so just return
  603. //
  604. if (pcvp->pCryptProviderData != NULL)
  605. {
  606. return TRUE;
  607. }
  608. //
  609. // cleanup usages that were generated prior to this call
  610. //
  611. for (i=0; i<pviewhelp->cUsages; i++)
  612. {
  613. free(pviewhelp->rgUsages[i]);
  614. }
  615. free(pviewhelp->rgUsages);
  616. }
  617. //
  618. // initialize usage variables
  619. //
  620. pviewhelp->cUsages = 0;
  621. pviewhelp->rgUsages = NULL;
  622. //
  623. // if a provider was passed in, then we just look at it for the usage and structure
  624. // passed in for the trust of that usage,
  625. // otherwise we need to look at each usage and validate trust for all of them
  626. //
  627. if (pcvp->pCryptProviderData != NULL)
  628. {
  629. //
  630. // allocate an array of 1 LPSTR
  631. //
  632. if (NULL == (pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR))))
  633. {
  634. SetLastError(E_OUTOFMEMORY);
  635. return FALSE;
  636. }
  637. //
  638. // copy either the 1 purpose that was passed in, or the purpose out of WinTrust state
  639. //
  640. if (pcvp->cPurposes == 1)
  641. {
  642. if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[0])+1)))
  643. {
  644. SetLastError(E_OUTOFMEMORY);
  645. return FALSE;
  646. }
  647. strcpy(pviewhelp->rgUsages[0], pcvp->rgszPurposes[0]);
  648. }
  649. else
  650. {
  651. if (NULL == (pviewhelp->rgUsages[0] = (LPSTR) malloc(strlen(pcvp->pCryptProviderData->pszUsageOID)+1)))
  652. {
  653. SetLastError(E_OUTOFMEMORY);
  654. return FALSE;
  655. }
  656. strcpy(pviewhelp->rgUsages[0], pcvp->pCryptProviderData->pszUsageOID);
  657. }
  658. pviewhelp->cUsages = 1;
  659. }
  660. else
  661. {
  662. //
  663. // check to see if usages where passed in, if so, then intersect those with
  664. // available usages in the cert, otherwise, get the available usages in the cert
  665. // and use them as is
  666. //
  667. if (pcvp->cPurposes != 0)
  668. {
  669. //
  670. // get the array of possible usages for the cert chain
  671. //
  672. // DSIE: Switch over to using pChainElement from philh's new chain building code.
  673. AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &localArrayOfUsages, &cLocalArrayOfUsages);
  674. if (cLocalArrayOfUsages != 0)
  675. fLocalUsagesAllocated = TRUE;
  676. //
  677. // for each usage that was passed in check to see if it is in the list of possible usages
  678. //
  679. for (i=0; i<pcvp->cPurposes; i++)
  680. {
  681. if (OIDinArray(pcvp->rgszPurposes[i], localArrayOfUsages, cLocalArrayOfUsages))
  682. {
  683. //
  684. // if an array hasn't yet been allocated, then allocate space for an array of
  685. // 1 LPSTR, otherwise use realloc to add one more element
  686. //
  687. if (pviewhelp->rgUsages == NULL)
  688. {
  689. pviewhelp->rgUsages = (LPSTR *) malloc(sizeof(LPSTR));
  690. }
  691. else
  692. {
  693. pTemp = realloc(pviewhelp->rgUsages, sizeof(LPSTR) * (pviewhelp->cUsages+1));
  694. if (pTemp == NULL)
  695. {
  696. free(pviewhelp->rgUsages);
  697. pviewhelp->rgUsages = NULL;
  698. }
  699. else
  700. {
  701. pviewhelp->rgUsages = (LPSTR *) pTemp;
  702. }
  703. }
  704. if (pviewhelp->rgUsages == NULL)
  705. {
  706. goto ErrorCleanUp;
  707. }
  708. //
  709. // allocate space for the usage string, then copy it, and increment number of usages
  710. //
  711. if (NULL == (pviewhelp->rgUsages[pviewhelp->cUsages] = (LPSTR) malloc(strlen(pcvp->rgszPurposes[i])+1)))
  712. {
  713. SetLastError(E_OUTOFMEMORY);
  714. goto ErrorCleanUp;
  715. }
  716. strcpy(pviewhelp->rgUsages[pviewhelp->cUsages], pcvp->rgszPurposes[i]);
  717. pviewhelp->cUsages++;
  718. }
  719. }
  720. }
  721. else
  722. {
  723. AllocAndReturnKeyUsageList(pviewhelp->rgpCryptProviderCerts[0], &(pviewhelp->rgUsages), &(pviewhelp->cUsages));
  724. }
  725. }
  726. CleanUp:
  727. if (fLocalUsagesAllocated)
  728. {
  729. i = 0;
  730. while ((i < cLocalArrayOfUsages) && (localArrayOfUsages[i] != NULL))
  731. {
  732. free(localArrayOfUsages[i]);
  733. i++;
  734. }
  735. free(localArrayOfUsages);
  736. }
  737. return fRet;
  738. ErrorCleanUp:
  739. if (pviewhelp->rgUsages != NULL)
  740. {
  741. i = 0;
  742. while ((i < pviewhelp->cUsages) && (pviewhelp->rgUsages[i] != NULL))
  743. {
  744. free(pviewhelp->rgUsages[i]);
  745. i++;
  746. }
  747. free(pviewhelp->rgUsages);
  748. }
  749. fRet = FALSE;
  750. goto CleanUp;
  751. }
  752. //////////////////////////////////////////////////////////////////////////////////////
  753. //
  754. //////////////////////////////////////////////////////////////////////////////////////
  755. BOOL BuildWinVTrustState(
  756. LPCWSTR szFileName,
  757. CMSG_SIGNER_INFO const *pSignerInfo,
  758. DWORD cStores,
  759. HCERTSTORE *rghStores,
  760. LPCSTR pszOID,
  761. PCERT_VIEWSIGNERINFO_PRIVATE pcvsiPrivate,
  762. CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
  763. WINTRUST_DATA *pWTD)
  764. {
  765. WINTRUST_FILE_INFO WTFI;
  766. WINTRUST_SGNR_INFO WTSI;
  767. HRESULT hr;
  768. GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
  769. //
  770. // initialize structs that are used locally with WinVerifyTrust()
  771. //
  772. memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
  773. pWTD->cbStruct = sizeof(WINTRUST_DATA);
  774. pWTD->dwUIChoice = WTD_UI_NONE;
  775. //
  776. // if the szFileName parameter is non NULL then this for a file,
  777. // otherwise it is for a signer info
  778. //
  779. if (szFileName != NULL)
  780. {
  781. pWTD->dwUnionChoice = WTD_CHOICE_FILE;
  782. pWTD->pFile = &WTFI;
  783. pWTD->pPolicyCallbackData = (void *) pszOID;
  784. memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
  785. WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
  786. WTFI.pcwszFilePath = szFileName;
  787. }
  788. else
  789. {
  790. pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
  791. pWTD->pSgnr = &WTSI;
  792. pWTD->pPolicyCallbackData = (void *) pszOID;
  793. memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
  794. WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
  795. WTSI.pcwszDisplayName = L"CryptUI";
  796. WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
  797. WTSI.chStores = cStores;
  798. WTSI.pahStores = rghStores;
  799. //WTSI.pszOID = pszOID;
  800. }
  801. pWTD->pSIPClientData = NULL;
  802. pWTD->dwStateAction = WTD_STATEACTION_VERIFY;
  803. hr = WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
  804. if (hr == ERROR_SUCCESS)
  805. {
  806. pcvsiPrivate->fpCryptProviderDataTrustedUsage = TRUE;
  807. }
  808. else
  809. {
  810. pcvsiPrivate->fpCryptProviderDataTrustedUsage = FALSE;
  811. }
  812. pcvsiPrivate->pCryptProviderData = WTHelperProvDataFromStateData(pWTD->hWVTStateData);
  813. return TRUE;
  814. }
  815. //////////////////////////////////////////////////////////////////////////////////////
  816. //
  817. //////////////////////////////////////////////////////////////////////////////////////
  818. BOOL FreeWinVTrustState(
  819. LPCWSTR szFileName,
  820. CMSG_SIGNER_INFO const *pSignerInfo,
  821. DWORD cStores,
  822. HCERTSTORE *rghStores,
  823. LPCSTR pszOID,
  824. CRYPT_PROVIDER_DEFUSAGE *pCryptProviderDefUsage,
  825. WINTRUST_DATA *pWTD)//,
  826. //BOOL *pfUseDefaultProvider)
  827. {
  828. WINTRUST_FILE_INFO WTFI;
  829. WINTRUST_SGNR_INFO WTSI;
  830. HRESULT hr;
  831. GUID defaultProviderGUID = WINTRUST_ACTION_GENERIC_CERT_VERIFY;
  832. // initialize structs that are used locally with WinVerifyTrust()
  833. memset(pWTD, 0x00, sizeof(WINTRUST_DATA));
  834. pWTD->cbStruct = sizeof(WINTRUST_DATA);
  835. pWTD->dwUIChoice = WTD_UI_NONE;
  836. //
  837. // if the szFileName parameter is non NULL then this for a file,
  838. // otherwise it is for a signer info
  839. //
  840. if (szFileName != NULL)
  841. {
  842. pWTD->dwUnionChoice = WTD_CHOICE_FILE;
  843. pWTD->pFile = &WTFI;
  844. memset(&WTFI, 0x00, sizeof(WINTRUST_FILE_INFO));
  845. WTFI.cbStruct = sizeof(WINTRUST_FILE_INFO);
  846. WTFI.pcwszFilePath = szFileName;
  847. }
  848. else
  849. {
  850. pWTD->dwUnionChoice = WTD_CHOICE_SIGNER;
  851. pWTD->pSgnr = &WTSI;
  852. memset(&WTSI, 0x00, sizeof(WINTRUST_SGNR_INFO));
  853. WTSI.cbStruct = sizeof(WINTRUST_SGNR_INFO);
  854. WTSI.psSignerInfo = (CMSG_SIGNER_INFO *) pSignerInfo;
  855. WTSI.chStores = cStores;
  856. WTSI.pahStores = rghStores;
  857. }
  858. /*if (*pfUseDefaultProvider)
  859. {
  860. pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
  861. WinVerifyTrustEx(NULL, &defaultProviderGUID, pWTD);
  862. }
  863. else
  864. {*/
  865. pWTD->dwStateAction = WTD_STATEACTION_CLOSE;
  866. WinVerifyTrustEx(NULL, &(pCryptProviderDefUsage->gActionID), pWTD);
  867. WintrustGetDefaultForUsage(DWACTION_FREE, pszOID, pCryptProviderDefUsage);
  868. //}
  869. return TRUE;
  870. }