Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2428 lines
60 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};
  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. if (NULL != pCertHierInfo->pwszParentMachineDefault)
  453. {
  454. SetWindowText(
  455. GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  456. pCertHierInfo->pwszParentMachineDefault);
  457. if (NULL != pCertHierInfo->pwszParentCADefault)
  458. {
  459. SetWindowText(
  460. GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  461. pCertHierInfo->pwszParentCADefault);
  462. }
  463. }
  464. // load formatted help string
  465. hr = myLoadRCString(
  466. pCertHierInfo->hInstance,
  467. IDS_REQUEST_HELPTEXT,
  468. &pwszHelpText);
  469. _JumpIfError(hr, error, "myLoadRCString");
  470. // get request file name
  471. hr = csiGetCARequestFileName(
  472. pCertHierInfo->hInstance,
  473. hDlg,
  474. pCertHierInfo->pwszSanitizedCAName,
  475. pCertHierInfo->iCertNew,
  476. pCertHierInfo->iKey,
  477. &pwszRequestFile);
  478. _JumpIfError(hr, error, "csiGetCARequestFileName");
  479. // replace %1
  480. if (!FormatMessage(
  481. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  482. FORMAT_MESSAGE_FROM_STRING |
  483. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  484. pwszHelpText,
  485. 0,
  486. 0,
  487. reinterpret_cast<WCHAR *>(&pwszExpandedHelpText),
  488. 0,
  489. reinterpret_cast<va_list *>
  490. (const_cast<WCHAR **>(&pwszRequestFile))) )
  491. {
  492. hr = myHLastError();
  493. _JumpError(hr, error, "FormatMessage");
  494. }
  495. // set help text
  496. SetWindowText(GetDlgItem(hDlg, IDC_REQUEST_HELPTEXT), pwszExpandedHelpText);
  497. hr = myInitUICASelectionControls(
  498. &g_CertHierCARequestUICASelection,
  499. pCertHierInfo->hInstance,
  500. hDlg,
  501. GetDlgItem(hDlg, IDC_BROWSE_CA),
  502. GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  503. GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  504. csiIsAnyDSCAAvailable(),
  505. &fCAsExist);
  506. _JumpIfError(hr, error, "myInitUICASelectionControls");
  507. error:
  508. if (NULL != pwszHelpText)
  509. {
  510. LocalFree(pwszHelpText);
  511. }
  512. if (NULL != pwszRequestFile)
  513. {
  514. LocalFree(pwszRequestFile);
  515. }
  516. if (NULL != pwszExpandedHelpText)
  517. {
  518. LocalFree(pwszExpandedHelpText);
  519. }
  520. return(hr);
  521. }
  522. HRESULT
  523. HandleOKButton(
  524. HWND hDlg,
  525. CERTHIERINFO *pCertHierInfo,
  526. BOOL *pfLeave)
  527. {
  528. HRESULT hr;
  529. WCHAR *pwszParentMachine = NULL;
  530. WCHAR *pwszParentCA = NULL;
  531. hr = myUICASelectionValidation(&g_CertHierCARequestUICASelection, pfLeave);
  532. _JumpIfError(hr, error, "myUICASelectionValidation");
  533. if (!*pfLeave)
  534. {
  535. goto error;
  536. }
  537. // get parent ca info
  538. hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_COMPUTER_NAME),
  539. &pwszParentMachine);
  540. _JumpIfError(hr, error, "myUIGetWindowText");
  541. hr = myUIGetWindowText(GetDlgItem(hDlg, IDC_PARENT_CA_NAME),
  542. &pwszParentCA);
  543. _JumpIfError(hr, error, "myUIGetWindowText");
  544. pCertHierInfo->pwszParentMachine = pwszParentMachine;
  545. pwszParentMachine = NULL;
  546. pCertHierInfo->pwszParentCA = pwszParentCA;
  547. pwszParentCA = NULL;
  548. hr = S_OK;
  549. error:
  550. if (NULL != pwszParentMachine)
  551. {
  552. LocalFree(pwszParentMachine);
  553. }
  554. if (NULL != pwszParentCA)
  555. {
  556. LocalFree(pwszParentCA);
  557. }
  558. return(hr);
  559. }
  560. INT_PTR CALLBACK
  561. CertHierProc(
  562. HWND hDlg,
  563. UINT iMsg,
  564. WPARAM wParam,
  565. LPARAM lParam)
  566. {
  567. HRESULT hr;
  568. BOOL ret = FALSE;
  569. BOOL fLeave;
  570. static CERTHIERINFO *s_pCertHierInfo = NULL;
  571. static BOOL s_fComputerChange = FALSE;
  572. switch (iMsg)
  573. {
  574. case WM_INITDIALOG:
  575. s_pCertHierInfo = (CERTHIERINFO *) lParam;
  576. hr = InitCertHierControls(hDlg, s_pCertHierInfo);
  577. _JumpIfError(hr, error, "InitCertHierControls");
  578. ret = TRUE;
  579. break;
  580. case WM_COMMAND:
  581. switch (LOWORD(wParam))
  582. {
  583. case IDC_BROWSE_CA:
  584. ret = TRUE;
  585. hr = myUICAHandleCABrowseButton(
  586. &g_CertHierCARequestUICASelection,
  587. csiIsAnyDSCAAvailable(),
  588. IDS_CA_PICKER_TITLE,
  589. IDS_CA_PICKER_PROMPT,
  590. NULL);
  591. _JumpIfError(hr, error, "myUICAHandleCABrowseButton");
  592. break;
  593. case IDC_PARENT_CA_NAME:
  594. hr = myUICAHandleCAListDropdown(
  595. (int)HIWORD(wParam),
  596. &g_CertHierCARequestUICASelection,
  597. &s_fComputerChange);
  598. _PrintIfError(hr, "myUICAHandleCAListDropdown");
  599. break;
  600. case IDC_PARENT_COMPUTER_NAME:
  601. switch ((int)HIWORD(wParam))
  602. {
  603. case EN_CHANGE: // edit change
  604. s_fComputerChange = TRUE;
  605. break;
  606. }
  607. break;
  608. case IDOK:
  609. ret = TRUE;
  610. hr = HandleOKButton(hDlg, s_pCertHierInfo, &fLeave);
  611. _PrintIfError(hr, "HandleOKButton");
  612. if (fLeave)
  613. {
  614. // update return status
  615. ret = EndDialog(hDlg, IDOK);
  616. goto error; //done;
  617. }
  618. break;
  619. case IDCANCEL:
  620. ret = EndDialog(hDlg, IDCANCEL);
  621. break;
  622. }
  623. break;
  624. }
  625. error:
  626. return(ret);
  627. }
  628. VOID
  629. MarkSetupComplete(
  630. IN WCHAR const *pwszSanitizedCAName)
  631. {
  632. HRESULT hr;
  633. // Clear pending/denied flags:
  634. hr = SetSetupStatus(
  635. pwszSanitizedCAName,
  636. SETUP_SUSPEND_FLAG |
  637. SETUP_ONLINE_FLAG |
  638. SETUP_REQUEST_FLAG |
  639. SETUP_DENIED_FLAG,
  640. FALSE);
  641. _PrintIfError(hr, "SetSetupStatus");
  642. // Force new CRL generation on startup:
  643. hr = SetSetupStatus(pwszSanitizedCAName, SETUP_FORCECRL_FLAG, TRUE);
  644. _PrintIfError(hr, "SetSetupStatus");
  645. CSILOG(hr, IDS_ILOG_SETUPCOMPLETE, NULL, NULL, NULL);
  646. }
  647. HRESULT
  648. FindKeyIndex(
  649. IN HCERTSTORE hMyStore,
  650. IN WCHAR const *pwszSanitizedCAName,
  651. IN BOOL fUnattended,
  652. IN BOOL fMachineKeyset,
  653. IN DWORD cCert,
  654. CRYPT_KEY_PROV_INFO *pKeyMatch,
  655. OUT DWORD *piKey)
  656. {
  657. HRESULT hr;
  658. DWORD i;
  659. CERT_CONTEXT const *pccCert = NULL;
  660. CRYPT_KEY_PROV_INFO *pKey = NULL;
  661. HCRYPTPROV hProv = NULL;
  662. CERT_PUBLIC_KEY_INFO *pPubKeyMatch = NULL;
  663. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  664. DWORD cb;
  665. DWORD NameId;
  666. *piKey = MAXDWORD;
  667. // get CSP handle
  668. if (!myCertSrvCryptAcquireContext(
  669. &hProv,
  670. pKeyMatch->pwszContainerName,
  671. pKeyMatch->pwszProvName,
  672. pKeyMatch->dwProvType,
  673. fUnattended? CRYPT_SILENT : 0,
  674. fMachineKeyset))
  675. {
  676. hr = myHLastError();
  677. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  678. }
  679. if (hProv == NULL)
  680. {
  681. hr = E_HANDLE;
  682. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  683. }
  684. if (!myCryptExportPublicKeyInfo(
  685. hProv,
  686. AT_SIGNATURE,
  687. CERTLIB_USE_LOCALALLOC,
  688. &pPubKeyMatch,
  689. &cb))
  690. {
  691. hr = myHLastError();
  692. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  693. }
  694. CryptReleaseContext(hProv, 0);
  695. hProv = NULL;
  696. for (i = 0; ; i++)
  697. {
  698. if (i >= cCert)
  699. {
  700. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  701. _JumpError(hr, error, "old key not found");
  702. }
  703. hr = myFindCACertByHashIndex(
  704. hMyStore,
  705. pwszSanitizedCAName,
  706. CSRH_CASIGCERT,
  707. i,
  708. &NameId,
  709. &pccCert);
  710. if (S_FALSE == hr)
  711. {
  712. continue;
  713. }
  714. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  715. // get the key provider info
  716. if (!myCertGetCertificateContextProperty(
  717. pccCert,
  718. CERT_KEY_PROV_INFO_PROP_ID,
  719. CERTLIB_USE_LOCALALLOC,
  720. (VOID **) &pKey,
  721. &cb))
  722. {
  723. hr = myHLastError();
  724. _JumpError(hr, error, "CertGetCertificateContextProperty");
  725. }
  726. // get CSP handle
  727. if (!myCertSrvCryptAcquireContext(
  728. &hProv,
  729. pKey->pwszContainerName,
  730. pKey->pwszProvName,
  731. pKey->dwProvType,
  732. fUnattended? CRYPT_SILENT : 0,
  733. fMachineKeyset))
  734. {
  735. hr = myHLastError();
  736. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  737. }
  738. if (hProv == NULL)
  739. {
  740. hr = E_HANDLE;
  741. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  742. }
  743. if (!myCryptExportPublicKeyInfo(
  744. hProv,
  745. AT_SIGNATURE,
  746. CERTLIB_USE_LOCALALLOC,
  747. &pPubKey,
  748. &cb))
  749. {
  750. hr = myHLastError();
  751. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  752. }
  753. // by design, CertComparePublicKeyInfo doesn't set last error!
  754. if (CertComparePublicKeyInfo(X509_ASN_ENCODING, pPubKey, pPubKeyMatch))
  755. {
  756. hr = myGetNameId(pccCert, &NameId);
  757. if (S_OK != hr)
  758. {
  759. *piKey = i;
  760. }
  761. else
  762. {
  763. *piKey = CANAMEIDTOIKEY(NameId);
  764. }
  765. break;
  766. }
  767. LocalFree(pPubKey);
  768. pPubKey = NULL;
  769. CryptReleaseContext(hProv, 0);
  770. hProv = NULL;
  771. LocalFree(pKey);
  772. pKey = NULL;
  773. CertFreeCertificateContext(pccCert);
  774. pccCert = NULL;
  775. }
  776. hr = S_OK;
  777. error:
  778. if (NULL != pPubKeyMatch)
  779. {
  780. LocalFree(pPubKeyMatch);
  781. }
  782. if (NULL != pPubKey)
  783. {
  784. LocalFree(pPubKey);
  785. }
  786. if (NULL != hProv)
  787. {
  788. CryptReleaseContext(hProv, 0);
  789. }
  790. if (NULL != pKey)
  791. {
  792. LocalFree(pKey);
  793. }
  794. if (NULL != pccCert)
  795. {
  796. CertFreeCertificateContext(pccCert);
  797. }
  798. CSILOG(hr, IDS_ILOG_KEYINDEX, NULL, NULL, piKey);
  799. return(hr);
  800. }
  801. HRESULT
  802. LoadCurrentCACertAndKeyInfo(
  803. IN WCHAR const *pwszSanitizedCAName,
  804. IN BOOL fNewKey,
  805. IN BOOL fUnattended,
  806. IN BOOL fMachineKeyset,
  807. IN DWORD iCertNew,
  808. OUT DWORD *piKey,
  809. OUT WCHAR **ppwszKeyContainer,
  810. OUT CERT_CONTEXT const **ppccCertOld)
  811. {
  812. HRESULT hr;
  813. HCERTSTORE hMyStore = NULL;
  814. DWORD cbKey;
  815. CRYPT_KEY_PROV_INFO *pKey = NULL;
  816. WCHAR *pwszKeyContainer = NULL;
  817. DWORD NameId;
  818. *ppwszKeyContainer = NULL;
  819. *ppccCertOld = NULL;
  820. *piKey = MAXDWORD;
  821. // open MY store
  822. hMyStore = CertOpenStore(
  823. CERT_STORE_PROV_SYSTEM_W,
  824. X509_ASN_ENCODING,
  825. NULL, // hProv
  826. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  827. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  828. wszMY_CERTSTORE);
  829. if (NULL == hMyStore)
  830. {
  831. hr = myHLastError();
  832. _JumpError(hr, error, "CertOpenStore");
  833. }
  834. hr = myFindCACertByHashIndex(
  835. hMyStore,
  836. pwszSanitizedCAName,
  837. CSRH_CASIGCERT,
  838. iCertNew - 1,
  839. &NameId,
  840. ppccCertOld);
  841. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  842. if (fNewKey)
  843. {
  844. *piKey = iCertNew; // New key: iKey set to iCert
  845. hr = myAllocIndexedName(
  846. pwszSanitizedCAName,
  847. *piKey,
  848. &pwszKeyContainer);
  849. _JumpIfError(hr, error, "myAllocIndexedName");
  850. }
  851. else
  852. {
  853. // get the key provider info
  854. if (!myCertGetCertificateContextProperty(
  855. *ppccCertOld,
  856. CERT_KEY_PROV_INFO_PROP_ID,
  857. CERTLIB_USE_LOCALALLOC,
  858. (VOID **) &pKey,
  859. &cbKey))
  860. {
  861. hr = myHLastError();
  862. _JumpError(hr, error, "CertGetCertificateContextProperty");
  863. }
  864. hr = myDupString(pKey->pwszContainerName, &pwszKeyContainer);
  865. _JumpIfError(hr, error, "myDupString");
  866. // Reuse key: iKey set to match oldest iCert using this key:
  867. hr = FindKeyIndex(
  868. hMyStore,
  869. pwszSanitizedCAName,
  870. fUnattended,
  871. fMachineKeyset,
  872. iCertNew,
  873. pKey,
  874. piKey);
  875. _JumpIfError(hr, error, "FindKeyIndex");
  876. CSASSERT(MAXDWORD != *piKey);
  877. }
  878. *ppwszKeyContainer = pwszKeyContainer;
  879. pwszKeyContainer = NULL;
  880. CSASSERT(S_OK == hr);
  881. error:
  882. if (NULL != pwszKeyContainer)
  883. {
  884. LocalFree(pwszKeyContainer);
  885. }
  886. if (NULL != pKey)
  887. {
  888. LocalFree(pKey);
  889. }
  890. if (NULL != hMyStore)
  891. {
  892. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  893. }
  894. CSILOG(hr, IDS_ILOG_LOADOLDCERT, *ppwszKeyContainer, NULL, piKey);
  895. return(hr);
  896. }
  897. HRESULT
  898. ReplaceExtension(
  899. IN CERT_EXTENSION const *pExtension,
  900. IN OUT DWORD *pcExtension,
  901. IN OUT CERT_EXTENSION *rgExtension)
  902. {
  903. DWORD i;
  904. CSASSERT(NULL != pExtension->pszObjId);
  905. for (i = 0; ; i++)
  906. {
  907. if (i == *pcExtension)
  908. {
  909. if (NULL != pExtension->Value.pbData)
  910. {
  911. (*pcExtension)++; // not found: append to array
  912. }
  913. break;
  914. }
  915. CSASSERT(i < *pcExtension);
  916. if (0 == strcmp(pExtension->pszObjId, rgExtension[i].pszObjId))
  917. {
  918. if (NULL == pExtension->Value.pbData)
  919. {
  920. // remove extension: copy last extension on top of this one
  921. // and decrement extension count
  922. (*pcExtension)--;
  923. pExtension = &rgExtension[*pcExtension];
  924. }
  925. break;
  926. }
  927. }
  928. rgExtension[i] = *pExtension; // append or overwrite extension
  929. return(S_OK);
  930. }
  931. HRESULT
  932. GetMinimumCertValidityPeriod(
  933. IN WCHAR const *pwszSanitizedCAName,
  934. IN DWORD cCert,
  935. OUT LONGLONG *pTimeDelta)
  936. {
  937. HRESULT hr;
  938. HCERTSTORE hMyStore = NULL;
  939. DWORD NameId;
  940. CERT_CONTEXT const *pcc = NULL;
  941. BOOL fFirst = TRUE;
  942. DWORD i;
  943. // open MY store
  944. hMyStore = CertOpenStore(
  945. CERT_STORE_PROV_SYSTEM_W,
  946. X509_ASN_ENCODING,
  947. NULL, // hProv
  948. CERT_SYSTEM_STORE_LOCAL_MACHINE |
  949. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  950. wszMY_CERTSTORE);
  951. if (NULL == hMyStore)
  952. {
  953. hr = myHLastError();
  954. _JumpError(hr, error, "CertOpenStore");
  955. }
  956. for (i = 0; i < cCert; i++)
  957. {
  958. LONGLONG TimeDelta;
  959. hr = myFindCACertByHashIndex(
  960. hMyStore,
  961. pwszSanitizedCAName,
  962. CSRH_CASIGCERT,
  963. i,
  964. &NameId,
  965. &pcc);
  966. if (S_OK != hr)
  967. {
  968. _PrintError(hr, "myFindCACertByHashIndex");
  969. continue;
  970. }
  971. TimeDelta = mySubtractFileTimes(
  972. &pcc->pCertInfo->NotAfter,
  973. &pcc->pCertInfo->NotBefore);
  974. DBGPRINT((
  975. DBG_SS_CERTLIBI,
  976. "iCert=%u TimeDelta=%x:%x\n",
  977. i,
  978. (DWORD) (TimeDelta >> 32),
  979. (DWORD) TimeDelta));
  980. if (fFirst || *pTimeDelta > TimeDelta)
  981. {
  982. *pTimeDelta = TimeDelta;
  983. DBGPRINT((
  984. DBG_SS_CERTLIBI,
  985. "iCert=%u *pTimeDelta=%x:%x\n",
  986. i,
  987. (DWORD) (*pTimeDelta >> 32),
  988. (DWORD) *pTimeDelta));
  989. fFirst = FALSE;
  990. }
  991. CertFreeCertificateContext(pcc);
  992. pcc = NULL;
  993. }
  994. if (fFirst)
  995. {
  996. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  997. _JumpError(hr, error, "no old Certs");
  998. }
  999. hr = S_OK;
  1000. error:
  1001. if (NULL != pcc)
  1002. {
  1003. CertFreeCertificateContext(pcc);
  1004. }
  1005. if (NULL != hMyStore)
  1006. {
  1007. CertCloseStore(hMyStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1008. }
  1009. return(hr);
  1010. }
  1011. HRESULT
  1012. GetCertHashExtension(
  1013. IN CERT_CONTEXT const *pCert,
  1014. OUT BYTE **ppbData,
  1015. OUT DWORD *pcbData)
  1016. {
  1017. HRESULT hr;
  1018. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  1019. CRYPT_DATA_BLOB Blob;
  1020. DWORD cbHash;
  1021. cbHash = sizeof(abHash);
  1022. if (!CertGetCertificateContextProperty(
  1023. pCert,
  1024. CERT_HASH_PROP_ID,
  1025. abHash,
  1026. &cbHash))
  1027. {
  1028. hr = myHLastError();
  1029. _JumpError(hr, error, "CertGetCertificateContextProperty");
  1030. }
  1031. Blob.cbData = cbHash;
  1032. Blob.pbData = abHash;
  1033. if (!myEncodeObject(
  1034. X509_ASN_ENCODING,
  1035. X509_OCTET_STRING,
  1036. &Blob,
  1037. 0,
  1038. CERTLIB_USE_LOCALALLOC,
  1039. ppbData,
  1040. pcbData))
  1041. {
  1042. hr = myHLastError();
  1043. _JumpError(hr, error, "myEncodeObject");
  1044. }
  1045. hr = S_OK;
  1046. error:
  1047. return(hr);
  1048. }
  1049. HRESULT
  1050. CloneRootCert(
  1051. IN HINF hInf,
  1052. IN CERT_CONTEXT const *pccCertOld,
  1053. IN CRYPT_KEY_PROV_INFO const *pKeyProvInfo,
  1054. IN HCRYPTPROV hProv,
  1055. IN WCHAR const *pwszSanitizedCAName,
  1056. IN DWORD iCert,
  1057. IN DWORD iKey,
  1058. IN BOOL fUseDS,
  1059. IN BOOL fNewKey,
  1060. IN DWORD dwRevocationFlags,
  1061. IN HINSTANCE hInstance,
  1062. IN BOOL fUnattended,
  1063. IN HWND hwnd,
  1064. OUT BYTE **ppbCert,
  1065. OUT DWORD *pcbCert)
  1066. {
  1067. HRESULT hr;
  1068. CERT_INFO Cert;
  1069. GUID guidSerialNumber;
  1070. LONGLONG TimeDelta;
  1071. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  1072. DWORD cbPubKey;
  1073. DWORD NameId;
  1074. CERT_EXTENSION *paext = NULL;
  1075. FILETIME ftNotAfterMin;
  1076. DWORD dwValidityPeriodCount;
  1077. ENUM_PERIOD enumValidityPeriod;
  1078. CERT_EXTENSION *pext;
  1079. #define CEXT_REPLACED 9
  1080. CERT_EXTENSION extBasicConstraints =
  1081. { NULL, FALSE, 0, NULL};
  1082. CERT_EXTENSION extSKI =
  1083. { szOID_SUBJECT_KEY_IDENTIFIER, FALSE, 0, NULL };
  1084. CERT_EXTENSION extCDP =
  1085. { szOID_CRL_DIST_POINTS, FALSE, 0, NULL };
  1086. CERT_EXTENSION extVersion =
  1087. { szOID_CERTSRV_CA_VERSION, FALSE, 0, NULL };
  1088. CERT_EXTENSION extPreviousHash =
  1089. { szOID_CERTSRV_PREVIOUS_CERT_HASH, FALSE, 0, NULL };
  1090. CERT_EXTENSION extPolicy =
  1091. { szOID_CERT_POLICIES, FALSE, 0, NULL };
  1092. CERT_EXTENSION extCross =
  1093. { szOID_CROSS_CERT_DIST_POINTS, FALSE, 0, NULL };
  1094. CERT_EXTENSION extAIA =
  1095. { szOID_AUTHORITY_INFO_ACCESS, FALSE, 0, NULL };
  1096. CERT_EXTENSION extEKU =
  1097. { NULL, FALSE, 0, NULL};
  1098. *ppbCert = NULL;
  1099. CopyMemory(&Cert, pccCertOld->pCertInfo, sizeof(Cert));
  1100. Cert.dwVersion = CERT_V3;
  1101. myGenerateGuidSerialNumber(&guidSerialNumber);
  1102. Cert.SerialNumber.pbData = (BYTE *) &guidSerialNumber;
  1103. Cert.SerialNumber.cbData = sizeof(guidSerialNumber);
  1104. if (!myAreBlobsSame(
  1105. Cert.Issuer.pbData,
  1106. Cert.Issuer.cbData,
  1107. Cert.Subject.pbData,
  1108. Cert.Subject.cbData))
  1109. {
  1110. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1111. _JumpError(hr, error, "non-Root Cert");
  1112. }
  1113. if (!myCryptExportPublicKeyInfo(
  1114. hProv,
  1115. AT_SIGNATURE,
  1116. CERTLIB_USE_LOCALALLOC,
  1117. &pPubKey,
  1118. &cbPubKey))
  1119. {
  1120. hr = myHLastError();
  1121. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  1122. }
  1123. Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
  1124. // make new cert expire at least 1 minute after old cert.
  1125. ftNotAfterMin = Cert.NotAfter;
  1126. myMakeExprDateTime(&ftNotAfterMin, 1, ENUM_PERIOD_MINUTES);
  1127. GetSystemTimeAsFileTime(&Cert.NotBefore);
  1128. hr = myInfGetValidityPeriod(
  1129. hInf,
  1130. NULL, // pwszValidityPeriodCount
  1131. NULL, // pwszValidityPeriodString
  1132. &dwValidityPeriodCount,
  1133. &enumValidityPeriod,
  1134. NULL); // pfSwap
  1135. if (S_OK == hr)
  1136. {
  1137. Cert.NotAfter = Cert.NotBefore;
  1138. myMakeExprDateTime(
  1139. &Cert.NotAfter,
  1140. dwValidityPeriodCount,
  1141. enumValidityPeriod);
  1142. TimeDelta = 0;
  1143. }
  1144. else
  1145. {
  1146. hr = GetMinimumCertValidityPeriod(
  1147. pwszSanitizedCAName,
  1148. iCert,
  1149. &TimeDelta);
  1150. _JumpIfError(hr, error, "GetMinimumCertValidityPeriod");
  1151. CSASSERT(0 != TimeDelta);
  1152. }
  1153. myMakeExprDateTime(
  1154. &Cert.NotBefore,
  1155. -CCLOCKSKEWMINUTESDEFAULT,
  1156. ENUM_PERIOD_MINUTES);
  1157. if (0 != TimeDelta)
  1158. {
  1159. Cert.NotAfter = Cert.NotBefore;
  1160. myAddToFileTime(&Cert.NotAfter, TimeDelta);
  1161. }
  1162. // make new cert expire at least 1 minute after old cert.
  1163. if (0 > CompareFileTime(&Cert.NotAfter, &ftNotAfterMin))
  1164. {
  1165. Cert.NotAfter = ftNotAfterMin;
  1166. }
  1167. if (!fNewKey)
  1168. {
  1169. Cert.NotBefore = pccCertOld->pCertInfo->NotBefore;
  1170. }
  1171. paext = (CERT_EXTENSION *) LocalAlloc(
  1172. LMEM_FIXED,
  1173. (Cert.cExtension + CEXT_REPLACED) * sizeof(paext[0]));
  1174. if (NULL == paext)
  1175. {
  1176. hr = E_OUTOFMEMORY;
  1177. _JumpError(hr, error, "LocalAlloc");
  1178. }
  1179. CopyMemory(paext, Cert.rgExtension, Cert.cExtension * sizeof(paext[0]));
  1180. Cert.rgExtension = paext;
  1181. // Basic constraints extension:
  1182. hr = myInfGetBasicConstraints2CAExtensionOrDefault(hInf, &extBasicConstraints);
  1183. _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
  1184. ReplaceExtension(&extBasicConstraints, &Cert.cExtension, Cert.rgExtension);
  1185. // Subject Key Identifier extension:
  1186. // If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
  1187. pext = NULL;
  1188. if (!fNewKey)
  1189. {
  1190. pext = CertFindExtension(
  1191. szOID_SUBJECT_KEY_IDENTIFIER,
  1192. Cert.cExtension,
  1193. Cert.rgExtension);
  1194. }
  1195. if (NULL == pext)
  1196. {
  1197. hr = myCreateSubjectKeyIdentifierExtension(
  1198. pPubKey,
  1199. &extSKI.Value.pbData,
  1200. &extSKI.Value.cbData);
  1201. _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
  1202. ReplaceExtension(&extSKI, &Cert.cExtension, Cert.rgExtension);
  1203. }
  1204. hr = CreateRevocationExtension(
  1205. hInf,
  1206. pwszSanitizedCAName,
  1207. iCert,
  1208. iKey,
  1209. fUseDS,
  1210. dwRevocationFlags,
  1211. &extCDP.fCritical,
  1212. &extCDP.Value.pbData,
  1213. &extCDP.Value.cbData);
  1214. _PrintIfError2(hr, "CreateRevocationExtension", S_FALSE);
  1215. if (S_OK == hr || S_FALSE == hr)
  1216. {
  1217. ReplaceExtension(&extCDP, &Cert.cExtension, Cert.rgExtension);
  1218. }
  1219. // Build the CA Version extension
  1220. NameId = MAKECANAMEID(iCert, iKey);
  1221. if (!myEncodeObject(
  1222. X509_ASN_ENCODING,
  1223. X509_INTEGER,
  1224. &NameId,
  1225. 0,
  1226. CERTLIB_USE_LOCALALLOC,
  1227. &extVersion.Value.pbData,
  1228. &extVersion.Value.cbData))
  1229. {
  1230. hr = myHLastError();
  1231. _JumpError(hr, error, "myEncodeObject");
  1232. }
  1233. ReplaceExtension(&extVersion, &Cert.cExtension, Cert.rgExtension);
  1234. // Build the previous CA cert hash extension
  1235. hr = GetCertHashExtension(
  1236. pccCertOld,
  1237. &extPreviousHash.Value.pbData,
  1238. &extPreviousHash.Value.cbData);
  1239. _JumpIfError(hr, error, "GetCertHashExtension");
  1240. ReplaceExtension(&extPreviousHash, &Cert.cExtension, Cert.rgExtension);
  1241. // Build the Policy Statement extension
  1242. hr = myInfGetPolicyStatementExtension(hInf, &extPolicy);
  1243. if (S_OK == hr || S_FALSE == hr)
  1244. {
  1245. ReplaceExtension(&extPolicy, &Cert.cExtension, Cert.rgExtension);
  1246. }
  1247. // Build the Cross Cert Dist Points extension
  1248. hr = myInfGetCrossCertDistributionPointsExtension(hInf, &extCross);
  1249. if (S_OK == hr || S_FALSE == hr)
  1250. {
  1251. ReplaceExtension(&extCross, &Cert.cExtension, Cert.rgExtension);
  1252. }
  1253. // Build the Authority Information Access extension
  1254. hr = CreateAuthorityInformationAccessExtension(
  1255. hInf,
  1256. pwszSanitizedCAName,
  1257. iCert,
  1258. iKey,
  1259. fUseDS,
  1260. &extAIA.fCritical,
  1261. &extAIA.Value.pbData,
  1262. &extAIA.Value.cbData);
  1263. _PrintIfError3(
  1264. hr,
  1265. "CreateAuthorityInformationAccessExtension",
  1266. E_HANDLE,
  1267. S_FALSE);
  1268. if (S_OK == hr || S_FALSE == hr)
  1269. {
  1270. ReplaceExtension(&extAIA, &Cert.cExtension, Cert.rgExtension);
  1271. }
  1272. // Build the Enhanced Key Usage extension
  1273. hr = myInfGetEnhancedKeyUsageExtension(hInf, &extEKU);
  1274. if (S_OK == hr || S_FALSE == hr)
  1275. {
  1276. ReplaceExtension(&extEKU, &Cert.cExtension, Cert.rgExtension);
  1277. }
  1278. hr = EncodeCertAndSign(
  1279. hProv,
  1280. &Cert,
  1281. Cert.SignatureAlgorithm.pszObjId,
  1282. ppbCert,
  1283. pcbCert,
  1284. hInstance,
  1285. fUnattended,
  1286. hwnd);
  1287. _JumpIfError(hr, error, "EncodeCertAndSign");
  1288. error:
  1289. if (NULL != extBasicConstraints.Value.pbData)
  1290. {
  1291. LocalFree(extBasicConstraints.Value.pbData);
  1292. }
  1293. if (NULL != extSKI.Value.pbData)
  1294. {
  1295. LocalFree(extSKI.Value.pbData);
  1296. }
  1297. if (NULL != extCDP.Value.pbData)
  1298. {
  1299. LocalFree(extCDP.Value.pbData);
  1300. }
  1301. if (NULL != extVersion.Value.pbData)
  1302. {
  1303. LocalFree(extVersion.Value.pbData);
  1304. }
  1305. if (NULL != extPreviousHash.Value.pbData)
  1306. {
  1307. LocalFree(extPreviousHash.Value.pbData);
  1308. }
  1309. if (NULL != extPolicy.Value.pbData)
  1310. {
  1311. LocalFree(extPolicy.Value.pbData);
  1312. }
  1313. if (NULL != extCross.Value.pbData)
  1314. {
  1315. LocalFree(extCross.Value.pbData);
  1316. }
  1317. if (NULL != extAIA.Value.pbData)
  1318. {
  1319. LocalFree(extAIA.Value.pbData);
  1320. }
  1321. if (NULL != extEKU.Value.pbData)
  1322. {
  1323. LocalFree(extEKU.Value.pbData);
  1324. }
  1325. if (NULL != paext)
  1326. {
  1327. LocalFree(paext);
  1328. }
  1329. if (NULL != pPubKey)
  1330. {
  1331. LocalFree(pPubKey);
  1332. }
  1333. CSILOG(hr, IDS_ILOG_CLONECERT, NULL, NULL, NULL);
  1334. return(hr);
  1335. }
  1336. HRESULT
  1337. csiBuildRequest(
  1338. OPTIONAL IN HINF hInf,
  1339. OPTIONAL IN CERT_CONTEXT const *pccPrevious,
  1340. IN BYTE const *pbSubjectEncoded,
  1341. IN DWORD cbSubjectEncoded,
  1342. IN char const *pszAlgId,
  1343. IN BOOL fNewKey,
  1344. IN DWORD iCert,
  1345. IN DWORD iKey,
  1346. IN HCRYPTPROV hProv,
  1347. IN HWND hwnd,
  1348. IN HINSTANCE hInstance,
  1349. IN BOOL fUnattended,
  1350. OUT BYTE **ppbEncode,
  1351. OUT DWORD *pcbEncode)
  1352. {
  1353. HRESULT hr;
  1354. CERT_PUBLIC_KEY_INFO *pInfo = NULL;
  1355. DWORD cbInfo = 0;
  1356. BYTE *pbEncode = NULL;
  1357. DWORD cbEncode;
  1358. CERT_REQUEST_INFO CertRequestInfo;
  1359. CRYPT_ALGORITHM_IDENTIFIER AlgId;
  1360. HCERTTYPE hCertType = NULL;
  1361. CRYPT_ATTR_BLOB ExtBlob;
  1362. CRYPT_ATTR_BLOB VersionBlob;
  1363. CRYPT_ATTRIBUTE aAttrib[2];
  1364. CERT_EXTENSIONS *pExtensions = NULL;
  1365. CERT_EXTENSIONS Extensions;
  1366. CERT_EXTENSION aext[8];
  1367. CERT_EXTENSION *paext = NULL;
  1368. DWORD i;
  1369. DWORD NameId = MAKECANAMEID(iCert, iKey);
  1370. DWORD cExtCommon = 0;
  1371. CERT_EXTENSION *pext;
  1372. DWORD cAttribute = 0;
  1373. CRYPT_ATTR_BLOB *paAttribute = NULL;
  1374. WCHAR *pwszTemplateName;
  1375. WCHAR *pwszTemplateNameInf = NULL;
  1376. ExtBlob.pbData = NULL;
  1377. VersionBlob.pbData = NULL;
  1378. if (!CryptExportPublicKeyInfo(
  1379. hProv,
  1380. AT_SIGNATURE,
  1381. X509_ASN_ENCODING,
  1382. NULL,
  1383. &cbInfo))
  1384. {
  1385. hr = myHLastError();
  1386. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  1387. }
  1388. pInfo = (CERT_PUBLIC_KEY_INFO *) LocalAlloc(LMEM_FIXED, cbInfo);
  1389. if (NULL == pInfo)
  1390. {
  1391. hr = E_OUTOFMEMORY;
  1392. _JumpError(hr, error, "LocalAlloc");
  1393. }
  1394. if (!CryptExportPublicKeyInfo(
  1395. hProv,
  1396. AT_SIGNATURE,
  1397. X509_ASN_ENCODING,
  1398. pInfo,
  1399. &cbInfo))
  1400. {
  1401. hr = myHLastError();
  1402. _JumpError(hr, error, "CryptExportPublicKeyInfo");
  1403. }
  1404. CertRequestInfo.dwVersion = CERT_REQUEST_V1;
  1405. CertRequestInfo.Subject.pbData = const_cast<BYTE *>(pbSubjectEncoded);
  1406. CertRequestInfo.Subject.cbData = cbSubjectEncoded;
  1407. CertRequestInfo.SubjectPublicKeyInfo = *pInfo;
  1408. // Build the CA Version extension
  1409. if (!myEncodeObject(
  1410. X509_ASN_ENCODING,
  1411. X509_INTEGER,
  1412. &NameId,
  1413. 0,
  1414. CERTLIB_USE_LOCALALLOC,
  1415. &aext[cExtCommon].Value.pbData,
  1416. &aext[cExtCommon].Value.cbData))
  1417. {
  1418. hr = myHLastError();
  1419. _JumpError(hr, error, "myEncodeObject");
  1420. }
  1421. aext[cExtCommon].pszObjId = szOID_CERTSRV_CA_VERSION;
  1422. aext[cExtCommon].fCritical = FALSE;
  1423. cExtCommon++;
  1424. // Build the previous CA cert hash extension
  1425. if (0 != iCert && NULL != pccPrevious)
  1426. {
  1427. hr = GetCertHashExtension(
  1428. pccPrevious,
  1429. &aext[cExtCommon].Value.pbData,
  1430. &aext[cExtCommon].Value.cbData);
  1431. _JumpIfError(hr, error, "GetCertHashExtension");
  1432. aext[cExtCommon].pszObjId = szOID_CERTSRV_PREVIOUS_CERT_HASH;
  1433. aext[cExtCommon].fCritical = FALSE;
  1434. cExtCommon++;
  1435. }
  1436. // Subject Key Identifier extension:
  1437. // If we're reusing the old key, reuse the old SKI -- even if it's "wrong".
  1438. pext = NULL;
  1439. if (0 != iCert && NULL != pccPrevious && !fNewKey)
  1440. {
  1441. pext = CertFindExtension(
  1442. szOID_SUBJECT_KEY_IDENTIFIER,
  1443. pccPrevious->pCertInfo->cExtension,
  1444. pccPrevious->pCertInfo->rgExtension);
  1445. }
  1446. if (NULL != pext)
  1447. {
  1448. aext[cExtCommon].Value.cbData = pext->Value.cbData;
  1449. aext[cExtCommon].Value.pbData = (BYTE *) LocalAlloc(
  1450. LMEM_FIXED,
  1451. pext->Value.cbData);
  1452. if (NULL == aext[cExtCommon].Value.pbData)
  1453. {
  1454. hr = E_OUTOFMEMORY;
  1455. _JumpError(hr, error, "LocalAlloc");
  1456. }
  1457. CopyMemory(
  1458. aext[cExtCommon].Value.pbData,
  1459. pext->Value.pbData,
  1460. pext->Value.cbData);
  1461. }
  1462. else
  1463. {
  1464. hr = myCreateSubjectKeyIdentifierExtension(
  1465. &CertRequestInfo.SubjectPublicKeyInfo,
  1466. &aext[cExtCommon].Value.pbData,
  1467. &aext[cExtCommon].Value.cbData);
  1468. _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
  1469. }
  1470. aext[cExtCommon].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
  1471. aext[cExtCommon].fCritical = FALSE;
  1472. cExtCommon++;
  1473. hr = myInfGetPolicyStatementExtension(hInf, &aext[cExtCommon]);
  1474. _PrintIfError(hr, "myInfGetPolicyStatementExtension");
  1475. if (S_OK == hr)
  1476. {
  1477. aext[cExtCommon].pszObjId = szOID_CERT_POLICIES;
  1478. cExtCommon++;
  1479. }
  1480. hr = myInfGetCrossCertDistributionPointsExtension(hInf, &aext[cExtCommon]);
  1481. _PrintIfError(hr, "myInfGetCrossCertDistributionPointsExtension");
  1482. if (S_OK == hr)
  1483. {
  1484. aext[cExtCommon].pszObjId = szOID_CROSS_CERT_DIST_POINTS;
  1485. cExtCommon++;
  1486. }
  1487. hr = myInfGetRequestAttributes(
  1488. hInf,
  1489. &cAttribute,
  1490. &paAttribute,
  1491. &pwszTemplateNameInf);
  1492. _PrintIfError(hr, "myInfGetRequestAttributes");
  1493. pwszTemplateName = pwszTemplateNameInf;
  1494. if (NULL == pwszTemplateName)
  1495. {
  1496. pwszTemplateName = wszCERTTYPE_SUBORDINATE_CA;
  1497. }
  1498. // Build the attribute containing the appropriate cert type info
  1499. hr = CAFindCertTypeByName(
  1500. pwszTemplateName,
  1501. NULL,
  1502. CT_FIND_LOCAL_SYSTEM |
  1503. CT_ENUM_MACHINE_TYPES |
  1504. CT_ENUM_USER_TYPES,
  1505. &hCertType);
  1506. if (S_OK == hr)
  1507. {
  1508. hr = CAGetCertTypeExtensions(hCertType, &pExtensions);
  1509. _JumpIfError(hr, error, "CAGetCertTypeExtensions");
  1510. paext = (CERT_EXTENSION *) LocalAlloc(
  1511. LMEM_FIXED,
  1512. (pExtensions->cExtension + cExtCommon) * sizeof(paext[0]));
  1513. if (NULL == paext)
  1514. {
  1515. hr = E_OUTOFMEMORY;
  1516. _JumpError(hr, error, "LocalAlloc");
  1517. }
  1518. CopyMemory(&paext[0], &aext[0], cExtCommon * sizeof(paext[0]));
  1519. CopyMemory(
  1520. &paext[cExtCommon],
  1521. pExtensions->rgExtension,
  1522. pExtensions->cExtension * sizeof(paext[0]));
  1523. Extensions.cExtension = cExtCommon + pExtensions->cExtension;
  1524. Extensions.rgExtension = paext;
  1525. }
  1526. else
  1527. {
  1528. DBGERRORPRINTLINE("CAFindCertTypeByName", hr);
  1529. // standard extensions are not available from CAGetCertTypeExtensions;
  1530. // construct them manually.
  1531. // Build the Cert Template extension
  1532. hr = myBuildCertTypeExtension(pwszTemplateName, &aext[cExtCommon]);
  1533. _JumpIfError(hr, error, "myBuildCertTypeExtension");
  1534. cExtCommon++;
  1535. if (!CreateKeyUsageExtension(
  1536. myCASIGN_KEY_USAGE,
  1537. &aext[cExtCommon].Value.pbData,
  1538. &aext[cExtCommon].Value.cbData,
  1539. hInstance,
  1540. fUnattended,
  1541. hwnd))
  1542. {
  1543. hr = myHLastError();
  1544. _JumpError(hr, error, "CreateKeyUsageExtension");
  1545. }
  1546. aext[cExtCommon].pszObjId = szOID_KEY_USAGE;
  1547. aext[cExtCommon].fCritical = FALSE;
  1548. cExtCommon++;
  1549. hr = myInfGetBasicConstraints2CAExtensionOrDefault(
  1550. hInf,
  1551. &aext[cExtCommon]);
  1552. _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
  1553. cExtCommon++;
  1554. CSASSERT(ARRAYSIZE(aext) >= cExtCommon);
  1555. Extensions.cExtension = cExtCommon;
  1556. Extensions.rgExtension = aext;
  1557. }
  1558. if (!myEncodeObject(
  1559. X509_ASN_ENCODING,
  1560. X509_EXTENSIONS,
  1561. &Extensions,
  1562. 0,
  1563. CERTLIB_USE_LOCALALLOC,
  1564. &ExtBlob.pbData,
  1565. &ExtBlob.cbData))
  1566. {
  1567. hr = myHLastError();
  1568. _JumpError(hr, error, "myEncodeObject");
  1569. }
  1570. // get the OS Version
  1571. hr = myBuildOSVersionAttribute(&VersionBlob.pbData, &VersionBlob.cbData);
  1572. _JumpIfError(hr, error, "myBuildOSVersionAttribute");
  1573. aAttrib[0].pszObjId = szOID_RSA_certExtensions;
  1574. aAttrib[0].cValue = 1;
  1575. aAttrib[0].rgValue = &ExtBlob;
  1576. aAttrib[1].pszObjId = szOID_OS_VERSION;
  1577. aAttrib[1].cValue = 1;
  1578. aAttrib[1].rgValue = &VersionBlob;
  1579. CertRequestInfo.cAttribute = ARRAYSIZE(aAttrib);
  1580. CertRequestInfo.rgAttribute = aAttrib;
  1581. AlgId.pszObjId = const_cast<char *>(pszAlgId);
  1582. AlgId.Parameters.cbData = 0;
  1583. AlgId.Parameters.pbData = NULL;
  1584. if (!CryptSignAndEncodeCertificate(
  1585. hProv,
  1586. AT_SIGNATURE,
  1587. X509_ASN_ENCODING,
  1588. X509_CERT_REQUEST_TO_BE_SIGNED,
  1589. &CertRequestInfo,
  1590. &AlgId,
  1591. NULL,
  1592. NULL,
  1593. &cbEncode))
  1594. {
  1595. hr = myHLastError();
  1596. _JumpError(hr, error, "CryptSignAndEncodeCertificate");
  1597. }
  1598. pbEncode = (BYTE *) LocalAlloc(LMEM_FIXED, cbEncode);
  1599. if (NULL == pbEncode)
  1600. {
  1601. hr = E_OUTOFMEMORY;
  1602. _JumpError(hr, error, "LocalAlloc");
  1603. }
  1604. if (!CryptSignAndEncodeCertificate(
  1605. hProv,
  1606. AT_SIGNATURE,
  1607. X509_ASN_ENCODING,
  1608. X509_CERT_REQUEST_TO_BE_SIGNED,
  1609. &CertRequestInfo,
  1610. &AlgId,
  1611. NULL,
  1612. pbEncode,
  1613. &cbEncode))
  1614. {
  1615. hr = myHLastError();
  1616. _JumpError(hr, error, "CryptSignAndEncodeCertificate");
  1617. }
  1618. // return value
  1619. *ppbEncode = pbEncode;
  1620. *pcbEncode = cbEncode;
  1621. hr = S_OK;
  1622. error:
  1623. if (NULL != pwszTemplateNameInf)
  1624. {
  1625. LocalFree(pwszTemplateNameInf);
  1626. }
  1627. if (NULL != paAttribute)
  1628. {
  1629. myInfFreeRequestAttributes(cAttribute, paAttribute);
  1630. }
  1631. for (i = 0; i < cExtCommon; i++)
  1632. {
  1633. if (NULL != aext[i].Value.pbData)
  1634. {
  1635. LocalFree(aext[i].Value.pbData);
  1636. }
  1637. }
  1638. if (NULL != paext)
  1639. {
  1640. LocalFree(paext);
  1641. }
  1642. if (NULL != ExtBlob.pbData)
  1643. {
  1644. LocalFree(ExtBlob.pbData);
  1645. }
  1646. if (NULL != VersionBlob.pbData)
  1647. {
  1648. LocalFree(VersionBlob.pbData);
  1649. }
  1650. if (NULL != pInfo)
  1651. {
  1652. LocalFree(pInfo);
  1653. }
  1654. if (NULL != hCertType)
  1655. {
  1656. if (NULL != pExtensions && &Extensions != pExtensions)
  1657. {
  1658. CAFreeCertTypeExtensions(hCertType, pExtensions);
  1659. }
  1660. CACloseCertType(hCertType);
  1661. }
  1662. CSILOG(hr, IDS_ILOG_BUILDREQUEST, NULL, NULL, &NameId);
  1663. return(hr);
  1664. }
  1665. //+-------------------------------------------------------------------------
  1666. // CertServerRequestCACertificateAndComplete -- implements the following:
  1667. // MMC snapin's RenewCert and InstallCert verbs
  1668. // certutil -InstallCert & -RenewCert
  1669. //+-------------------------------------------------------------------------
  1670. HRESULT
  1671. CertServerRequestCACertificateAndComplete(
  1672. IN HINSTANCE hInstance,
  1673. IN HWND hwnd,
  1674. IN DWORD Flags,
  1675. IN WCHAR const *pwszCAName,
  1676. OPTIONAL IN WCHAR const *pwszParentMachine,
  1677. OPTIONAL IN WCHAR const *pwszParentCA,
  1678. OPTIONAL IN WCHAR const *pwszCAChainFile,
  1679. OPTIONAL OUT WCHAR **ppwszRequestFile)
  1680. {
  1681. HRESULT hr;
  1682. DWORD dwSetupStatus;
  1683. WCHAR const *pwszFinalParentMachine = pwszParentMachine;
  1684. WCHAR const *pwszFinalParentCA = pwszParentCA;
  1685. WCHAR *pwszRequestFile = NULL;
  1686. WCHAR *pwszCertFile = NULL;
  1687. BYTE *pbRequest = NULL;
  1688. DWORD cbRequest;
  1689. BSTR strChain = NULL;
  1690. BYTE *pbChain = NULL;
  1691. DWORD cbChain;
  1692. WCHAR *pwszKeyContainer = NULL;
  1693. WCHAR *pwszServerName = NULL;
  1694. WCHAR *pwsz;
  1695. CERTHIERINFO CertHierInfo;
  1696. ENUM_CATYPES CAType;
  1697. BOOL fUseDS;
  1698. DWORD dwRevocationFlags;
  1699. DWORD iCertNew;
  1700. DWORD iKey;
  1701. CERT_CONTEXT const *pccCertOld = NULL;
  1702. HCRYPTPROV hProv = NULL;
  1703. CRYPT_KEY_PROV_INFO KeyProvInfo;
  1704. ALG_ID idAlg;
  1705. BOOL fMachineKeyset;
  1706. BOOL fKeyGenFailed;
  1707. CHAR *pszAlgId = NULL;
  1708. BOOL fUnattended = (CSRF_UNATTENDED & Flags)? TRUE : FALSE;
  1709. BOOL fRenew = (CSRF_RENEWCACERT & Flags)? TRUE : FALSE;
  1710. BOOL fNewKey = (CSRF_NEWKEYS & Flags)? TRUE : FALSE;
  1711. UINT idMsg;
  1712. WCHAR *pwszProvName = NULL;
  1713. DWORD dwProvType;
  1714. HINF hInf = INVALID_HANDLE_VALUE;
  1715. DWORD ErrorLine;
  1716. idMsg = IDS_ILOG_INSTALLCERT;
  1717. if (fRenew)
  1718. {
  1719. idMsg = fNewKey? IDS_ILOG_RENEWNEWKEY : IDS_ILOG_RENEWOLDKEY;
  1720. }
  1721. ZeroMemory(&CertHierInfo, sizeof(CertHierInfo));
  1722. ZeroMemory(&KeyProvInfo, sizeof(KeyProvInfo));
  1723. if (NULL != ppwszRequestFile)
  1724. {
  1725. *ppwszRequestFile = NULL;
  1726. }
  1727. if (NULL == pwszCAName)
  1728. {
  1729. hr = E_POINTER;
  1730. _JumpError(hr, error, "NULL CA Name");
  1731. }
  1732. hr = mySanitizeName(pwszCAName, &CertHierInfo.pwszSanitizedCAName);
  1733. _JumpIfError(hr, error, "mySanitizeName");
  1734. hr = GetSetupStatus(CertHierInfo.pwszSanitizedCAName, &dwSetupStatus);
  1735. _JumpIfError(hr, error, "GetSetupStatus");
  1736. hr = myGetCertRegDWValue(
  1737. CertHierInfo.pwszSanitizedCAName,
  1738. NULL,
  1739. NULL,
  1740. wszREGCATYPE,
  1741. (DWORD *) &CAType);
  1742. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCATYPE);
  1743. // use DS or not
  1744. hr = myGetCertRegDWValue(
  1745. CertHierInfo.pwszSanitizedCAName,
  1746. NULL,
  1747. NULL,
  1748. wszREGCAUSEDS,
  1749. (DWORD *) &fUseDS);
  1750. _JumpIfErrorStr(hr, error, "myGetCertRegDWValue", wszREGCAUSEDS);
  1751. hr = myGetCertRegStrValue(
  1752. CertHierInfo.pwszSanitizedCAName,
  1753. NULL,
  1754. NULL,
  1755. wszREGCASERVERNAME,
  1756. &pwszServerName);
  1757. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", wszREGCASERVERNAME);
  1758. hr = myGetCertRegDWValue(
  1759. CertHierInfo.pwszSanitizedCAName,
  1760. wszREGKEYPOLICYMODULES,
  1761. wszCLASS_CERTPOLICY,
  1762. wszREGREVOCATIONTYPE,
  1763. &dwRevocationFlags);
  1764. if (S_OK != hr)
  1765. {
  1766. dwRevocationFlags = fUseDS? REVEXT_DEFAULT_DS : REVEXT_DEFAULT_NODS;
  1767. }
  1768. // Current Hash count is the same as the next iCert
  1769. hr = myGetCARegHashCount(
  1770. CertHierInfo.pwszSanitizedCAName,
  1771. CSRH_CASIGCERT,
  1772. &iCertNew);
  1773. _JumpIfError(hr, error, "myGetCARegHashCount");
  1774. if (fRenew)
  1775. {
  1776. // We're renewing the CA cert, so the initial setup should be complete.
  1777. hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  1778. if (0 == iCertNew || (SETUP_SUSPEND_FLAG & dwSetupStatus))
  1779. {
  1780. _JumpError(hr, error, "not fully installed");
  1781. }
  1782. if (SETUP_REQUEST_FLAG & dwSetupStatus)
  1783. {
  1784. if (0 == (CSRF_OVERWRITE & Flags))
  1785. {
  1786. _JumpError(hr, error, "Renewal already in progress");
  1787. }
  1788. _PrintError(hr, "Ignoring renewal already in progress");
  1789. }
  1790. hr = myGetCertSrvCSP(
  1791. FALSE, // fEncryptionCSP
  1792. CertHierInfo.pwszSanitizedCAName,
  1793. &dwProvType,
  1794. &pwszProvName,
  1795. &idAlg,
  1796. &fMachineKeyset,
  1797. NULL); // pdwKeySize
  1798. _JumpIfError(hr, error, "myGetCertSrvCSP");
  1799. hr = LoadCurrentCACertAndKeyInfo(
  1800. CertHierInfo.pwszSanitizedCAName,
  1801. fNewKey,
  1802. fUnattended,
  1803. fMachineKeyset,
  1804. iCertNew,
  1805. &iKey,
  1806. &pwszKeyContainer,
  1807. &pccCertOld);
  1808. _JumpIfError(hr, error, "LoadCurrentCACertAndKeyInfo");
  1809. CSASSERT(MAXDWORD != iKey);
  1810. hr = csiFillKeyProvInfo(
  1811. pwszKeyContainer,
  1812. pwszProvName,
  1813. dwProvType,
  1814. fMachineKeyset,
  1815. &KeyProvInfo);
  1816. _JumpIfError(hr, error, "csiFillKeyProvInfo");
  1817. hr = GetCertServerKeyProviderInfo(
  1818. CertHierInfo.pwszSanitizedCAName,
  1819. pwszKeyContainer,
  1820. &idAlg,
  1821. &fMachineKeyset,
  1822. &KeyProvInfo);
  1823. _JumpIfError(hr, error, "GetCertServerKeyProviderInfo");
  1824. hr = myInfOpenFile(NULL, &hInf, &ErrorLine);
  1825. _PrintIfError2(
  1826. hr,
  1827. "myInfOpenFile",
  1828. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1829. if (fNewKey)
  1830. {
  1831. CWaitCursor cwait;
  1832. DWORD cbitKey;
  1833. hr = myInfGetKeyLength(hInf, &cbitKey);
  1834. if (S_OK != hr)
  1835. {
  1836. cbitKey = CertGetPublicKeyLength(
  1837. X509_ASN_ENCODING,
  1838. &pccCertOld->pCertInfo->SubjectPublicKeyInfo);
  1839. if (0 == cbitKey || 512 == cbitKey)
  1840. {
  1841. if (0 == cbitKey)
  1842. {
  1843. hr = myHLastError();
  1844. _PrintError(hr, "CertGetPublicKeyLength");
  1845. }
  1846. cbitKey = 1024;
  1847. }
  1848. }
  1849. hr = csiGenerateCAKeys(
  1850. KeyProvInfo.pwszContainerName,
  1851. KeyProvInfo.pwszProvName,
  1852. KeyProvInfo.dwProvType,
  1853. fMachineKeyset,
  1854. cbitKey, // dwKeyLength,
  1855. hInstance,
  1856. fUnattended,
  1857. hwnd,
  1858. &fKeyGenFailed);
  1859. _JumpIfError(hr, error, "csiGenerateCAKeys");
  1860. }
  1861. // get CSP handle
  1862. if (!myCertSrvCryptAcquireContext(
  1863. &hProv,
  1864. KeyProvInfo.pwszContainerName,
  1865. KeyProvInfo.pwszProvName,
  1866. KeyProvInfo.dwProvType,
  1867. fUnattended? CRYPT_SILENT : 0,
  1868. fMachineKeyset))
  1869. {
  1870. hr = myHLastError();
  1871. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  1872. }
  1873. if (hProv == NULL)
  1874. {
  1875. hr = E_HANDLE;
  1876. _JumpError(hr, error, "myCertSrvCryptAcquireContext");
  1877. }
  1878. if (IsRootCA(CAType))
  1879. {
  1880. hr = CloneRootCert(
  1881. hInf,
  1882. pccCertOld,
  1883. &KeyProvInfo,
  1884. hProv,
  1885. CertHierInfo.pwszSanitizedCAName,
  1886. iCertNew,
  1887. iKey,
  1888. fUseDS,
  1889. fNewKey,
  1890. dwRevocationFlags,
  1891. hInstance,
  1892. fUnattended,
  1893. hwnd,
  1894. &pbChain,
  1895. &cbChain);
  1896. _JumpIfError(hr, error, "CloneRootCert");
  1897. }
  1898. else
  1899. {
  1900. // get request file name
  1901. hr = csiGetCARequestFileName(
  1902. hInstance,
  1903. hwnd,
  1904. CertHierInfo.pwszSanitizedCAName,
  1905. iCertNew,
  1906. iKey,
  1907. &pwszRequestFile);
  1908. _JumpIfError(hr, error, "csiGetCARequestFileName");
  1909. hr = myGetSigningOID(
  1910. NULL, // hProv
  1911. KeyProvInfo.pwszProvName,
  1912. KeyProvInfo.dwProvType,
  1913. idAlg,
  1914. &pszAlgId);
  1915. _JumpIfError(hr, error, "myGetSigningOID");
  1916. hr = csiBuildRequest(
  1917. hInf,
  1918. pccCertOld,
  1919. pccCertOld->pCertInfo->Subject.pbData,
  1920. pccCertOld->pCertInfo->Subject.cbData,
  1921. pszAlgId,
  1922. fNewKey,
  1923. iCertNew,
  1924. iKey,
  1925. hProv,
  1926. hwnd,
  1927. hInstance,
  1928. fUnattended,
  1929. &pbRequest,
  1930. &cbRequest);
  1931. _JumpIfError(hr, error, "csiBuildRequest");
  1932. hr = EncodeToFileW(
  1933. pwszRequestFile,
  1934. pbRequest,
  1935. cbRequest,
  1936. DECF_FORCEOVERWRITE | CRYPT_STRING_BASE64REQUESTHEADER);
  1937. _JumpIfError(hr, error, "EncodeToFileW");
  1938. hr = mySetCertRegKeyIndexAndContainer(
  1939. CertHierInfo.pwszSanitizedCAName,
  1940. iKey,
  1941. pwszKeyContainer);
  1942. _JumpIfError(hr, error, "mySetCertRegKeyIndexAndContainer");
  1943. hr = SetSetupStatus(
  1944. CertHierInfo.pwszSanitizedCAName,
  1945. SETUP_REQUEST_FLAG,
  1946. TRUE);
  1947. _JumpIfError(hr, error, "SetSetupStatus");
  1948. if (NULL != ppwszRequestFile)
  1949. {
  1950. *ppwszRequestFile = pwszRequestFile;
  1951. pwszRequestFile = NULL;
  1952. CSASSERT(S_OK == hr);
  1953. }
  1954. }
  1955. }
  1956. else
  1957. {
  1958. // We're not renewing the CA cert, so this had better be an incomplete
  1959. // renewal or initial setup; we're waiting for the new cert or chain.
  1960. if (IsRootCA(CAType) || 0 == (SETUP_REQUEST_FLAG & dwSetupStatus))
  1961. {
  1962. hr = HRESULT_FROM_WIN32(ERROR_INVALID_STATE);
  1963. _JumpIfError(hr, error, "no outstanding request");
  1964. }
  1965. hr = myGetCertRegKeyIndexAndContainer(
  1966. CertHierInfo.pwszSanitizedCAName,
  1967. &iKey,
  1968. &pwszKeyContainer);
  1969. _JumpIfError(hr, error, "myGetCertRegKeyIndexAndContainer");
  1970. if (NULL == pwszCAChainFile)
  1971. {
  1972. // pop up open dlg
  1973. hr = myGetOpenFileName(
  1974. hwnd,
  1975. hInstance,
  1976. IDS_CAHIER_INSTALL_TITLE,
  1977. IDS_CAHIER_CERTFILE_FILTER,
  1978. 0, // no def ext
  1979. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  1980. NULL, // no default file
  1981. &pwszCertFile);
  1982. if (S_OK == hr && NULL != pwszCertFile)
  1983. {
  1984. pwszCAChainFile = pwszCertFile;
  1985. }
  1986. }
  1987. if (NULL != pwszCAChainFile)
  1988. {
  1989. hr = DecodeFileW(pwszCAChainFile, &pbChain, &cbChain, CRYPT_STRING_ANY);
  1990. _JumpIfErrorStr(hr, error, "DecodeFileW", pwszCAChainFile);
  1991. }
  1992. }
  1993. if (!IsRootCA(CAType) && NULL == pbChain)
  1994. {
  1995. // if we haven't created the request, grab it from a file for resubmission
  1996. if (pbRequest == NULL)
  1997. {
  1998. hr = myGetCARegFileNameTemplate(
  1999. wszREGREQUESTFILENAME,
  2000. pwszServerName,
  2001. CertHierInfo.pwszSanitizedCAName,
  2002. iCertNew,
  2003. iKey,
  2004. &pwszRequestFile);
  2005. _JumpIfError(hr, error, "myGetCARegFileNameTemplate");
  2006. hr = DecodeFileW(pwszRequestFile, &pbRequest, &cbRequest, CRYPT_STRING_ANY);
  2007. _JumpIfErrorStr(hr, error, "DecodeFileW", pwszRequestFile);
  2008. }
  2009. if (NULL == pwszParentMachine || NULL == pwszParentCA)
  2010. {
  2011. CertHierInfo.hInstance = hInstance;
  2012. CertHierInfo.fUnattended = fUnattended;
  2013. CertHierInfo.iCertNew = iCertNew;
  2014. CertHierInfo.iKey = iKey;
  2015. // get parent ca info
  2016. hr = myGetCertRegStrValue(
  2017. CertHierInfo.pwszSanitizedCAName,
  2018. NULL,
  2019. NULL,
  2020. wszREGPARENTCAMACHINE,
  2021. &CertHierInfo.pwszParentMachineDefault);
  2022. _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCAMACHINE);
  2023. hr = myGetCertRegStrValue(
  2024. CertHierInfo.pwszSanitizedCAName,
  2025. NULL,
  2026. NULL,
  2027. wszREGPARENTCANAME,
  2028. &CertHierInfo.pwszParentCADefault);
  2029. _PrintIfErrorStr(hr, "myGetCertRegStrValue", wszREGPARENTCANAME);
  2030. // invoke parent ca dialog to select
  2031. if (IDOK != (int) DialogBoxParam(
  2032. hInstance,
  2033. MAKEINTRESOURCE(IDD_COMPLETE_DIALOG),
  2034. hwnd,
  2035. CertHierProc,
  2036. (LPARAM) &CertHierInfo))
  2037. {
  2038. // cancel
  2039. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  2040. _JumpError(hr, error, "cancel");
  2041. }
  2042. pwszFinalParentMachine = CertHierInfo.pwszParentMachine;
  2043. pwszFinalParentCA = CertHierInfo.pwszParentCA;
  2044. }
  2045. BOOL fRetrievePending =
  2046. (SETUP_REQUEST_FLAG & dwSetupStatus) &&
  2047. (SETUP_ONLINE_FLAG & dwSetupStatus) &&
  2048. NULL != CertHierInfo.pwszParentMachineDefault &&
  2049. NULL != CertHierInfo.pwszParentCADefault &&
  2050. 0 == lstrcmpi(
  2051. pwszFinalParentMachine,
  2052. CertHierInfo.pwszParentMachineDefault) &&
  2053. 0 == lstrcmpi(
  2054. pwszFinalParentCA,
  2055. CertHierInfo.pwszParentCADefault);
  2056. // submit to parent ca
  2057. hr = csiSubmitCARequest(
  2058. hInstance,
  2059. fUnattended,
  2060. hwnd,
  2061. fRenew,
  2062. fRetrievePending,
  2063. CertHierInfo.pwszSanitizedCAName,
  2064. pwszFinalParentMachine,
  2065. pwszFinalParentCA,
  2066. pbRequest,
  2067. cbRequest,
  2068. &strChain);
  2069. _JumpIfError(hr, error, "csiSubmitCARequest");
  2070. cbChain = SysStringByteLen(strChain);
  2071. }
  2072. hr = FinishSuspendedSetupFromPKCS7(
  2073. hInstance,
  2074. fUnattended,
  2075. hwnd,
  2076. CertHierInfo.pwszSanitizedCAName,
  2077. pwszKeyContainer,
  2078. iKey,
  2079. fRenew || 0 != iCertNew,
  2080. NULL != pbChain? pbChain : (BYTE *) strChain,
  2081. cbChain);
  2082. _JumpIfError(hr, error, "FinishSuspendedSetupFromPKCS7");
  2083. MarkSetupComplete(CertHierInfo.pwszSanitizedCAName);
  2084. CSASSERT(S_OK == hr);
  2085. error:
  2086. if (INVALID_HANDLE_VALUE != hInf)
  2087. {
  2088. myInfCloseFile(hInf);
  2089. }
  2090. FreeCertHierInfo(&CertHierInfo);
  2091. csiFreeKeyProvInfo(&KeyProvInfo);
  2092. if (NULL != hProv)
  2093. {
  2094. CryptReleaseContext(hProv, 0);
  2095. }
  2096. if (NULL != pszAlgId)
  2097. {
  2098. LocalFree(pszAlgId);
  2099. }
  2100. if (NULL != pwszKeyContainer)
  2101. {
  2102. LocalFree(pwszKeyContainer);
  2103. }
  2104. if (NULL != pccCertOld)
  2105. {
  2106. CertFreeCertificateContext(pccCertOld);
  2107. }
  2108. if (NULL != pwszRequestFile)
  2109. {
  2110. LocalFree(pwszRequestFile);
  2111. }
  2112. if (NULL != pwszCertFile)
  2113. {
  2114. LocalFree(pwszCertFile);
  2115. }
  2116. if (NULL != pwszServerName)
  2117. {
  2118. LocalFree(pwszServerName);
  2119. }
  2120. if (NULL != pbRequest)
  2121. {
  2122. LocalFree(pbRequest);
  2123. }
  2124. if (NULL != pbChain)
  2125. {
  2126. LocalFree(pbChain);
  2127. }
  2128. if (NULL != pwszProvName)
  2129. {
  2130. LocalFree(pwszProvName);
  2131. }
  2132. if (NULL != strChain)
  2133. {
  2134. SysFreeString(strChain);
  2135. }
  2136. CSILOG(hr, idMsg, pwszCAName, NULL, NULL);
  2137. return(hr);
  2138. }