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.

2691 lines
69 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: certhier.cpp
  8. //
  9. // Contents: Install cert server hierarchical
  10. //
  11. // History: 09-26-96
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cpp>
  15. #pragma hdrstop
  16. // C Run-Time Includes
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <memory.h>
  20. // Windows System Includes
  21. #include <winsvc.h>
  22. #include <rpc.h>
  23. #include <tchar.h>
  24. #include <csdisp.h>
  25. #include <certca.h>
  26. // Application Includes
  27. #include "cscsp.h"
  28. #include "certmsg.h"
  29. #include "certhier.h"
  30. #include "setupids.h"
  31. #include "tfc.h"
  32. #define __dwFILE__ __dwFILE_INITLIB_CERTHIER_CPP__
  33. // following veriables are extern in initlib, bad.
  34. LPSTR pszObjIdSignatureAlgorithm = szOID_OIWSEC_sha1RSASign;
  35. HRESULT
  36. csiFillKeyProvInfo(
  37. IN WCHAR const *pwszContainerName,
  38. IN WCHAR const *pwszProvName,
  39. IN DWORD dwProvType,
  40. IN BOOL fMachineKeyset,
  41. OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo) // call csiFreeKeyProvInfo to free
  42. {
  43. HRESULT hr;
  44. WCHAR *pwszContainerNameT = NULL;
  45. WCHAR *pwszProvNameT = NULL;
  46. ZeroMemory(pKeyProvInfo, sizeof(*pKeyProvInfo));
  47. hr = myDupString(pwszContainerName, &pwszContainerNameT);
  48. _JumpIfError(hr, error, "myDupString");
  49. hr = myDupString(pwszProvName, &pwszProvNameT);
  50. _JumpIfError(hr, error, "myDupString");
  51. pKeyProvInfo->pwszContainerName = pwszContainerNameT;
  52. pKeyProvInfo->pwszProvName = pwszProvNameT;
  53. pKeyProvInfo->dwProvType = dwProvType;
  54. if (fMachineKeyset)
  55. {
  56. pKeyProvInfo->dwFlags = CRYPT_MACHINE_KEYSET;
  57. }
  58. pKeyProvInfo->dwKeySpec = AT_SIGNATURE;
  59. pwszContainerNameT = NULL;
  60. pwszProvNameT = NULL;
  61. hr = S_OK;
  62. error:
  63. if (NULL != pwszContainerNameT)
  64. {
  65. LocalFree(pwszContainerNameT);
  66. }
  67. if (NULL != pwszProvNameT)
  68. {
  69. LocalFree(pwszProvNameT);
  70. }
  71. return(hr);
  72. }
  73. VOID
  74. csiFreeKeyProvInfo(
  75. IN OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo)
  76. {
  77. if (NULL != pKeyProvInfo->pwszProvName)
  78. {
  79. LocalFree(pKeyProvInfo->pwszProvName);
  80. pKeyProvInfo->pwszProvName = NULL;
  81. }
  82. if (NULL != pKeyProvInfo->pwszContainerName)
  83. {
  84. LocalFree(pKeyProvInfo->pwszContainerName);
  85. pKeyProvInfo->pwszContainerName = NULL;
  86. }
  87. }
  88. HRESULT
  89. GetCertServerKeyProviderInfo(
  90. IN WCHAR const *pwszSanitizedCAName,
  91. IN WCHAR const *pwszKeyContainerName,
  92. OUT ALG_ID *pidAlg,
  93. OUT BOOL *pfMachineKeyset,
  94. OUT CRYPT_KEY_PROV_INFO *pKeyProvInfo) // call csiFreeKeyProvInfo to free
  95. {
  96. HRESULT hr;
  97. WCHAR *pwszProvName = NULL;
  98. DWORD dwProvType;
  99. ZeroMemory(pKeyProvInfo, sizeof(*pKeyProvInfo));
  100. // get CSP info
  101. hr = myGetCertSrvCSP(
  102. FALSE, // fEncryptionCSP
  103. pwszSanitizedCAName,
  104. &dwProvType,
  105. &pwszProvName,
  106. pidAlg,
  107. pfMachineKeyset,
  108. NULL); // pdwKeySize
  109. _JumpIfError(hr, error, "myGetCertSrvCSP");
  110. hr = csiFillKeyProvInfo(
  111. pwszKeyContainerName,
  112. pwszProvName,
  113. dwProvType,
  114. *pfMachineKeyset,
  115. pKeyProvInfo);
  116. _JumpIfError(hr, error, "csiFillKeyProvInfo");
  117. error:
  118. if (NULL != pwszProvName)
  119. {
  120. LocalFree(pwszProvName);
  121. }
  122. return(hr);
  123. }
  124. HRESULT
  125. mySetCertRegKeyIndexAndContainer(
  126. IN WCHAR const *pwszSanitizedCAName,
  127. IN DWORD iKey,
  128. IN WCHAR const *pwszKeyContainer)
  129. {
  130. HRESULT hr;
  131. hr = mySetCertRegDWValue(
  132. pwszSanitizedCAName,
  133. NULL,
  134. NULL,
  135. wszREGREQUESTKEYINDEX,
  136. iKey);
  137. _JumpIfErrorStr(hr, error, "mySetCertRegDWValue", wszREGREQUESTKEYINDEX);
  138. hr = mySetCertRegStrValue(
  139. pwszSanitizedCAName,
  140. NULL,
  141. NULL,
  142. wszREGREQUESTKEYCONTAINER,
  143. pwszKeyContainer);
  144. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", wszREGREQUESTKEYCONTAINER);
  145. error:
  146. return(hr);
  147. }
  148. HRESULT
  149. myGetCertRegKeyIndexAndContainer(
  150. IN WCHAR const *pwszSanitizedCAName,
  151. OUT DWORD *piKey,
  152. OUT WCHAR **ppwszKeyContainer)
  153. {
  154. HRESULT hr;
  155. *ppwszKeyContainer = NULL;
  156. hr = myGetCertRegDWValue(
  157. pwszSanitizedCAName,
  158. NULL,
  159. NULL,
  160. wszREGREQUESTKEYINDEX,
  161. piKey);
  162. if (S_OK != hr)
  163. {
  164. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  165. {
  166. _JumpErrorStr(hr, error, "myGetCertRegDWValue", wszREGREQUESTKEYINDEX);
  167. }
  168. *piKey = 0;
  169. }
  170. hr = myGetCertRegStrValue(
  171. pwszSanitizedCAName,
  172. NULL,
  173. NULL,
  174. wszREGREQUESTKEYCONTAINER,
  175. ppwszKeyContainer);
  176. if (S_OK != hr)
  177. {
  178. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  179. {
  180. _JumpErrorStr(hr, error, "myGetCertRegStrValue", wszREGREQUESTKEYCONTAINER);
  181. }
  182. hr = myDupString(pwszSanitizedCAName, ppwszKeyContainer);
  183. _JumpIfError(hr, error, "myDupString");
  184. }
  185. CSASSERT(S_OK == hr);
  186. error:
  187. return(hr);
  188. }
  189. HRESULT
  190. FinishSuspendedSetupFromPKCS7(
  191. IN HINSTANCE hInstance,
  192. IN BOOL fUnattended,
  193. IN HWND hwnd,
  194. IN WCHAR const *pwszSanitizedCAName,
  195. IN OPTIONAL WCHAR const *pwszKeyContainer,
  196. IN DWORD iKey,
  197. IN BOOL fRenew,
  198. IN BYTE const *pbChain,
  199. IN DWORD cbChain)
  200. {
  201. HRESULT hr;
  202. CRYPT_KEY_PROV_INFO KeyProvInfo;
  203. WCHAR *pwszCommonName = NULL;
  204. WCHAR *pwszServerName = NULL;
  205. WCHAR *pwszCertFile = NULL;
  206. WCHAR *pwszKeyContainerReg = NULL;
  207. ENUM_CATYPES CAType;
  208. DWORD iCertNew;
  209. BOOL fUseDS;
  210. ALG_ID idAlg;
  211. BOOL fMachineKeyset;
  212. ZeroMemory(&KeyProvInfo, sizeof(KeyProvInfo));
  213. hr = myGetCARegHashCount(pwszSanitizedCAName, CSRH_CASIGCERT, &iCertNew);
  214. _JumpIfError(hr, error, "myGetCARegHashCount");
  215. if (NULL == pwszKeyContainer)
  216. {
  217. // get Key Index and Container name from registry
  218. hr = myGetCertRegKeyIndexAndContainer(
  219. pwszSanitizedCAName,
  220. &iKey,
  221. &pwszKeyContainerReg);
  222. _JumpIfError(hr, error, "myGetCertRegKeyIndexAndContainer");
  223. pwszKeyContainer = pwszKeyContainerReg;
  224. }
  225. // get CSP info
  226. hr = GetCertServerKeyProviderInfo(
  227. pwszSanitizedCAName,
  228. pwszKeyContainer,
  229. &idAlg,
  230. &fMachineKeyset,
  231. &KeyProvInfo);
  232. _JumpIfError(hr, error, "GetCertServerKeyProviderInfo");
  233. // get common name
  234. hr = myGetCertRegStrValue(
  235. pwszSanitizedCAName,
  236. NULL,
  237. NULL,
  238. wszREGCOMMONNAME,
  239. &pwszCommonName);
  240. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCOMMONNAME);
  241. // get ca type
  242. hr = myGetCertRegDWValue(
  243. pwszSanitizedCAName,
  244. NULL,
  245. NULL,
  246. wszREGCATYPE,
  247. (DWORD *) &CAType);
  248. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE);
  249. // use DS or not
  250. hr = myGetCertRegDWValue(
  251. pwszSanitizedCAName,
  252. NULL,
  253. NULL,
  254. wszREGCAUSEDS,
  255. (DWORD *) &fUseDS);
  256. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS);
  257. // server name
  258. hr = myGetCertRegStrValue(
  259. pwszSanitizedCAName,
  260. NULL,
  261. NULL,
  262. wszREGCASERVERNAME,
  263. &pwszServerName);
  264. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
  265. hr = myGetCARegFileNameTemplate(
  266. wszREGCACERTFILENAME,
  267. pwszServerName,
  268. pwszSanitizedCAName,
  269. iCertNew,
  270. iKey,
  271. &pwszCertFile);
  272. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  273. {
  274. _JumpIfError(hr, error, "myGetCARegFileNameTemplate");
  275. }
  276. hr = csiFinishInstallationFromPKCS7(
  277. hInstance,
  278. fUnattended,
  279. hwnd,
  280. pwszSanitizedCAName,
  281. pwszCommonName,
  282. &KeyProvInfo,
  283. CAType,
  284. iCertNew,
  285. iKey,
  286. fUseDS,
  287. fRenew,
  288. pwszServerName,
  289. pbChain,
  290. cbChain,
  291. pwszCertFile);
  292. _JumpIfError(hr, error, "csiFinishInstallationFromPKCS7");
  293. error:
  294. if (NULL != pwszKeyContainerReg)
  295. {
  296. LocalFree(pwszKeyContainerReg);
  297. }
  298. if (NULL != pwszCommonName)
  299. {
  300. LocalFree(pwszCommonName);
  301. }
  302. if (NULL != pwszCertFile)
  303. {
  304. LocalFree(pwszCertFile);
  305. }
  306. if (NULL != pwszServerName)
  307. {
  308. LocalFree(pwszServerName);
  309. }
  310. csiFreeKeyProvInfo(&KeyProvInfo);
  311. CSILOG(hr, IDS_ILOG_FINISHSUSPENDEDSETUP, NULL, NULL, NULL);
  312. return(hr);
  313. }
  314. typedef struct _CERTHIERINFO
  315. {
  316. HINSTANCE hInstance;
  317. BOOL fUnattended;
  318. WCHAR *pwszSanitizedCAName;
  319. WCHAR *pwszParentMachine;
  320. WCHAR *pwszParentCA;
  321. WCHAR *pwszParentMachineDefault;
  322. WCHAR *pwszParentCADefault;
  323. DWORD iCertNew;
  324. DWORD iKey;
  325. } CERTHIERINFO;
  326. VOID
  327. FreeCertHierInfo(
  328. IN OUT CERTHIERINFO *pCertHierInfo)
  329. {
  330. if (NULL != pCertHierInfo->pwszSanitizedCAName)
  331. {
  332. LocalFree(pCertHierInfo->pwszSanitizedCAName);
  333. }
  334. if (NULL != pCertHierInfo->pwszParentMachine)
  335. {
  336. LocalFree(pCertHierInfo->pwszParentMachine);
  337. }
  338. if (NULL != pCertHierInfo->pwszParentCA)
  339. {
  340. LocalFree(pCertHierInfo->pwszParentCA);
  341. }
  342. if (NULL != pCertHierInfo->pwszParentMachineDefault)
  343. {
  344. LocalFree(pCertHierInfo->pwszParentMachineDefault);
  345. }
  346. if (NULL != pCertHierInfo->pwszParentCADefault)
  347. {
  348. LocalFree(pCertHierInfo->pwszParentCADefault);
  349. }
  350. }
  351. CERTSRVUICASELECTION g_CertHierCARequestUICASelection =
  352. { NULL, NULL, NULL, NULL, NULL, ENUM_UNKNOWN_CA, false, true };
  353. HRESULT
  354. csiGetCARequestFileName(
  355. IN HINSTANCE hInstance,
  356. IN HWND hwnd,
  357. IN WCHAR const *pwszSanitizedCAName,
  358. IN DWORD iCertNew,
  359. IN DWORD iKey,
  360. OUT WCHAR **ppwszRequestFile)
  361. {
  362. HRESULT hr;
  363. WCHAR *pwszServerName = NULL;
  364. WCHAR *pwszRequestFile = NULL;
  365. WCHAR *pwszSharedFolder = NULL;
  366. // init
  367. *ppwszRequestFile = NULL;
  368. // get server name
  369. hr = myGetCertRegStrValue(
  370. pwszSanitizedCAName,
  371. NULL,
  372. NULL,
  373. wszREGCASERVERNAME,
  374. &pwszServerName);
  375. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
  376. hr = myGetCARegFileNameTemplate(
  377. wszREGREQUESTFILENAME,
  378. pwszServerName,
  379. pwszSanitizedCAName,
  380. iCertNew,
  381. iKey,
  382. &pwszRequestFile);
  383. if (S_OK != hr)
  384. {
  385. hr = myGetCertRegStrValue(
  386. NULL,
  387. NULL,
  388. NULL,
  389. wszREGDIRECTORY,
  390. &pwszSharedFolder);
  391. if (S_OK != hr)
  392. {
  393. CSASSERT(NULL == pwszSharedFolder);
  394. }
  395. hr = csiBuildCACertFileName(
  396. hInstance,
  397. hwnd,
  398. TRUE, // fUnattended
  399. pwszSharedFolder,
  400. pwszSanitizedCAName,
  401. L".req",
  402. 0, // iCertNew == 0!
  403. &pwszRequestFile);
  404. _JumpIfError(hr, error, "csiBuildCACertFileName");
  405. hr = mySetCARegFileNameTemplate(
  406. wszREGREQUESTFILENAME,
  407. pwszServerName,
  408. pwszSanitizedCAName,
  409. pwszRequestFile);
  410. _JumpIfError(hr, error, "mySetCARegFileNameTemplate");
  411. LocalFree(pwszRequestFile);
  412. pwszRequestFile = NULL;
  413. hr = csiBuildCACertFileName(
  414. hInstance,
  415. hwnd,
  416. TRUE, // fUnattended
  417. pwszSharedFolder,
  418. pwszSanitizedCAName,
  419. L".req",
  420. iCertNew,
  421. &pwszRequestFile);
  422. _JumpIfError(hr, error, "csiBuildCACertFileName");
  423. }
  424. *ppwszRequestFile = pwszRequestFile;
  425. pwszRequestFile = NULL;
  426. hr = S_OK;
  427. error:
  428. if (NULL != pwszRequestFile)
  429. {
  430. LocalFree(pwszRequestFile);
  431. }
  432. if (NULL != pwszServerName)
  433. {
  434. LocalFree(pwszServerName);
  435. }
  436. if (NULL != pwszSharedFolder)
  437. {
  438. LocalFree(pwszSharedFolder);
  439. }
  440. return hr;
  441. }
  442. HRESULT
  443. InitCertHierControls(
  444. HWND hDlg,
  445. CERTHIERINFO *pCertHierInfo)
  446. {
  447. HRESULT hr;
  448. BOOL fCAsExist;
  449. WCHAR *pwszHelpText = NULL;
  450. WCHAR *pwszRequestFile = NULL;
  451. WCHAR *pwszExpandedHelpText = NULL;
  452. WCHAR *pwszzCAList = NULL;
  453. BOOL fSetCA = FALSE;
  454. if (NULL != pCertHierInfo->pwszParentMachineDefault)
  455. {
  456. if (!SetWindowText(
  457. GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  458. pCertHierInfo->pwszParentMachineDefault))
  459. {
  460. hr = myHLastError();
  461. _JumpError(hr, error, "SetWindowText");
  462. }
  463. if (NULL != pCertHierInfo->pwszParentCADefault)
  464. {
  465. DWORD cwcCA = wcslen(pCertHierInfo->pwszParentCADefault);
  466. pwszzCAList = (WCHAR *) LocalAlloc(
  467. LMEM_FIXED,
  468. (cwcCA + 2) * sizeof(WCHAR));
  469. if (NULL == pwszzCAList)
  470. {
  471. hr = E_OUTOFMEMORY;
  472. _JumpError(hr, error, "LocalAlloc");
  473. }
  474. wcscpy(pwszzCAList, pCertHierInfo->pwszParentCADefault);
  475. pwszzCAList[cwcCA + 1] = L'\0';
  476. hr = myUICASelectionUpdateCAList(
  477. GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  478. pwszzCAList);
  479. _JumpIfError(hr, error, "myUICASelectionUpdateCAList");
  480. fSetCA = TRUE;
  481. }
  482. }
  483. // load formatted help string
  484. hr = myLoadRCString(
  485. pCertHierInfo->hInstance,
  486. IDS_REQUEST_HELPTEXT,
  487. &pwszHelpText);
  488. _JumpIfError(hr, error, "myLoadRCString");
  489. // get request file name
  490. hr = csiGetCARequestFileName(
  491. pCertHierInfo->hInstance,
  492. hDlg,
  493. pCertHierInfo->pwszSanitizedCAName,
  494. pCertHierInfo->iCertNew,
  495. pCertHierInfo->iKey,
  496. &pwszRequestFile);
  497. _JumpIfError(hr, error, "csiGetCARequestFileName");
  498. // replace %1
  499. if (!FormatMessage(
  500. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  501. FORMAT_MESSAGE_FROM_STRING |
  502. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  503. pwszHelpText,
  504. 0,
  505. 0,
  506. reinterpret_cast<WCHAR *>(&pwszExpandedHelpText),
  507. 0,
  508. reinterpret_cast<va_list *>
  509. (const_cast<WCHAR **>(&pwszRequestFile))) )
  510. {
  511. hr = myHLastError();
  512. _JumpError(hr, error, "FormatMessage");
  513. }
  514. // set help text
  515. SetWindowText(GetDlgItem(hDlg, IDC_REQUEST_HELPTEXT), pwszExpandedHelpText);
  516. hr = myInitUICASelectionControls(
  517. &g_CertHierCARequestUICASelection,
  518. pCertHierInfo->hInstance,
  519. hDlg,
  520. GetDlgItem(hDlg, IDC_BROWSE_CA),
  521. GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  522. GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  523. csiIsAnyDSCAAvailable(),
  524. &fCAsExist);
  525. _JumpIfError(hr, error, "myInitUICASelectionControls");
  526. if (fSetCA)
  527. {
  528. hr = myUICAConditionallyDisplayEnterpriseWarning(
  529. &g_CertHierCARequestUICASelection);
  530. _JumpIfError(hr, error, "myUICAConditionallyDisplayEnterpriseWarning");
  531. }
  532. error:
  533. if (NULL != pwszzCAList)
  534. {
  535. LocalFree(pwszzCAList);
  536. }
  537. if (NULL != pwszHelpText)
  538. {
  539. LocalFree(pwszHelpText);
  540. }
  541. if (NULL != pwszRequestFile)
  542. {
  543. LocalFree(pwszRequestFile);
  544. }
  545. if (NULL != pwszExpandedHelpText)
  546. {
  547. LocalFree(pwszExpandedHelpText);
  548. }
  549. return(hr);
  550. }
  551. HRESULT
  552. HandleOKButton(
  553. HWND hDlg,
  554. CERTHIERINFO *pCertHierInfo,
  555. BOOL *pfLeave)
  556. {
  557. HRESULT hr;
  558. WCHAR *pwszParentMachine = NULL;
  559. WCHAR *pwszParentCA = NULL;
  560. hr = myUICASelectionValidation(&g_CertHierCARequestUICASelection, pfLeave);
  561. _JumpIfError(hr, error, "myUICASelectionValidation");
  562. if (!*pfLeave)
  563. {
  564. goto error;
  565. }
  566. // get parent ca info
  567. hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  568. &pwszParentMachine);
  569. _JumpIfError(hr, error, "myUIGetWindowText");
  570. hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  571. &pwszParentCA);
  572. _JumpIfError(hr, error, "myUIGetWindowText");
  573. pCertHierInfo->pwszParentMachine = pwszParentMachine;
  574. pwszParentMachine = NULL;
  575. pCertHierInfo->pwszParentCA = pwszParentCA;
  576. pwszParentCA = NULL;
  577. hr = S_OK;
  578. error:
  579. if (NULL != pwszParentMachine)
  580. {
  581. LocalFree(pwszParentMachine);
  582. }
  583. if (NULL != pwszParentCA)
  584. {
  585. LocalFree(pwszParentCA);
  586. }
  587. return(hr);
  588. }
  589. INT_PTR CALLBACK
  590. CertHierProc(
  591. HWND hDlg,
  592. UINT iMsg,
  593. WPARAM wParam,
  594. LPARAM lParam)
  595. {
  596. HRESULT hr;
  597. BOOL ret = FALSE;
  598. BOOL fLeave;
  599. static CERTHIERINFO *s_pCertHierInfo = NULL;
  600. static BOOL s_fComputerChange = FALSE;
  601. switch (iMsg)
  602. {
  603. case WM_INITDIALOG:
  604. s_pCertHierInfo = (CERTHIERINFO *) lParam;
  605. hr = InitCertHierControls(hDlg, s_pCertHierInfo);
  606. _JumpIfError(hr, error, "InitCertHierControls");
  607. ret = TRUE;
  608. break;
  609. case WM_COMMAND:
  610. switch (LOWORD(wParam))
  611. {
  612. case IDC_BROWSE_CA:
  613. ret = TRUE;
  614. hr = myUICAHandleCABrowseButton(
  615. &g_CertHierCARequestUICASelection,
  616. csiIsAnyDSCAAvailable(),
  617. IDS_CA_PICKER_TITLE,
  618. IDS_CA_PICKER_PROMPT,
  619. NULL);
  620. _JumpIfError(hr, error, "myUICAHandleCABrowseButton");
  621. break;
  622. case IDC_PARENT_CA_NAME:
  623. hr = myUICAHandleCAListDropdown(
  624. (int)HIWORD(wParam),
  625. &g_CertHierCARequestUICASelection,
  626. &s_fComputerChange);
  627. _PrintIfError(hr, "myUICAHandleCAListDropdown");
  628. break;
  629. case IDC_PARENT_COMPUTER_NAME:
  630. switch ((int)HIWORD(wParam))
  631. {
  632. case EN_CHANGE: // edit change
  633. s_fComputerChange = TRUE;
  634. break;
  635. }
  636. break;
  637. case IDOK:
  638. ret = TRUE;
  639. hr = HandleOKButton(hDlg, s_pCertHierInfo, &fLeave);
  640. _PrintIfError(hr, "HandleOKButton");
  641. if (fLeave)
  642. {
  643. // update return status
  644. ret = EndDialog(hDlg, IDOK);
  645. goto error; //done;
  646. }
  647. break;
  648. case IDCANCEL:
  649. ret = EndDialog(hDlg, IDCANCEL);
  650. break;
  651. }
  652. break;
  653. }
  654. error:
  655. return(ret);
  656. }
  657. VOID
  658. MarkSetupComplete(
  659. IN WCHAR const *pwszSanitizedCAName)
  660. {
  661. HRESULT hr;
  662. // Clear pending/denied flags:
  663. hr = SetSetupStatus(
  664. pwszSanitizedCAName,
  665. SETUP_SUSPEND_FLAG |
  666. SETUP_ONLINE_FLAG |
  667. SETUP_REQUEST_FLAG |
  668. SETUP_DENIED_FLAG,
  669. FALSE);
  670. _PrintIfError(hr, "SetSetupStatus");
  671. // Force new CRL generation on startup:
  672. hr = SetSetupStatus(pwszSanitizedCAName, SETUP_FORCECRL_FLAG, TRUE);
  673. _PrintIfError(hr, "SetSetupStatus");
  674. CSILOG(hr, IDS_ILOG_SETUPCOMPLETE, NULL, NULL, NULL);
  675. }
  676. HRESULT
  677. FindKeyIndex(
  678. IN HCERTSTORE hMyStore,
  679. IN WCHAR const *pwszSanitizedCAName,
  680. IN BOOL fUnattended,
  681. IN BOOL fMachineKeyset,
  682. IN DWORD cCert,
  683. CRYPT_KEY_PROV_INFO *pKeyMatch,
  684. OUT DWORD *piKey)
  685. {
  686. HRESULT hr;
  687. DWORD i;
  688. CERT_CONTEXT const *pccCert = NULL;
  689. CRYPT_KEY_PROV_INFO *pKey = NULL;
  690. HCRYPTPROV hProv = NULL;
  691. CERT_PUBLIC_KEY_INFO *pPubKeyMatch = NULL;
  692. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  693. DWORD cb;
  694. DWORD NameId;
  695. *piKey = MAXDWORD;
  696. // get CSP handle
  697. if (!myCertSrvCryptAcquireContext(
  698. &hProv,
  699. pKeyMatch->pwszContainerName,
  700. pKeyMatch->pwszProvName,
  701. pKeyMatch->dwProvType,
  702. fUnattended? CRYPT_SILENT : 0,
  703. fMachineKeyset))
  704. {
  705. hr = myHLastError();
  706. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  707. }
  708. if (hProv == NULL)
  709. {
  710. hr = E_HANDLE;
  711. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  712. }
  713. if (!myCryptExportPublicKeyInfo(
  714. hProv,
  715. AT_SIGNATURE,
  716. CERTLIB_USE_LOCALALLOC,
  717. &pPubKeyMatch,
  718. &cb))
  719. {
  720. hr = myHLastError();
  721. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  722. }
  723. CryptReleaseContext(hProv, 0);
  724. hProv = NULL;
  725. for (i = 0; ; i++)
  726. {
  727. if (i >= cCert)
  728. {
  729. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  730. _JumpError(hr, error, "old key not found");
  731. }
  732. hr = myFindCACertByHashIndex(
  733. hMyStore,
  734. pwszSanitizedCAName,
  735. CSRH_CASIGCERT,
  736. i,
  737. &NameId,
  738. &pccCert);
  739. if (S_FALSE == hr)
  740. {
  741. continue;
  742. }
  743. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  744. // get the key provider info
  745. if (!myCertGetCertificateContextProperty(
  746. pccCert,
  747. CERT_KEY_PROV_INFO_PROP_ID,
  748. CERTLIB_USE_LOCALALLOC,
  749. (VOID **) &pKey,
  750. &cb))
  751. {
  752. hr = myHLastError();
  753. _JumpError(hr, error, "CertGetCertificateContextProperty");
  754. }
  755. // get CSP handle
  756. if (!myCertSrvCryptAcquireContext(
  757. &hProv,
  758. pKey->pwszContainerName,
  759. pKey->pwszProvName,
  760. pKey->dwProvType,
  761. fUnattended? CRYPT_SILENT : 0,
  762. fMachineKeyset))
  763. {
  764. hr = myHLastError();
  765. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  766. }
  767. if (hProv == NULL)
  768. {
  769. hr = E_HANDLE;
  770. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  771. }
  772. if (!myCryptExportPublicKeyInfo(
  773. hProv,
  774. AT_SIGNATURE,
  775. CERTLIB_USE_LOCALALLOC,
  776. &pPubKey,
  777. &cb))
  778. {
  779. hr = myHLastError();
  780. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  781. }
  782. // by design, CertComparePublicKeyInfo doesn't set last error!
  783. if (CertComparePublicKeyInfo(X509_ASN_ENCODING, pPubKey, pPubKeyMatch))
  784. {
  785. hr = myGetNameId(pccCert, &NameId);
  786. if (S_OK != hr)
  787. {
  788. *piKey = i;
  789. }
  790. else
  791. {
  792. *piKey = CANAMEIDTOIKEY(NameId);
  793. }
  794. break;
  795. }
  796. LocalFree(pPubKey);
  797. pPubKey = NULL;
  798. CryptReleaseContext(hProv, 0);
  799. hProv = NULL;
  800. LocalFree(pKey);
  801. pKey = NULL;
  802. CertFreeCertificateContext(pccCert);
  803. pccCert = NULL;
  804. }
  805. hr = S_OK;
  806. error:
  807. if (NULL != pPubKeyMatch)
  808. {
  809. LocalFree(pPubKeyMatch);
  810. }
  811. if (NULL != pPubKey)
  812. {
  813. LocalFree(pPubKey);
  814. }
  815. if (NULL != hProv)
  816. {
  817. CryptReleaseContext(hProv, 0);
  818. }
  819. if (NULL != pKey)
  820. {
  821. LocalFree(pKey);
  822. }
  823. if (NULL != pccCert)
  824. {
  825. CertFreeCertificateContext(pccCert);
  826. }
  827. CSILOG(hr, IDS_ILOG_KEYINDEX, NULL, NULL, piKey);
  828. return(hr);
  829. }
  830. HRESULT
  831. LoadCurrentCACertAndKeyInfo(
  832. IN WCHAR const *pwszSanitizedCAName,
  833. IN BOOL fNewKey,
  834. IN BOOL fUnattended,
  835. IN BOOL fMachineKeyset,
  836. IN DWORD iCertNew,
  837. OUT DWORD *piKey,
  838. OUT WCHAR **ppwszKeyContainer,
  839. OUT CERT_CONTEXT const **ppccCertOld)
  840. {
  841. HRESULT hr;
  842. HCERTSTORE hMyStore = NULL;
  843. DWORD cbKey;
  844. CRYPT_KEY_PROV_INFO *pKey = NULL;
  845. WCHAR *pwszKeyContainer = NULL;
  846. DWORD NameId;
  847. *ppwszKeyContainer = NULL;
  848. *ppccCertOld = NULL;
  849. *piKey = MAXDWORD;
  850. // open MY store
  851. hMyStore = CertOpenStore(
  852. CERT_STORE_PROV_SYSTEM_W,
  853. X509_ASN_ENCODING,
  854. NULL, // hProv
  855. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  856. CERT_STORE_READONLY_FLAG,
  857. wszMY_CERTSTORE);
  858. if (NULL == hMyStore)
  859. {
  860. hr = myHLastError();
  861. _JumpError(hr, error, "CertOpenStore");
  862. }
  863. hr = myFindCACertByHashIndex(
  864. hMyStore,
  865. pwszSanitizedCAName,
  866. CSRH_CASIGCERT,
  867. iCertNew - 1,
  868. &NameId,
  869. ppccCertOld);
  870. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  871. if (fNewKey)
  872. {
  873. *piKey = iCertNew; // New key: iKey set to iCert
  874. hr = myAllocIndexedName(
  875. pwszSanitizedCAName,
  876. *piKey,
  877. MAXDWORD, // IndexTarget
  878. &pwszKeyContainer);
  879. _JumpIfError(hr, error, "myAllocIndexedName");
  880. }
  881. else
  882. {
  883. // get the key provider info
  884. if (!myCertGetCertificateContextProperty(
  885. *ppccCertOld,
  886. CERT_KEY_PROV_INFO_PROP_ID,
  887. CERTLIB_USE_LOCALALLOC,
  888. (VOID **) &pKey,
  889. &cbKey))
  890. {
  891. hr = myHLastError();
  892. _JumpError(hr, error, "CertGetCertificateContextProperty");
  893. }
  894. hr = myDupString(pKey->pwszContainerName, &pwszKeyContainer);
  895. _JumpIfError(hr, error, "myDupString");
  896. // Reuse key: iKey set to match oldest iCert using this key:
  897. hr = FindKeyIndex(
  898. hMyStore,
  899. pwszSanitizedCAName,
  900. fUnattended,
  901. fMachineKeyset,
  902. iCertNew,
  903. pKey,
  904. piKey);
  905. _JumpIfError(hr, error, "FindKeyIndex");
  906. CSASSERT(MAXDWORD != *piKey);
  907. }
  908. *ppwszKeyContainer = pwszKeyContainer;
  909. pwszKeyContainer = NULL;
  910. CSASSERT(S_OK == hr);
  911. error:
  912. if (NULL != pwszKeyContainer)
  913. {
  914. LocalFree(pwszKeyContainer);
  915. }
  916. if (NULL != pKey)
  917. {
  918. LocalFree(pKey);
  919. }
  920. if (NULL != hMyStore)
  921. {
  922. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  923. }
  924. CSILOG(hr, IDS_ILOG_LOADOLDCERT, *ppwszKeyContainer, NULL, piKey);
  925. return(hr);
  926. }
  927. HRESULT
  928. ReplaceExtension(
  929. IN CERT_EXTENSION const *pExtension,
  930. IN OUT DWORD *pcExtension,
  931. IN OUT CERT_EXTENSION *rgExtension)
  932. {
  933. DWORD i;
  934. CSASSERT(NULL != pExtension->pszObjId);
  935. for (i = 0; ; i++)
  936. {
  937. if (i == *pcExtension)
  938. {
  939. if (NULL != pExtension->Value.pbData)
  940. {
  941. (*pcExtension)++; // not found: append to array
  942. }
  943. break;
  944. }
  945. CSASSERT(i < *pcExtension);
  946. if (0 == strcmp(pExtension->pszObjId, rgExtension[i].pszObjId))
  947. {
  948. if (NULL == pExtension->Value.pbData)
  949. {
  950. // remove extension: copy last extension on top of this one
  951. // and decrement extension count
  952. (*pcExtension)--;
  953. pExtension = &rgExtension[*pcExtension];
  954. }
  955. break;
  956. }
  957. }
  958. rgExtension[i] = *pExtension; // append or overwrite extension
  959. return(S_OK);
  960. }
  961. HRESULT
  962. GetMinimumCertValidityPeriod(
  963. IN WCHAR const *pwszSanitizedCAName,
  964. IN DWORD cCert,
  965. OUT LONGLONG *pTimeDelta)
  966. {
  967. HRESULT hr;
  968. HCERTSTORE hMyStore = NULL;
  969. DWORD NameId;
  970. CERT_CONTEXT const *pcc = NULL;
  971. BOOL fFirst = TRUE;
  972. DWORD i;
  973. // open MY store
  974. hMyStore = CertOpenStore(
  975. CERT_STORE_PROV_SYSTEM_W,
  976. X509_ASN_ENCODING,
  977. NULL, // hProv
  978. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  979. CERT_STORE_READONLY_FLAG,
  980. wszMY_CERTSTORE);
  981. if (NULL == hMyStore)
  982. {
  983. hr = myHLastError();
  984. _JumpError(hr, error, "CertOpenStore");
  985. }
  986. for (i = 0; i < cCert; i++)
  987. {
  988. LONGLONG TimeDelta;
  989. hr = myFindCACertByHashIndex(
  990. hMyStore,
  991. pwszSanitizedCAName,
  992. CSRH_CASIGCERT,
  993. i,
  994. &NameId,
  995. &pcc);
  996. if (S_OK != hr)
  997. {
  998. _PrintError(hr, "myFindCACertByHashIndex");
  999. continue;
  1000. }
  1001. TimeDelta = mySubtractFileTimes(
  1002. &pcc->pCertInfo->NotAfter,
  1003. &pcc->pCertInfo->NotBefore);
  1004. DBGPRINT((
  1005. DBG_SS_CERTLIBI,
  1006. "iCert=%u TimeDelta=%x:%x\n",
  1007. i,
  1008. (DWORD) (TimeDelta >> 32),
  1009. (DWORD) TimeDelta));
  1010. if (fFirst || *pTimeDelta > TimeDelta)
  1011. {
  1012. *pTimeDelta = TimeDelta;
  1013. DBGPRINT((
  1014. DBG_SS_CERTLIBI,
  1015. "iCert=%u *pTimeDelta=%x:%x\n",
  1016. i,
  1017. (DWORD) (*pTimeDelta >> 32),
  1018. (DWORD) *pTimeDelta));
  1019. fFirst = FALSE;
  1020. }
  1021. CertFreeCertificateContext(pcc);
  1022. pcc = NULL;
  1023. }
  1024. if (fFirst)
  1025. {
  1026. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1027. _JumpError(hr, error, "no old Certs");
  1028. }
  1029. hr = S_OK;
  1030. error:
  1031. if (NULL != pcc)
  1032. {
  1033. CertFreeCertificateContext(pcc);
  1034. }
  1035. if (NULL != hMyStore)
  1036. {
  1037. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1038. }
  1039. return(hr);
  1040. }
  1041. HRESULT
  1042. GetCertHashExtension(
  1043. IN CERT_CONTEXT const *pCert,
  1044. OUT BYTE **ppbData,
  1045. OUT DWORD *pcbData)
  1046. {
  1047. HRESULT hr;
  1048. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  1049. CRYPT_DATA_BLOB Blob;
  1050. DWORD cbHash;
  1051. cbHash = sizeof(abHash);
  1052. if (!CertGetCertificateContextProperty(
  1053. pCert,
  1054. CERT_HASH_PROP_ID,
  1055. abHash,
  1056. &cbHash))
  1057. {
  1058. hr = myHLastError();
  1059. _JumpError(hr, error, "CertGetCertificateContextProperty");
  1060. }
  1061. Blob.cbData = cbHash;
  1062. Blob.pbData = abHash;
  1063. if (!myEncodeObject(
  1064. X509_ASN_ENCODING,
  1065. X509_OCTET_STRING,
  1066. &Blob,
  1067. 0,
  1068. CERTLIB_USE_LOCALALLOC,
  1069. ppbData,
  1070. pcbData))
  1071. {
  1072. hr = myHLastError();
  1073. _JumpError(hr, error, "myEncodeObject");
  1074. }
  1075. hr = S_OK;
  1076. error:
  1077. return(hr);
  1078. }
  1079. VOID
  1080. csiLogInfError(
  1081. IN HINF hInf,
  1082. IN HRESULT hr)
  1083. {
  1084. if (S_OK != hr && INVALID_HANDLE_VALUE != hInf)
  1085. {
  1086. WCHAR *pwszInfError = myInfGetError();
  1087. _PrintErrorStr(hr, "csiLogInfError", pwszInfError);
  1088. CSILOG(hr, IDS_ILOG_INFERROR, pwszInfError, NULL, NULL);
  1089. if (NULL != pwszInfError)
  1090. {
  1091. LocalFree(pwszInfError);
  1092. }
  1093. }
  1094. }
  1095. HRESULT
  1096. CloneRootCert(
  1097. IN HINF hInf,
  1098. IN CERT_CONTEXT const *pccCertOld,
  1099. IN HCRYPTPROV hProv,
  1100. IN WCHAR const *pwszSanitizedCAName,
  1101. IN DWORD iCert,
  1102. IN DWORD iKey,
  1103. IN BOOL fUseDS,
  1104. IN BOOL fNewKey,
  1105. IN DWORD dwRevocationFlags,
  1106. IN HINSTANCE hInstance,
  1107. IN BOOL fUnattended,
  1108. IN HWND hwnd,
  1109. OUT BYTE **ppbCert,
  1110. OUT DWORD *pcbCert)
  1111. {
  1112. HRESULT hr;
  1113. CERT_INFO Cert;
  1114. GUID guidSerialNumber;
  1115. LONGLONG TimeDelta;
  1116. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  1117. DWORD cbPubKey;
  1118. DWORD NameId;
  1119. CERT_EXTENSION *paext = NULL;
  1120. FILETIME ftNotAfterMin;
  1121. DWORD dwValidityPeriodCount;
  1122. ENUM_PERIOD enumValidityPeriod;
  1123. CERT_EXTENSION *pext;
  1124. DWORD cExtInf = 0;
  1125. CERT_EXTENSION *rgExtInf = NULL;
  1126. DWORD cExtMerged;
  1127. CERT_EXTENSION *rgExtMerged = NULL;
  1128. #define CEXT_REPLACED 9
  1129. CERT_EXTENSION extBasicConstraints =
  1130. { NULL, FALSE, 0, NULL};
  1131. CERT_EXTENSION extSKI =
  1132. { szOID_SUBJECT_KEY_IDENTIFIER, FALSE, 0, NULL };
  1133. CERT_EXTENSION extCDP =
  1134. { szOID_CRL_DIST_POINTS, FALSE, 0, NULL };
  1135. CERT_EXTENSION extVersion =
  1136. { szOID_CERTSRV_CA_VERSION, FALSE, 0, NULL };
  1137. CERT_EXTENSION extPreviousHash =
  1138. { szOID_CERTSRV_PREVIOUS_CERT_HASH, FALSE, 0, NULL };
  1139. CERT_EXTENSION extPolicy =
  1140. { szOID_CERT_POLICIES, FALSE, 0, NULL };
  1141. CERT_EXTENSION extCross =
  1142. { szOID_CROSS_CERT_DIST_POINTS, FALSE, 0, NULL };
  1143. CERT_EXTENSION extAIA =
  1144. { szOID_AUTHORITY_INFO_ACCESS, FALSE, 0, NULL };
  1145. CERT_EXTENSION extEKU =
  1146. { NULL, FALSE, 0, NULL};
  1147. *ppbCert = NULL;
  1148. CopyMemory(&Cert, pccCertOld->pCertInfo, sizeof(Cert));
  1149. Cert.dwVersion = CERT_V3;
  1150. myGenerateGuidSerialNumber(&guidSerialNumber);
  1151. Cert.SerialNumber.pbData = (BYTE *) &guidSerialNumber;
  1152. Cert.SerialNumber.cbData = sizeof(guidSerialNumber);
  1153. if (!myAreBlobsSame(
  1154. Cert.Issuer.pbData,
  1155. Cert.Issuer.cbData,
  1156. Cert.Subject.pbData,
  1157. Cert.Subject.cbData))
  1158. {
  1159. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1160. _JumpError(hr, error, "non-Root Cert");
  1161. }
  1162. if (!myCryptExportPublicKeyInfo(
  1163. hProv,
  1164. AT_SIGNATURE,
  1165. CERTLIB_USE_LOCALALLOC,
  1166. &pPubKey,
  1167. &cbPubKey))
  1168. {
  1169. hr = myHLastError();
  1170. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  1171. }
  1172. Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
  1173. // make new cert expire at least 1 minute after old cert.
  1174. ftNotAfterMin = Cert.NotAfter;
  1175. myMakeExprDateTime(&ftNotAfterMin, 1, ENUM_PERIOD_MINUTES);
  1176. GetSystemTimeAsFileTime(&Cert.NotBefore);
  1177. hr = myInfGetValidityPeriod(
  1178. hInf,
  1179. NULL, // pwszValidityPeriodCount
  1180. NULL, // pwszValidityPeriodString
  1181. &dwValidityPeriodCount,
  1182. &enumValidityPeriod,
  1183. NULL); // pfSwap
  1184. csiLogInfError(hInf, hr);
  1185. if (S_OK == hr)
  1186. {
  1187. Cert.NotAfter = Cert.NotBefore;
  1188. myMakeExprDateTime(
  1189. &Cert.NotAfter,
  1190. dwValidityPeriodCount,
  1191. enumValidityPeriod);
  1192. TimeDelta = 0;
  1193. }
  1194. else
  1195. {
  1196. hr = GetMinimumCertValidityPeriod(
  1197. pwszSanitizedCAName,
  1198. iCert,
  1199. &TimeDelta);
  1200. _JumpIfError(hr, error, "GetMinimumCertValidityPeriod");
  1201. CSASSERT(0 != TimeDelta);
  1202. }
  1203. myMakeExprDateTime(
  1204. &Cert.NotBefore,
  1205. -CCLOCKSKEWMINUTESDEFAULT,
  1206. ENUM_PERIOD_MINUTES);
  1207. if (0 != TimeDelta)
  1208. {
  1209. Cert.NotAfter = Cert.NotBefore;
  1210. myAddToFileTime(&Cert.NotAfter, TimeDelta);
  1211. }
  1212. // make new cert expire at least 1 minute after old cert.
  1213. if (0 > CompareFileTime(&Cert.NotAfter, &ftNotAfterMin))
  1214. {
  1215. Cert.NotAfter = ftNotAfterMin;
  1216. }
  1217. if (!fNewKey)
  1218. {
  1219. Cert.NotBefore = pccCertOld->pCertInfo->NotBefore;
  1220. }
  1221. paext = (CERT_EXTENSION *) LocalAlloc(
  1222. LMEM_FIXED,
  1223. (Cert.cExtension + CEXT_REPLACED) * sizeof(paext[0]));
  1224. if (NULL == paext)
  1225. {
  1226. hr = E_OUTOFMEMORY;
  1227. _JumpError(hr, error, "LocalAlloc");
  1228. }
  1229. CopyMemory(paext, Cert.rgExtension, Cert.cExtension * sizeof(paext[0]));
  1230. Cert.rgExtension = paext;
  1231. // Basic constraints extension:
  1232. hr = myInfGetBasicConstraints2CAExtensionOrDefault(hInf, &extBasicConstraints);
  1233. csiLogInfError(hInf, hr);
  1234. _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
  1235. ReplaceExtension(&extBasicConstraints, &Cert.cExtension, Cert.rgExtension);
  1236. // Subject Key Identifier extension:
  1237. // If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
  1238. pext = NULL;
  1239. if (!fNewKey)
  1240. {
  1241. pext = CertFindExtension(
  1242. szOID_SUBJECT_KEY_IDENTIFIER,
  1243. Cert.cExtension,
  1244. Cert.rgExtension);
  1245. }
  1246. if (NULL == pext)
  1247. {
  1248. hr = myCreateSubjectKeyIdentifierExtension(
  1249. pPubKey,
  1250. &extSKI.Value.pbData,
  1251. &extSKI.Value.cbData);
  1252. _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
  1253. ReplaceExtension(&extSKI, &Cert.cExtension, Cert.rgExtension);
  1254. }
  1255. hr = CreateRevocationExtension(
  1256. hInf,
  1257. pwszSanitizedCAName,
  1258. iCert,
  1259. iKey,
  1260. fUseDS,
  1261. dwRevocationFlags,
  1262. &extCDP.fCritical,
  1263. &extCDP.Value.pbData,
  1264. &extCDP.Value.cbData);
  1265. _PrintIfError2(hr, "CreateRevocationExtension", S_FALSE);
  1266. if (S_OK == hr || S_FALSE == hr)
  1267. {
  1268. ReplaceExtension(&extCDP, &Cert.cExtension, Cert.rgExtension);
  1269. }
  1270. // Build the CA Version extension
  1271. NameId = MAKECANAMEID(iCert, iKey);
  1272. if (!myEncodeObject(
  1273. X509_ASN_ENCODING,
  1274. X509_INTEGER,
  1275. &NameId,
  1276. 0,
  1277. CERTLIB_USE_LOCALALLOC,
  1278. &extVersion.Value.pbData,
  1279. &extVersion.Value.cbData))
  1280. {
  1281. hr = myHLastError();
  1282. _JumpError(hr, error, "myEncodeObject");
  1283. }
  1284. ReplaceExtension(&extVersion, &Cert.cExtension, Cert.rgExtension);
  1285. // Build the previous CA cert hash extension
  1286. hr = GetCertHashExtension(
  1287. pccCertOld,
  1288. &extPreviousHash.Value.pbData,
  1289. &extPreviousHash.Value.cbData);
  1290. _JumpIfError(hr, error, "GetCertHashExtension");
  1291. ReplaceExtension(&extPreviousHash, &Cert.cExtension, Cert.rgExtension);
  1292. // Build the Policy Statement extension
  1293. hr = myInfGetPolicyStatementExtension(hInf, &extPolicy);
  1294. csiLogInfError(hInf, hr);
  1295. if (S_OK == hr || S_FALSE == hr)
  1296. {
  1297. ReplaceExtension(&extPolicy, &Cert.cExtension, Cert.rgExtension);
  1298. }
  1299. // Build the Cross Cert Dist Points extension
  1300. hr = myInfGetCrossCertDistributionPointsExtension(hInf, &extCross);
  1301. csiLogInfError(hInf, hr);
  1302. if (S_OK == hr || S_FALSE == hr)
  1303. {
  1304. ReplaceExtension(&extCross, &Cert.cExtension, Cert.rgExtension);
  1305. }
  1306. // Build the Authority Information Access extension
  1307. hr = CreateAuthorityInformationAccessExtension(
  1308. hInf,
  1309. pwszSanitizedCAName,
  1310. iCert,
  1311. iKey,
  1312. fUseDS,
  1313. &extAIA.fCritical,
  1314. &extAIA.Value.pbData,
  1315. &extAIA.Value.cbData);
  1316. _PrintIfError3(
  1317. hr,
  1318. "CreateAuthorityInformationAccessExtension",
  1319. E_HANDLE,
  1320. S_FALSE);
  1321. if (S_OK == hr || S_FALSE == hr)
  1322. {
  1323. ReplaceExtension(&extAIA, &Cert.cExtension, Cert.rgExtension);
  1324. }
  1325. // Build the Enhanced Key Usage extension
  1326. hr = myInfGetEnhancedKeyUsageExtension(hInf, &extEKU);
  1327. csiLogInfError(hInf, hr);
  1328. if (S_OK == hr || S_FALSE == hr)
  1329. {
  1330. ReplaceExtension(&extEKU, &Cert.cExtension, Cert.rgExtension);
  1331. }
  1332. hr = myInfGetExtensions(hInf, &cExtInf, &rgExtInf);
  1333. csiLogInfError(hInf, hr);
  1334. _PrintIfError(hr, "myInfGetExtensions");
  1335. if (0 != cExtInf)
  1336. {
  1337. hr = myMergeExtensions(
  1338. Cert.cExtension,
  1339. Cert.rgExtension,
  1340. cExtInf,
  1341. rgExtInf,
  1342. &cExtMerged,
  1343. &rgExtMerged);
  1344. _JumpIfError(hr, error, "myMergeExtensions");
  1345. Cert.cExtension = cExtMerged;
  1346. Cert.rgExtension = rgExtMerged;
  1347. }
  1348. if (0 == Cert.cExtension)
  1349. {
  1350. Cert.dwVersion = CERT_V1;
  1351. }
  1352. hr = EncodeCertAndSign(
  1353. hProv,
  1354. &Cert,
  1355. Cert.SignatureAlgorithm.pszObjId,
  1356. ppbCert,
  1357. pcbCert,
  1358. hInstance,
  1359. fUnattended,
  1360. hwnd);
  1361. _JumpIfError(hr, error, "EncodeCertAndSign");
  1362. error:
  1363. if (NULL != extBasicConstraints.Value.pbData)
  1364. {
  1365. LocalFree(extBasicConstraints.Value.pbData);
  1366. }
  1367. if (NULL != extSKI.Value.pbData)
  1368. {
  1369. LocalFree(extSKI.Value.pbData);
  1370. }
  1371. if (NULL != extCDP.Value.pbData)
  1372. {
  1373. LocalFree(extCDP.Value.pbData);
  1374. }
  1375. if (NULL != extVersion.Value.pbData)
  1376. {
  1377. LocalFree(extVersion.Value.pbData);
  1378. }
  1379. if (NULL != extPreviousHash.Value.pbData)
  1380. {
  1381. LocalFree(extPreviousHash.Value.pbData);
  1382. }
  1383. if (NULL != extPolicy.Value.pbData)
  1384. {
  1385. LocalFree(extPolicy.Value.pbData);
  1386. }
  1387. if (NULL != extCross.Value.pbData)
  1388. {
  1389. LocalFree(extCross.Value.pbData);
  1390. }
  1391. if (NULL != extAIA.Value.pbData)
  1392. {
  1393. LocalFree(extAIA.Value.pbData);
  1394. }
  1395. if (NULL != extEKU.Value.pbData)
  1396. {
  1397. LocalFree(extEKU.Value.pbData);
  1398. }
  1399. if (NULL != rgExtMerged)
  1400. {
  1401. LocalFree(rgExtMerged);
  1402. }
  1403. myInfFreeExtensions(cExtInf, rgExtInf);
  1404. if (NULL != paext)
  1405. {
  1406. LocalFree(paext);
  1407. }
  1408. if (NULL != pPubKey)
  1409. {
  1410. LocalFree(pPubKey);
  1411. }
  1412. CSILOG(hr, IDS_ILOG_CLONECERT, NULL, NULL, NULL);
  1413. return(hr);
  1414. }
  1415. HRESULT
  1416. csiBuildRequest(
  1417. OPTIONAL IN HINF hInf,
  1418. OPTIONAL IN CERT_CONTEXT const *pccPrevious,
  1419. IN BYTE const *pbSubjectEncoded,
  1420. IN DWORD cbSubjectEncoded,
  1421. IN char const *pszAlgId,
  1422. IN BOOL fNewKey,
  1423. IN DWORD iCert,
  1424. IN DWORD iKey,
  1425. IN HCRYPTPROV hProv,
  1426. IN HWND hwnd,
  1427. IN HINSTANCE hInstance,
  1428. IN BOOL fUnattended,
  1429. OUT BYTE **ppbEncode,
  1430. OUT DWORD *pcbEncode)
  1431. {
  1432. HRESULT hr;
  1433. CERT_PUBLIC_KEY_INFO *pInfo = NULL;
  1434. DWORD cbInfo = 0;
  1435. BYTE *pbEncode = NULL;
  1436. DWORD cbEncode;
  1437. CERT_REQUEST_INFO CertRequestInfo;
  1438. CRYPT_ALGORITHM_IDENTIFIER AlgId;
  1439. HCERTTYPE hCertType = NULL;
  1440. CRYPT_ATTR_BLOB ExtBlob;
  1441. CRYPT_ATTR_BLOB ExtBlobNT4;
  1442. CRYPT_ATTR_BLOB VersionBlob;
  1443. CRYPT_ATTRIBUTE aAttrib[3];
  1444. CERT_EXTENSIONS *pExtensions = NULL;
  1445. CERT_EXTENSIONS Extensions;
  1446. CERT_EXTENSIONS ExtensionsNT4;
  1447. CERT_EXTENSION aext[8];
  1448. CERT_EXTENSION aextNT4[4];
  1449. CERT_EXTENSION *paext = NULL;
  1450. char const *apszOIDNT4[] = {
  1451. szOID_BASIC_CONSTRAINTS2,
  1452. szOID_SUBJECT_KEY_IDENTIFIER,
  1453. szOID_KEY_USAGE,
  1454. szOID_ENHANCED_KEY_USAGE,
  1455. };
  1456. DWORD i;
  1457. DWORD NameId = MAKECANAMEID(iCert, iKey);
  1458. DWORD cExtCommon = 0;
  1459. CERT_EXTENSION *pext;
  1460. DWORD cAttribute = 0;
  1461. CRYPT_ATTR_BLOB *paAttribute = NULL;
  1462. WCHAR *pwszTemplateName;
  1463. WCHAR *pwszTemplateNameInf = NULL;
  1464. DWORD cExtInf = 0;
  1465. CERT_EXTENSION *rgExtInf = NULL;
  1466. DWORD cExtMerged;
  1467. CERT_EXTENSION *rgExtMerged = NULL;
  1468. BOOL fVersionAttr = TRUE;
  1469. ExtBlob.pbData = NULL;
  1470. ExtBlobNT4.pbData = NULL;
  1471. VersionBlob.pbData = NULL;
  1472. if (!CryptExportPublicKeyInfo(
  1473. hProv,
  1474. AT_SIGNATURE,
  1475. X509_ASN_ENCODING,
  1476. NULL,
  1477. &cbInfo))
  1478. {
  1479. hr = myHLastError();
  1480. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  1481. }
  1482. pInfo = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbInfo);
  1483. if (NULL == pInfo)
  1484. {
  1485. hr = E_OUTOFMEMORY;
  1486. _JumpError(hr, error, "LocalAlloc");
  1487. }
  1488. if (!CryptExportPublicKeyInfo(
  1489. hProv,
  1490. AT_SIGNATURE,
  1491. X509_ASN_ENCODING,
  1492. pInfo,
  1493. &cbInfo))
  1494. {
  1495. hr = myHLastError();
  1496. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  1497. }
  1498. CertRequestInfo.dwVersion = CERT_REQUEST_V1;
  1499. CertRequestInfo.Subject.pbData = const_cast<BYTE *>(pbSubjectEncoded);
  1500. CertRequestInfo.Subject.cbData = cbSubjectEncoded;
  1501. CertRequestInfo.SubjectPublicKeyInfo = *pInfo;
  1502. // Build the CA Version extension
  1503. if (!myEncodeObject(
  1504. X509_ASN_ENCODING,
  1505. X509_INTEGER,
  1506. &NameId,
  1507. 0,
  1508. CERTLIB_USE_LOCALALLOC,
  1509. &aext[cExtCommon].Value.pbData,
  1510. &aext[cExtCommon].Value.cbData))
  1511. {
  1512. hr = myHLastError();
  1513. _JumpError(hr, error, "myEncodeObject");
  1514. }
  1515. aext[cExtCommon].pszObjId = szOID_CERTSRV_CA_VERSION;
  1516. aext[cExtCommon].fCritical = FALSE;
  1517. cExtCommon++;
  1518. // Build the previous CA cert hash extension
  1519. if (0 != iCert && NULL != pccPrevious)
  1520. {
  1521. hr = GetCertHashExtension(
  1522. pccPrevious,
  1523. &aext[cExtCommon].Value.pbData,
  1524. &aext[cExtCommon].Value.cbData);
  1525. _JumpIfError(hr, error, "GetCertHashExtension");
  1526. aext[cExtCommon].pszObjId = szOID_CERTSRV_PREVIOUS_CERT_HASH;
  1527. aext[cExtCommon].fCritical = FALSE;
  1528. cExtCommon++;
  1529. }
  1530. // Subject Key Identifier extension:
  1531. // If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
  1532. pext = NULL;
  1533. if (0 != iCert && NULL != pccPrevious && !fNewKey)
  1534. {
  1535. pext = CertFindExtension(
  1536. szOID_SUBJECT_KEY_IDENTIFIER,
  1537. pccPrevious->pCertInfo->cExtension,
  1538. pccPrevious->pCertInfo->rgExtension);
  1539. }
  1540. if (NULL != pext)
  1541. {
  1542. aext[cExtCommon].Value.cbData = pext->Value.cbData;
  1543. aext[cExtCommon].Value.pbData = (BYTE *) LocalAlloc(
  1544. LMEM_FIXED,
  1545. pext->Value.cbData);
  1546. if (NULL == aext[cExtCommon].Value.pbData)
  1547. {
  1548. hr = E_OUTOFMEMORY;
  1549. _JumpError(hr, error, "LocalAlloc");
  1550. }
  1551. CopyMemory(
  1552. aext[cExtCommon].Value.pbData,
  1553. pext->Value.pbData,
  1554. pext->Value.cbData);
  1555. }
  1556. else
  1557. {
  1558. hr = myCreateSubjectKeyIdentifierExtension(
  1559. &CertRequestInfo.SubjectPublicKeyInfo,
  1560. &aext[cExtCommon].Value.pbData,
  1561. &aext[cExtCommon].Value.cbData);
  1562. _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
  1563. }
  1564. aext[cExtCommon].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
  1565. aext[cExtCommon].fCritical = FALSE;
  1566. cExtCommon++;
  1567. hr = myInfGetPolicyStatementExtension(hInf, &aext[cExtCommon]);
  1568. csiLogInfError(hInf, hr);
  1569. _PrintIfError(hr, "myInfGetPolicyStatementExtension");
  1570. if (S_OK == hr)
  1571. {
  1572. aext[cExtCommon].pszObjId = szOID_CERT_POLICIES;
  1573. cExtCommon++;
  1574. }
  1575. hr = myInfGetCrossCertDistributionPointsExtension(hInf, &aext[cExtCommon]);
  1576. csiLogInfError(hInf, hr);
  1577. _PrintIfError(hr, "myInfGetCrossCertDistributionPointsExtension");
  1578. if (S_OK == hr)
  1579. {
  1580. aext[cExtCommon].pszObjId = szOID_CROSS_CERT_DIST_POINTS;
  1581. cExtCommon++;
  1582. }
  1583. hr = myInfGetRequestAttributes(
  1584. hInf,
  1585. &cAttribute,
  1586. &paAttribute,
  1587. &pwszTemplateNameInf);
  1588. csiLogInfError(hInf, hr);
  1589. _PrintIfError(hr, "myInfGetRequestAttributes");
  1590. hr = myInfGetExtensions(hInf, &cExtInf, &rgExtInf);
  1591. csiLogInfError(hInf, hr);
  1592. _PrintIfError(hr, "myInfGetExtensions");
  1593. pwszTemplateName = pwszTemplateNameInf;
  1594. if (NULL == pwszTemplateName)
  1595. {
  1596. pwszTemplateName = wszCERTTYPE_SUBORDINATE_CA;
  1597. }
  1598. // Build the attribute containing the appropriate cert type info
  1599. hr = CAFindCertTypeByName(
  1600. pwszTemplateName,
  1601. NULL,
  1602. CT_FIND_LOCAL_SYSTEM |
  1603. CT_ENUM_MACHINE_TYPES |
  1604. CT_ENUM_USER_TYPES,
  1605. &hCertType);
  1606. if (S_OK == hr)
  1607. {
  1608. hr = CAGetCertTypeExtensions(hCertType, &pExtensions);
  1609. _JumpIfError(hr, error, "CAGetCertTypeExtensions");
  1610. paext = (CERT_EXTENSION *) LocalAlloc(
  1611. LMEM_FIXED,
  1612. (pExtensions->cExtension + cExtCommon) * sizeof(paext[0]));
  1613. if (NULL == paext)
  1614. {
  1615. hr = E_OUTOFMEMORY;
  1616. _JumpError(hr, error, "LocalAlloc");
  1617. }
  1618. CopyMemory(&paext[0], &aext[0], cExtCommon * sizeof(paext[0]));
  1619. CopyMemory(
  1620. &paext[cExtCommon],
  1621. pExtensions->rgExtension,
  1622. pExtensions->cExtension * sizeof(paext[0]));
  1623. Extensions.cExtension = cExtCommon + pExtensions->cExtension;
  1624. Extensions.rgExtension = paext;
  1625. }
  1626. else
  1627. {
  1628. DBGERRORPRINTLINE("CAFindCertTypeByName", hr);
  1629. // standard extensions are not available from CAGetCertTypeExtensions;
  1630. // construct them manually.
  1631. // Build the Cert Template extension
  1632. hr = myBuildCertTypeExtension(pwszTemplateName, &aext[cExtCommon]);
  1633. _JumpIfError(hr, error, "myBuildCertTypeExtension");
  1634. cExtCommon++;
  1635. if (!CreateKeyUsageExtension(
  1636. myCASIGN_KEY_USAGE,
  1637. &aext[cExtCommon].Value.pbData,
  1638. &aext[cExtCommon].Value.cbData,
  1639. hInstance,
  1640. fUnattended,
  1641. hwnd))
  1642. {
  1643. hr = myHLastError();
  1644. _JumpError(hr, error, "CreateKeyUsageExtension");
  1645. }
  1646. aext[cExtCommon].pszObjId = szOID_KEY_USAGE;
  1647. aext[cExtCommon].fCritical = FALSE;
  1648. cExtCommon++;
  1649. hr = myInfGetBasicConstraints2CAExtensionOrDefault(
  1650. hInf,
  1651. &aext[cExtCommon]);
  1652. csiLogInfError(hInf, hr);
  1653. _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
  1654. cExtCommon++;
  1655. CSASSERT(ARRAYSIZE(aext) >= cExtCommon);
  1656. Extensions.cExtension = cExtCommon;
  1657. Extensions.rgExtension = aext;
  1658. }
  1659. if (0 != cExtInf)
  1660. {
  1661. pext = CertFindExtension(
  1662. szOID_OS_VERSION,
  1663. cExtInf,
  1664. rgExtInf);
  1665. if (NULL != pext && NULL == pext->Value.pbData)
  1666. {
  1667. fVersionAttr = FALSE;
  1668. }
  1669. hr = myMergeExtensions(
  1670. Extensions.cExtension,
  1671. Extensions.rgExtension,
  1672. cExtInf,
  1673. rgExtInf,
  1674. &cExtMerged,
  1675. &rgExtMerged);
  1676. _JumpIfError(hr, error, "myMergeExtensions");
  1677. Extensions.cExtension = cExtMerged;
  1678. Extensions.rgExtension = rgExtMerged;
  1679. }
  1680. if (0 != Extensions.cExtension)
  1681. {
  1682. if (!myEncodeObject(
  1683. X509_ASN_ENCODING,
  1684. X509_EXTENSIONS,
  1685. &Extensions,
  1686. 0,
  1687. CERTLIB_USE_LOCALALLOC,
  1688. &ExtBlob.pbData,
  1689. &ExtBlob.cbData))
  1690. {
  1691. hr = myHLastError();
  1692. _JumpError(hr, error, "myEncodeObject");
  1693. }
  1694. }
  1695. // To allow an NT4 SP6a cert server to recognize this request as
  1696. // a subordinate CA request, put the basic constraints extension into
  1697. // a request attribute tagged with the old OID (szOID_CERT_EXTENSIONS).
  1698. // Do the same for subject key id (NT4 computed SKI incorrectly),
  1699. // key usage and enhanced key usage.
  1700. ExtensionsNT4.cExtension = 0;
  1701. CSASSERT(CSExpr(ARRAYSIZE(apszOIDNT4) == ARRAYSIZE(aextNT4)));
  1702. for (i = 0; i < ARRAYSIZE(apszOIDNT4); i++)
  1703. {
  1704. pext = CertFindExtension(
  1705. apszOIDNT4[i],
  1706. Extensions.cExtension,
  1707. Extensions.rgExtension);
  1708. if (NULL != pext)
  1709. {
  1710. aextNT4[ExtensionsNT4.cExtension] = *pext;
  1711. ExtensionsNT4.cExtension++;
  1712. }
  1713. }
  1714. if (0 != ExtensionsNT4.cExtension)
  1715. {
  1716. ExtensionsNT4.rgExtension = aextNT4;
  1717. if (!myEncodeObject(
  1718. X509_ASN_ENCODING,
  1719. X509_EXTENSIONS,
  1720. &ExtensionsNT4,
  1721. 0,
  1722. CERTLIB_USE_LOCALALLOC,
  1723. &ExtBlobNT4.pbData,
  1724. &ExtBlobNT4.cbData))
  1725. {
  1726. hr = myHLastError();
  1727. _JumpError(hr, error, "myEncodeObject");
  1728. }
  1729. }
  1730. // get the OS Version
  1731. hr = myBuildOSVersionAttribute(&VersionBlob.pbData, &VersionBlob.cbData);
  1732. _JumpIfError(hr, error, "myBuildOSVersionAttribute");
  1733. CertRequestInfo.cAttribute = 0;
  1734. CertRequestInfo.rgAttribute = aAttrib;
  1735. if (NULL != ExtBlob.pbData)
  1736. {
  1737. aAttrib[CertRequestInfo.cAttribute].pszObjId = szOID_RSA_certExtensions;
  1738. aAttrib[CertRequestInfo.cAttribute].cValue = 1;
  1739. aAttrib[CertRequestInfo.cAttribute].rgValue = &ExtBlob;
  1740. CertRequestInfo.cAttribute++;
  1741. }
  1742. if (fVersionAttr)
  1743. {
  1744. aAttrib[CertRequestInfo.cAttribute].pszObjId = szOID_OS_VERSION;
  1745. aAttrib[CertRequestInfo.cAttribute].cValue = 1;
  1746. aAttrib[CertRequestInfo.cAttribute].rgValue = &VersionBlob;
  1747. CertRequestInfo.cAttribute++;
  1748. }
  1749. if (NULL != ExtBlobNT4.pbData)
  1750. {
  1751. aAttrib[CertRequestInfo.cAttribute].pszObjId = szOID_CERT_EXTENSIONS;
  1752. aAttrib[CertRequestInfo.cAttribute].cValue = 1;
  1753. aAttrib[CertRequestInfo.cAttribute].rgValue = &ExtBlobNT4;
  1754. CertRequestInfo.cAttribute++;
  1755. }
  1756. CSASSERT(CertRequestInfo.cAttribute <= ARRAYSIZE(aAttrib));
  1757. AlgId.pszObjId = const_cast<char *>(pszAlgId);
  1758. AlgId.Parameters.cbData = 0;
  1759. AlgId.Parameters.pbData = NULL;
  1760. if (!CryptSignAndEncodeCertificate(
  1761. hProv,
  1762. AT_SIGNATURE,
  1763. X509_ASN_ENCODING,
  1764. X509_CERT_REQUEST_TO_BE_SIGNED,
  1765. &CertRequestInfo,
  1766. &AlgId,
  1767. NULL,
  1768. NULL,
  1769. &cbEncode))
  1770. {
  1771. hr = myHLastError();
  1772. _JumpError(hr, error, "CryptSignAndEncodeCertificate");
  1773. }
  1774. pbEncode = (BYTE *) LocalAlloc(LMEM_FIXED, cbEncode);
  1775. if (NULL == pbEncode)
  1776. {
  1777. hr = E_OUTOFMEMORY;
  1778. _JumpError(hr, error, "LocalAlloc");
  1779. }
  1780. if (!CryptSignAndEncodeCertificate(
  1781. hProv,
  1782. AT_SIGNATURE,
  1783. X509_ASN_ENCODING,
  1784. X509_CERT_REQUEST_TO_BE_SIGNED,
  1785. &CertRequestInfo,
  1786. &AlgId,
  1787. NULL,
  1788. pbEncode,
  1789. &cbEncode))
  1790. {
  1791. hr = myHLastError();
  1792. _JumpError(hr, error, "CryptSignAndEncodeCertificate");
  1793. }
  1794. // return value
  1795. *ppbEncode = pbEncode;
  1796. *pcbEncode = cbEncode;
  1797. hr = S_OK;
  1798. error:
  1799. if (NULL != pwszTemplateNameInf)
  1800. {
  1801. LocalFree(pwszTemplateNameInf);
  1802. }
  1803. if (NULL != paAttribute)
  1804. {
  1805. myInfFreeRequestAttributes(cAttribute, paAttribute);
  1806. }
  1807. for (i = 0; i < cExtCommon; i++)
  1808. {
  1809. if (NULL != aext[i].Value.pbData)
  1810. {
  1811. LocalFree(aext[i].Value.pbData);
  1812. }
  1813. }
  1814. if (NULL != paext)
  1815. {
  1816. LocalFree(paext);
  1817. }
  1818. if (NULL != rgExtMerged)
  1819. {
  1820. LocalFree(rgExtMerged);
  1821. }
  1822. myInfFreeExtensions(cExtInf, rgExtInf);
  1823. if (NULL != ExtBlob.pbData)
  1824. {
  1825. LocalFree(ExtBlob.pbData);
  1826. }
  1827. if (NULL != ExtBlobNT4.pbData)
  1828. {
  1829. LocalFree(ExtBlobNT4.pbData);
  1830. }
  1831. if (NULL != VersionBlob.pbData)
  1832. {
  1833. LocalFree(VersionBlob.pbData);
  1834. }
  1835. if (NULL != pInfo)
  1836. {
  1837. LocalFree(pInfo);
  1838. }
  1839. if (NULL != hCertType)
  1840. {
  1841. if (NULL != pExtensions && &Extensions != pExtensions)
  1842. {
  1843. CAFreeCertTypeExtensions(hCertType, pExtensions);
  1844. }
  1845. CACloseCertType(hCertType);
  1846. }
  1847. CSILOG(hr, IDS_ILOG_BUILDREQUEST, NULL, NULL, &NameId);
  1848. return(hr);
  1849. }
  1850. //+-------------------------------------------------------------------------
  1851. // CertServerRequestCACertificateAndComplete -- implements the following:
  1852. // MMC snapin's RenewCert and InstallCert verbs
  1853. // certutil -InstallCert & -RenewCert
  1854. //+-------------------------------------------------------------------------
  1855. HRESULT
  1856. CertServerRequestCACertificateAndComplete(
  1857. IN HINSTANCE hInstance,
  1858. IN HWND hwnd,
  1859. IN DWORD Flags,
  1860. IN WCHAR const *pwszCAName,
  1861. OPTIONAL IN WCHAR const *pwszParentMachine,
  1862. OPTIONAL IN WCHAR const *pwszParentCA,
  1863. OPTIONAL IN WCHAR const *pwszCAChainFile,
  1864. OPTIONAL OUT WCHAR **ppwszRequestFile)
  1865. {
  1866. HRESULT hr;
  1867. DWORD dwSetupStatus;
  1868. WCHAR const *pwszFinalParentMachine = pwszParentMachine;
  1869. WCHAR const *pwszFinalParentCA = pwszParentCA;
  1870. WCHAR *pwszRequestFile = NULL;
  1871. WCHAR *pwszCertFile = NULL;
  1872. BYTE *pbRequest = NULL;
  1873. DWORD cbRequest;
  1874. BSTR strChain = NULL;
  1875. BYTE *pbChain = NULL;
  1876. DWORD cbChain;
  1877. WCHAR *pwszKeyContainer = NULL;
  1878. WCHAR *pwszServerName = NULL;
  1879. CERTHIERINFO CertHierInfo;
  1880. ENUM_CATYPES CAType;
  1881. BOOL fUseDS;
  1882. DWORD dwRevocationFlags;
  1883. DWORD iCertNew;
  1884. DWORD iKey;
  1885. CERT_CONTEXT const *pccCertOld = NULL;
  1886. HCRYPTPROV hProv = NULL;
  1887. CRYPT_KEY_PROV_INFO KeyProvInfo;
  1888. ALG_ID idAlg;
  1889. BOOL fMachineKeyset;
  1890. BOOL fKeyGenFailed;
  1891. CHAR *pszAlgId = NULL;
  1892. BOOL fUnattended = (CSRF_UNATTENDED & Flags)? TRUE : FALSE;
  1893. BOOL fRenew = (CSRF_RENEWCACERT & Flags)? TRUE : FALSE;
  1894. BOOL fNewKey = (CSRF_NEWKEYS & Flags)? TRUE : FALSE;
  1895. UINT idMsg;
  1896. WCHAR *pwszProvName = NULL;
  1897. DWORD dwProvType;
  1898. HINF hInf = INVALID_HANDLE_VALUE;
  1899. DWORD ErrorLine;
  1900. WCHAR *pwszzUnreferencedInfSections = NULL;
  1901. BOOL fEnableKeyCounting = FALSE;
  1902. idMsg = IDS_ILOG_INSTALLCERT;
  1903. if (fRenew)
  1904. {
  1905. idMsg = fNewKey? IDS_ILOG_RENEWNEWKEY : IDS_ILOG_RENEWOLDKEY;
  1906. }
  1907. ZeroMemory(&CertHierInfo, sizeof(CertHierInfo));
  1908. ZeroMemory(&KeyProvInfo, sizeof(KeyProvInfo));
  1909. if (NULL != ppwszRequestFile)
  1910. {
  1911. *ppwszRequestFile = NULL;
  1912. }
  1913. if (NULL == pwszCAName)
  1914. {
  1915. hr = E_POINTER;
  1916. _JumpError(hr, error, "NULL CA Name");
  1917. }
  1918. hr = mySanitizeName(pwszCAName, &CertHierInfo.pwszSanitizedCAName);
  1919. _JumpIfError(hr, error, "mySanitizeName");
  1920. hr = GetSetupStatus(CertHierInfo.pwszSanitizedCAName, &dwSetupStatus);
  1921. _JumpIfError(hr, error, "GetSetupStatus");
  1922. hr = myGetCertRegDWValue(
  1923. CertHierInfo.pwszSanitizedCAName,
  1924. NULL,
  1925. NULL,
  1926. wszREGCATYPE,
  1927. (DWORD *) &CAType);
  1928. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE);
  1929. // use DS or not
  1930. hr = myGetCertRegDWValue(
  1931. CertHierInfo.pwszSanitizedCAName,
  1932. NULL,
  1933. NULL,
  1934. wszREGCAUSEDS,
  1935. (DWORD *) &fUseDS);
  1936. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS);
  1937. hr = myGetCertRegStrValue(
  1938. CertHierInfo.pwszSanitizedCAName,
  1939. NULL,
  1940. NULL,
  1941. wszREGCASERVERNAME,
  1942. &pwszServerName);
  1943. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
  1944. hr = myGetCertRegDWValue(
  1945. CertHierInfo.pwszSanitizedCAName,
  1946. wszREGKEYPOLICYMODULES,
  1947. wszCLASS_CERTPOLICY,
  1948. wszREGREVOCATIONTYPE,
  1949. &dwRevocationFlags);
  1950. if (S_OK != hr)
  1951. {
  1952. dwRevocationFlags = fUseDS? REVEXT_DEFAULT_DS : REVEXT_DEFAULT_NODS;
  1953. }
  1954. // Current Hash count is the same as the next iCert
  1955. hr = myGetCARegHashCount(
  1956. CertHierInfo.pwszSanitizedCAName,
  1957. CSRH_CASIGCERT,
  1958. &iCertNew);
  1959. _JumpIfError(hr, error, "myGetCARegHashCount");
  1960. cbChain = 0;
  1961. cbRequest = 0;
  1962. if (fRenew)
  1963. {
  1964. // We're renewing the CA cert, so the initial setup should be complete.
  1965. hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  1966. if (0 == iCertNew || (SETUP_SUSPEND_FLAG & dwSetupStatus))
  1967. {
  1968. _JumpError(hr, error, "not fully installed");
  1969. }
  1970. if (SETUP_REQUEST_FLAG & dwSetupStatus)
  1971. {
  1972. if (0 == (CSRF_OVERWRITE & Flags))
  1973. {
  1974. _JumpError(hr, error, "Renewal already in progress");
  1975. }
  1976. _PrintError(hr, "Ignoring renewal already in progress");
  1977. }
  1978. hr = myGetCertSrvCSP(
  1979. FALSE, // fEncryptionCSP
  1980. CertHierInfo.pwszSanitizedCAName,
  1981. &dwProvType,
  1982. &pwszProvName,
  1983. &idAlg,
  1984. &fMachineKeyset,
  1985. NULL); // pdwKeySize
  1986. _JumpIfError(hr, error, "myGetCertSrvCSP");
  1987. hr = LoadCurrentCACertAndKeyInfo(
  1988. CertHierInfo.pwszSanitizedCAName,
  1989. fNewKey,
  1990. fUnattended,
  1991. fMachineKeyset,
  1992. iCertNew,
  1993. &iKey,
  1994. &pwszKeyContainer,
  1995. &pccCertOld);
  1996. _JumpIfError(hr, error, "LoadCurrentCACertAndKeyInfo");
  1997. CSASSERT(MAXDWORD != iKey);
  1998. hr = csiFillKeyProvInfo(
  1999. pwszKeyContainer,
  2000. pwszProvName,
  2001. dwProvType,
  2002. fMachineKeyset,
  2003. &KeyProvInfo);
  2004. _JumpIfError(hr, error, "csiFillKeyProvInfo");
  2005. hr = myInfOpenFile(NULL, &hInf, &ErrorLine);
  2006. _PrintIfError2(
  2007. hr,
  2008. "myInfOpenFile",
  2009. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  2010. if (fNewKey)
  2011. {
  2012. CWaitCursor cwait;
  2013. DWORD cbitKey;
  2014. hr = myInfGetKeyLength(hInf, &cbitKey);
  2015. if (S_OK != hr)
  2016. {
  2017. cbitKey = CertGetPublicKeyLength(
  2018. X509_ASN_ENCODING,
  2019. &pccCertOld->pCertInfo->SubjectPublicKeyInfo);
  2020. if (0 == cbitKey || 512 == cbitKey)
  2021. {
  2022. if (0 == cbitKey)
  2023. {
  2024. hr = myHLastError();
  2025. _PrintError(hr, "CertGetPublicKeyLength");
  2026. }
  2027. cbitKey = 1024;
  2028. }
  2029. }
  2030. hr = myInfGetEnableKeyCounting(hInf, &fEnableKeyCounting);
  2031. if (S_OK != hr)
  2032. {
  2033. fEnableKeyCounting = FALSE;
  2034. }
  2035. hr = csiGenerateCAKeys(
  2036. KeyProvInfo.pwszContainerName,
  2037. KeyProvInfo.pwszProvName,
  2038. KeyProvInfo.dwProvType,
  2039. fMachineKeyset,
  2040. cbitKey, // dwKeyLength,
  2041. hInstance,
  2042. fUnattended,
  2043. fEnableKeyCounting,
  2044. hwnd,
  2045. &fKeyGenFailed);
  2046. _JumpIfError(hr, error, "csiGenerateCAKeys");
  2047. }
  2048. // get CSP handle
  2049. if (!myCertSrvCryptAcquireContext(
  2050. &hProv,
  2051. KeyProvInfo.pwszContainerName,
  2052. KeyProvInfo.pwszProvName,
  2053. KeyProvInfo.dwProvType,
  2054. fUnattended? CRYPT_SILENT : 0,
  2055. fMachineKeyset))
  2056. {
  2057. hr = myHLastError();
  2058. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  2059. }
  2060. if (hProv == NULL)
  2061. {
  2062. hr = E_HANDLE;
  2063. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  2064. }
  2065. if (IsRootCA(CAType))
  2066. {
  2067. hr = CloneRootCert(
  2068. hInf,
  2069. pccCertOld,
  2070. hProv,
  2071. CertHierInfo.pwszSanitizedCAName,
  2072. iCertNew,
  2073. iKey,
  2074. fUseDS,
  2075. fNewKey,
  2076. dwRevocationFlags,
  2077. hInstance,
  2078. fUnattended,
  2079. hwnd,
  2080. &pbChain,
  2081. &cbChain);
  2082. _JumpIfError(hr, error, "CloneRootCert");
  2083. }
  2084. else
  2085. {
  2086. // get request file name
  2087. hr = csiGetCARequestFileName(
  2088. hInstance,
  2089. hwnd,
  2090. CertHierInfo.pwszSanitizedCAName,
  2091. iCertNew,
  2092. iKey,
  2093. &pwszRequestFile);
  2094. _JumpIfError(hr, error, "csiGetCARequestFileName");
  2095. hr = myGetSigningOID(
  2096. NULL, // hProv
  2097. KeyProvInfo.pwszProvName,
  2098. KeyProvInfo.dwProvType,
  2099. idAlg,
  2100. &pszAlgId);
  2101. _JumpIfError(hr, error, "myGetSigningOID");
  2102. hr = csiBuildRequest(
  2103. hInf,
  2104. pccCertOld,
  2105. pccCertOld->pCertInfo->Subject.pbData,
  2106. pccCertOld->pCertInfo->Subject.cbData,
  2107. pszAlgId,
  2108. fNewKey,
  2109. iCertNew,
  2110. iKey,
  2111. hProv,
  2112. hwnd,
  2113. hInstance,
  2114. fUnattended,
  2115. &pbRequest,
  2116. &cbRequest);
  2117. _JumpIfError(hr, error, "csiBuildRequest");
  2118. hr = EncodeToFileW(
  2119. pwszRequestFile,
  2120. pbRequest,
  2121. cbRequest,
  2122. DECF_FORCEOVERWRITE | CRYPT_STRING_BASE64REQUESTHEADER);
  2123. _JumpIfErrorStr(hr, error, "EncodeToFileW", pwszRequestFile);
  2124. hr = mySetCertRegKeyIndexAndContainer(
  2125. CertHierInfo.pwszSanitizedCAName,
  2126. iKey,
  2127. pwszKeyContainer);
  2128. _JumpIfError(hr, error, "mySetCertRegKeyIndexAndContainer");
  2129. hr = SetSetupStatus(
  2130. CertHierInfo.pwszSanitizedCAName,
  2131. SETUP_REQUEST_FLAG,
  2132. TRUE);
  2133. _JumpIfError(hr, error, "SetSetupStatus");
  2134. if (NULL != ppwszRequestFile)
  2135. {
  2136. *ppwszRequestFile = pwszRequestFile;
  2137. pwszRequestFile = NULL;
  2138. CSASSERT(S_OK == hr);
  2139. }
  2140. }
  2141. if (INVALID_HANDLE_VALUE != hInf)
  2142. {
  2143. hr = myInfGetUnreferencedSectionNames(
  2144. &pwszzUnreferencedInfSections);
  2145. _PrintIfError(hr, "myInfGetUnreferencedSectionNames");
  2146. if (NULL != pwszzUnreferencedInfSections)
  2147. {
  2148. WCHAR *pwsz;
  2149. pwsz = pwszzUnreferencedInfSections;
  2150. while (L'\0' != *pwsz)
  2151. {
  2152. pwsz += wcslen(pwsz);
  2153. *pwsz++ = L',';
  2154. }
  2155. if (pwsz > pwszzUnreferencedInfSections && *--pwsz == L',')
  2156. {
  2157. *pwsz = L'\0';
  2158. }
  2159. CSILOG(
  2160. S_OK,
  2161. IDS_ILOG_UNREFERENCEDINFSECTIONS,
  2162. pwszzUnreferencedInfSections,
  2163. NULL,
  2164. NULL);
  2165. }
  2166. static WCHAR const * const s_apwszKeys[] =
  2167. {
  2168. wszINFKEY_UTF8,
  2169. wszINFKEY_RENEWALKEYLENGTH,
  2170. wszINFKEY_RENEWALVALIDITYPERIODSTRING,
  2171. wszINFKEY_RENEWALVALIDITYPERIODCOUNT,
  2172. NULL
  2173. };
  2174. hr = myInfGetKeyList(
  2175. hInf,
  2176. wszINFSECTION_CERTSERVER,
  2177. NULL, // pwszKey
  2178. s_apwszKeys,
  2179. NULL, // pfCritical
  2180. NULL); // ppwszzTemplateList
  2181. csiLogInfError(hInf, hr);
  2182. _PrintIfErrorStr(hr, "myInfGetKeyList", wszINFSECTION_CERTSERVER);
  2183. }
  2184. }
  2185. else
  2186. {
  2187. // We're not renewing the CA cert, so this had better be an incomplete
  2188. // renewal or initial setup; we're waiting for the new cert or chain.
  2189. if (IsRootCA(CAType) || 0 == (SETUP_REQUEST_FLAG & dwSetupStatus))
  2190. {
  2191. hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  2192. _JumpIfError(hr, error, "no outstanding request");
  2193. }
  2194. hr = myGetCertRegKeyIndexAndContainer(
  2195. CertHierInfo.pwszSanitizedCAName,
  2196. &iKey,
  2197. &pwszKeyContainer);
  2198. _JumpIfError(hr, error, "myGetCertRegKeyIndexAndContainer");
  2199. if (NULL == pwszCAChainFile)
  2200. {
  2201. // pop up open dlg
  2202. hr = myGetOpenFileName(
  2203. hwnd,
  2204. hInstance,
  2205. IDS_CAHIER_INSTALL_TITLE,
  2206. IDS_CAHIER_CERTFILE_FILTER,
  2207. 0, // no def ext
  2208. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  2209. NULL, // no default file
  2210. &pwszCertFile);
  2211. if (S_OK == hr && NULL != pwszCertFile)
  2212. {
  2213. pwszCAChainFile = pwszCertFile;
  2214. }
  2215. }
  2216. if (NULL != pwszCAChainFile)
  2217. {
  2218. hr = DecodeFileW(pwszCAChainFile, &pbChain, &cbChain, CRYPT_STRING_ANY);
  2219. _JumpIfErrorStr(hr, error, "DecodeFileW", pwszCAChainFile);
  2220. }
  2221. }
  2222. if (!IsRootCA(CAType) && NULL == pbChain)
  2223. {
  2224. // if we haven't created the request, grab it from a file for resubmission
  2225. if (pbRequest == NULL)
  2226. {
  2227. hr = myGetCARegFileNameTemplate(
  2228. wszREGREQUESTFILENAME,
  2229. pwszServerName,
  2230. CertHierInfo.pwszSanitizedCAName,
  2231. iCertNew,
  2232. iKey,
  2233. &pwszRequestFile);
  2234. _JumpIfError(hr, error, "myGetCARegFileNameTemplate");
  2235. hr = DecodeFileW(pwszRequestFile, &pbRequest, &cbRequest, CRYPT_STRING_ANY);
  2236. _JumpIfErrorStr(hr, error, "DecodeFileW", pwszRequestFile);
  2237. }
  2238. if (NULL == pwszParentMachine || NULL == pwszParentCA)
  2239. {
  2240. CertHierInfo.hInstance = hInstance;
  2241. CertHierInfo.fUnattended = fUnattended;
  2242. CertHierInfo.iCertNew = iCertNew;
  2243. CertHierInfo.iKey = iKey;
  2244. // get parent ca info
  2245. hr = myGetCertRegStrValue(
  2246. CertHierInfo.pwszSanitizedCAName,
  2247. NULL,
  2248. NULL,
  2249. wszREGPARENTCAMACHINE,
  2250. &CertHierInfo.pwszParentMachineDefault);
  2251. _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCAMACHINE);
  2252. hr = myGetCertRegStrValue(
  2253. CertHierInfo.pwszSanitizedCAName,
  2254. NULL,
  2255. NULL,
  2256. wszREGPARENTCANAME,
  2257. &CertHierInfo.pwszParentCADefault);
  2258. _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCANAME);
  2259. // invoke parent ca dialog to select
  2260. if (IDOK != (int) DialogBoxParam(
  2261. hInstance,
  2262. MAKEINTRESOURCE(IDD_COMPLETE_DIALOG),
  2263. hwnd,
  2264. CertHierProc,
  2265. (LPARAM) &CertHierInfo))
  2266. {
  2267. // cancel
  2268. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2269. _JumpError(hr, error, "cancel");
  2270. }
  2271. pwszFinalParentMachine = CertHierInfo.pwszParentMachine;
  2272. pwszFinalParentCA = CertHierInfo.pwszParentCA;
  2273. }
  2274. BOOL fRetrievePending =
  2275. !fRenew &&
  2276. (SETUP_REQUEST_FLAG & dwSetupStatus) &&
  2277. (SETUP_ONLINE_FLAG & dwSetupStatus) &&
  2278. NULL != CertHierInfo.pwszParentMachineDefault &&
  2279. NULL != CertHierInfo.pwszParentCADefault &&
  2280. 0 == mylstrcmpiL(
  2281. pwszFinalParentMachine,
  2282. CertHierInfo.pwszParentMachineDefault) &&
  2283. 0 == mylstrcmpiL(
  2284. pwszFinalParentCA,
  2285. CertHierInfo.pwszParentCADefault);
  2286. // submit to parent ca
  2287. hr = csiSubmitCARequest(
  2288. hInstance,
  2289. fUnattended,
  2290. hwnd,
  2291. fRenew,
  2292. iCertNew,
  2293. fRetrievePending,
  2294. CertHierInfo.pwszSanitizedCAName,
  2295. pwszFinalParentMachine,
  2296. pwszFinalParentCA,
  2297. pbRequest,
  2298. cbRequest,
  2299. &strChain);
  2300. _JumpIfError(hr, error, "csiSubmitCARequest");
  2301. cbChain = SysStringByteLen(strChain);
  2302. }
  2303. hr = FinishSuspendedSetupFromPKCS7(
  2304. hInstance,
  2305. fUnattended,
  2306. hwnd,
  2307. CertHierInfo.pwszSanitizedCAName,
  2308. pwszKeyContainer,
  2309. iKey,
  2310. fRenew || 0 != iCertNew,
  2311. NULL != pbChain? pbChain : (BYTE *) strChain,
  2312. cbChain);
  2313. _JumpIfError(hr, error, "FinishSuspendedSetupFromPKCS7");
  2314. MarkSetupComplete(CertHierInfo.pwszSanitizedCAName);
  2315. CSASSERT(S_OK == hr);
  2316. error:
  2317. CSILOG(
  2318. hr,
  2319. idMsg,
  2320. pwszCAName,
  2321. NULL != pwszRequestFile? pwszRequestFile :
  2322. (NULL != ppwszRequestFile && NULL != *ppwszRequestFile)?
  2323. *ppwszRequestFile : pwszCertFile,
  2324. NULL);
  2325. if (INVALID_HANDLE_VALUE != hInf)
  2326. {
  2327. myInfCloseFile(hInf);
  2328. }
  2329. FreeCertHierInfo(&CertHierInfo);
  2330. csiFreeKeyProvInfo(&KeyProvInfo);
  2331. if (NULL != hProv)
  2332. {
  2333. CryptReleaseContext(hProv, 0);
  2334. }
  2335. if (NULL != pwszzUnreferencedInfSections)
  2336. {
  2337. LocalFree(pwszzUnreferencedInfSections);
  2338. }
  2339. if (NULL != pszAlgId)
  2340. {
  2341. LocalFree(pszAlgId);
  2342. }
  2343. if (NULL != pwszKeyContainer)
  2344. {
  2345. LocalFree(pwszKeyContainer);
  2346. }
  2347. if (NULL != pccCertOld)
  2348. {
  2349. CertFreeCertificateContext(pccCertOld);
  2350. }
  2351. if (NULL != pwszRequestFile)
  2352. {
  2353. LocalFree(pwszRequestFile);
  2354. }
  2355. if (NULL != pwszCertFile)
  2356. {
  2357. LocalFree(pwszCertFile);
  2358. }
  2359. if (NULL != pwszServerName)
  2360. {
  2361. LocalFree(pwszServerName);
  2362. }
  2363. if (NULL != pbRequest)
  2364. {
  2365. LocalFree(pbRequest);
  2366. }
  2367. if (NULL != pbChain)
  2368. {
  2369. LocalFree(pbChain);
  2370. }
  2371. if (NULL != pwszProvName)
  2372. {
  2373. LocalFree(pwszProvName);
  2374. }
  2375. if (NULL != strChain)
  2376. {
  2377. SysFreeString(strChain);
  2378. }
  2379. myInfClearError();
  2380. return(hr);
  2381. }