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.

4534 lines
105 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: initlib.cpp
  8. //
  9. // Contents: Install cert server
  10. //
  11. //--------------------------------------------------------------------------
  12. #include <pch.cpp>
  13. #pragma hdrstop
  14. // C Run-Time Includes
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <memory.h>
  18. #include <time.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <io.h>
  22. #include <winldap.h>
  23. #include <ntldap.h>
  24. // Windows System Includes
  25. #include <winsvc.h>
  26. #include <rpc.h>
  27. #include <tchar.h>
  28. #include <lmaccess.h>
  29. #include <lmwksta.h>
  30. #include <csdisp.h>
  31. #include <wincrypt.h>
  32. #include <objbase.h>
  33. #include <initguid.h>
  34. #include <userenv.h>
  35. #include <cainfop.h>
  36. #define SECURITY_WIN32
  37. #include <security.h>
  38. #include <lmerr.h>
  39. // Application Includes
  40. #include "setupids.h"
  41. #include "certmsg.h"
  42. #include "certca.h"
  43. #include "certhier.h"
  44. #include "tfc.h"
  45. #include "cscsp.h"
  46. #include "csldap.h"
  47. #include "certacl.h"
  48. #define __dwFILE__ __dwFILE_INITLIB_INITLIB_CPP__
  49. WCHAR const g_szSlash[] = L"\\";
  50. DWORD g_dwNameEncodeFlags = CERT_RDN_ENABLE_UTF8_UNICODE_FLAG;
  51. #define MAX_COMPUTER_DNS_NAME 256
  52. using namespace CertSrv;
  53. //+=====================================================================
  54. // DS DNs:
  55. //
  56. // DomainDN Example (no longer used for Cert server DS objects):
  57. // DC=pksdom2,DC=nttest,DC=microsoft,DC=com
  58. //
  59. // ConfigDN Example:
  60. // CN=Configuration,DC=pksdom2,DC=nttest,DC=microsoft,DC=com
  61. //
  62. // Cert server DS objects reside in Public Key Services container under
  63. // the Configuraton container:
  64. // CN=Public Key Services,CN=Services,<ConfigDN>
  65. //
  66. //
  67. // In the Public Key Services container:
  68. //
  69. // Root Trust container:
  70. // Each Root CA creates a Root Trust object in this container to store trusted
  71. // Root CA certificates downloaded by all DS clients.
  72. // Renewed CAs and CAs on multiple machines using the same CA name may use the
  73. // same Root Trust object, because certs are always added -- they are never
  74. // removed.
  75. //
  76. // CN=Certification Authorities
  77. // CN=CA foo
  78. // CN=CA bar
  79. // ...
  80. //
  81. //
  82. // Authority Information Access container:
  83. // Each CA creates an AIA object in this container to store CA certs for chain
  84. // building. Renewed CAs and CAs on multiple machines using the same CA name
  85. // may use the same AIA object, because certs are always added -- they are
  86. // never removed.
  87. //
  88. // CN=AIA
  89. // CN=CA foo
  90. // CN=CA bar
  91. // ...
  92. //
  93. //
  94. // CRL Distribution Point containers:
  95. // Each CA creates a CDP object in this container for each unique CA key to
  96. // store CRLs for revocation checking. Only one base CRL and zero or one
  97. // delta CRL are stored in each CDP object, due to potential size constraints,
  98. // and because the attribute is single valued. When a CA is renewed and a new
  99. // CA key is generated during the renewal, a new CDP object is created with
  100. // the CA's key index (in parentheses) appended to the CN. A nested container
  101. // is created for each machine with the CN set to the short machine name
  102. // (first component of the machine's full DNS name).
  103. //
  104. // CN=CDP
  105. // CN=<CA foo's MachineName>
  106. // CN=CA foo
  107. // CN=CA foo(1)
  108. // CN=CA foo(3)
  109. // CN=<CA bar's MachineName>
  110. // CN=CA bar
  111. // CN=CA bar(1)
  112. //
  113. //
  114. // Enrollment Services container:
  115. // Each CA creates an Enrollment Services object in this container. A flags
  116. // attribute indicates whether the CA supports autoenrollment (an Enterprise
  117. // CA) or not (Standalone CA). The Enrollment Services object publishes the
  118. // existence of the CA to all DS clients. Enrollment Services objects are
  119. // created and managed by the certca.h CA APIs.
  120. //
  121. // CN=Enrollment Services
  122. // CN=CA foo
  123. // CN=CA bar
  124. // ...
  125. //
  126. // Enterprise Trust object:
  127. // A single Enterprise Trust object contains certificates for all
  128. // autoenrollment-enabled CAs (root and subordinate Entrprise CAs).
  129. //
  130. // CN=NTAuthCertificates
  131. //
  132. //======================================================================
  133. WCHAR const s_wszRootCAs[] =
  134. L","
  135. L"CN=Certification Authorities,"
  136. L"CN=Public Key Services,"
  137. L"CN=Services,";
  138. WCHAR const s_wszEnterpriseCAs[] =
  139. L"CN=NTAuthCertificates,"
  140. L"CN=Public Key Services,"
  141. L"CN=Services,";
  142. //+-------------------------------------------------------------------------
  143. // Write an encoded DER blob to a file
  144. //--------------------------------------------------------------------------
  145. BOOL
  146. csiWriteDERToFile(
  147. IN WCHAR const *pwszFileName,
  148. IN BYTE const *pbDER,
  149. IN DWORD cbDER,
  150. IN HINSTANCE hInstance,
  151. IN BOOL fUnattended,
  152. IN HWND hwnd)
  153. {
  154. BOOL fResult = FALSE;
  155. HRESULT hr;
  156. HANDLE hLocalFile;
  157. DWORD dwBytesWritten;
  158. do
  159. {
  160. // Write the Encoded Blob to the file
  161. hLocalFile = CreateFile(
  162. pwszFileName,
  163. GENERIC_WRITE,
  164. 0,
  165. NULL,
  166. CREATE_ALWAYS,
  167. 0,
  168. 0);
  169. if (INVALID_HANDLE_VALUE == hLocalFile)
  170. {
  171. hr = myHLastError();
  172. CertErrorMessageBox(
  173. hInstance,
  174. fUnattended,
  175. hwnd,
  176. IDS_ERR_CREATEFILE,
  177. hr,
  178. pwszFileName);
  179. break;
  180. }
  181. if (!WriteFile(hLocalFile, pbDER, cbDER, &dwBytesWritten, NULL))
  182. {
  183. hr = myHLastError();
  184. CertErrorMessageBox(
  185. hInstance,
  186. fUnattended,
  187. hwnd,
  188. IDS_ERR_WRITEFILE,
  189. hr,
  190. pwszFileName);
  191. break;
  192. }
  193. fResult = TRUE;
  194. } while (FALSE);
  195. if (INVALID_HANDLE_VALUE != hLocalFile)
  196. {
  197. CloseHandle(hLocalFile);
  198. }
  199. if (!fResult)
  200. {
  201. SetLastError(hr);
  202. }
  203. return(fResult);
  204. }
  205. BOOL
  206. CreateKeyUsageExtension(
  207. BYTE bIntendedKeyUsage,
  208. OUT BYTE **ppbEncoded,
  209. IN OUT DWORD *pcbEncoded,
  210. HINSTANCE hInstance,
  211. BOOL fUnattended,
  212. HWND hwnd)
  213. {
  214. BOOL fResult = FALSE;
  215. HRESULT hr;
  216. BYTE *pbEncoded = NULL;
  217. DWORD cbEncoded;
  218. CRYPT_BIT_BLOB KeyUsage;
  219. KeyUsage.pbData = &bIntendedKeyUsage;
  220. KeyUsage.cbData = 1;
  221. KeyUsage.cUnusedBits = 0;
  222. if (!myEncodeKeyUsage(
  223. X509_ASN_ENCODING,
  224. &KeyUsage,
  225. CERTLIB_USE_LOCALALLOC,
  226. &pbEncoded,
  227. &cbEncoded))
  228. {
  229. hr = myHLastError();
  230. CertErrorMessageBox(
  231. hInstance,
  232. fUnattended,
  233. hwnd,
  234. IDS_ERR_ENCODEKEYATTR,
  235. hr,
  236. NULL);
  237. goto error;
  238. }
  239. fResult = TRUE;
  240. error:
  241. if (!fResult)
  242. {
  243. SetLastError(hr);
  244. }
  245. *ppbEncoded = pbEncoded;
  246. *pcbEncoded = cbEncoded;
  247. return(fResult);
  248. }
  249. #ifdef USE_NETSCAPE_TYPE_EXTENSION
  250. BOOL
  251. CreateNetscapeTypeExtension(
  252. OUT BYTE **ppbEncoded,
  253. OUT DWORD *pcbEncoded)
  254. {
  255. BOOL fResult = FALSE;
  256. CRYPT_BIT_BLOB NetscapeType;
  257. BYTE temp = NETSCAPE_SSL_CA_CERT_TYPE | NETSCAPE_SMIME_CA_CERT_TYPE;
  258. NetscapeType.pbData = &temp;
  259. NetscapeType.cbData = 1;
  260. NetscapeType.cUnusedBits = 0;
  261. if (!myEncodeObject(
  262. X509_ASN_ENCODING,
  263. X509_BITS,
  264. &NetscapeType,
  265. 0,
  266. CERTLIB_USE_LOCALALLOC,
  267. ppbEncoded,
  268. pcbEncoded))
  269. {
  270. goto exit;
  271. }
  272. fResult = TRUE;
  273. exit:
  274. return(fResult);
  275. }
  276. #endif
  277. HRESULT
  278. GetRegCRLDistributionPoints(
  279. IN WCHAR const *pwszSanitizedName,
  280. IN BOOL fUseDS,
  281. OUT WCHAR **ppwszz)
  282. {
  283. HRESULT hr;
  284. WCHAR *pwszz = NULL;
  285. WCHAR *pwsz;
  286. WCHAR *pwszzCopy;
  287. DWORD cwc;
  288. DWORD Flags;
  289. WCHAR *pwszT;
  290. *ppwszz = NULL;
  291. hr = myGetCertRegMultiStrValue(
  292. pwszSanitizedName,
  293. NULL,
  294. NULL,
  295. wszREGCRLPUBLICATIONURLS,
  296. &pwszz);
  297. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  298. {
  299. hr = S_OK;
  300. goto error;
  301. }
  302. _JumpIfErrorStr(
  303. hr,
  304. error,
  305. "myGetCertRegMultiStrValue",
  306. wszREGCRLPUBLICATIONURLS);
  307. cwc = 0;
  308. for (pwsz = pwszz; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  309. {
  310. Flags = _wtoi(pwsz);
  311. if (CSURL_ADDTOCERTCDP & Flags)
  312. {
  313. pwszT = pwsz;
  314. while (iswdigit(*pwszT))
  315. {
  316. pwszT++;
  317. }
  318. if (pwszT > pwsz && L':' == *pwszT)
  319. {
  320. pwszT++;
  321. cwc += wcslen(pwszT) + 1;
  322. }
  323. }
  324. }
  325. if (0 == cwc)
  326. {
  327. hr = S_OK;
  328. goto error;
  329. }
  330. pwszzCopy = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  331. if (NULL == pwszzCopy)
  332. {
  333. hr = E_OUTOFMEMORY;
  334. _JumpError(hr, error, "LocalAlloc");
  335. }
  336. *ppwszz = pwszzCopy;
  337. for (pwsz = pwszz; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  338. {
  339. Flags = _wtoi(pwsz);
  340. if (CSURL_ADDTOCERTCDP & Flags)
  341. {
  342. pwszT = pwsz;
  343. while (iswdigit(*pwszT))
  344. {
  345. pwszT++;
  346. }
  347. if (pwszT > pwsz && L':' == *pwszT)
  348. {
  349. pwszT++;
  350. wcscpy(pwszzCopy, pwszT);
  351. pwszzCopy += wcslen(pwszT) + 1;
  352. }
  353. }
  354. }
  355. *pwszzCopy = L'\0';
  356. CSASSERT(SAFE_SUBTRACT_POINTERS(pwszzCopy, *ppwszz) == cwc);
  357. error:
  358. if (NULL != pwszz)
  359. {
  360. LocalFree(pwszz);
  361. }
  362. return(hr);
  363. }
  364. HRESULT
  365. FormatTemplateURLs(
  366. IN WCHAR const *pwszSanitizedName,
  367. IN DWORD iCert,
  368. IN DWORD iCRL,
  369. IN BOOL fUseDS,
  370. IN WCHAR const *pwszzIn,
  371. OUT DWORD *pcpwsz,
  372. OUT WCHAR ***ppapwszOut)
  373. {
  374. HRESULT hr;
  375. DWORD i;
  376. WCHAR const **papwszTemplate = NULL;
  377. WCHAR const *pwsz;
  378. WCHAR **papwszOut = NULL;
  379. DWORD cpwsz = 0;
  380. WCHAR *pwszServerName = NULL;
  381. LDAP *pld = NULL;
  382. BSTR strConfigDN = NULL;
  383. BSTR strDomainDN = NULL;
  384. *pcpwsz = 0;
  385. *ppapwszOut = NULL;
  386. cpwsz = 0;
  387. if (NULL != pwszzIn)
  388. {
  389. for (pwsz = pwszzIn; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  390. {
  391. cpwsz++;
  392. }
  393. }
  394. if (0 == cpwsz)
  395. {
  396. hr = S_FALSE;
  397. goto error;
  398. }
  399. papwszTemplate = (WCHAR const **) LocalAlloc(
  400. LMEM_FIXED,
  401. cpwsz * sizeof(papwszTemplate[0]));
  402. if (NULL == papwszTemplate)
  403. {
  404. hr = E_OUTOFMEMORY;
  405. _JumpError(hr, error, "LocalAlloc");
  406. }
  407. i = 0;
  408. for (pwsz = pwszzIn; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  409. {
  410. papwszTemplate[i++] = pwsz;
  411. }
  412. CSASSERT(i == cpwsz);
  413. papwszOut = (WCHAR **) LocalAlloc(
  414. LMEM_FIXED | LMEM_ZEROINIT,
  415. cpwsz * sizeof(papwszOut[0]));
  416. if (NULL == papwszOut)
  417. {
  418. hr = E_OUTOFMEMORY;
  419. _JumpError(hr, error, "LocalAlloc");
  420. }
  421. hr = myGetMachineDnsName(&pwszServerName);
  422. _JumpIfError(hr, error, "myGetMachineDnsName");
  423. if (fUseDS)
  424. {
  425. // bind to ds
  426. hr = myRobustLdapBind(&pld, FALSE);
  427. _JumpIfError(hr, error, "myRobustLdapBind");
  428. hr = myGetAuthoritativeDomainDn(pld, &strDomainDN, &strConfigDN);
  429. if (S_OK != hr)
  430. {
  431. hr = HRESULT_FROM_WIN32(hr);
  432. _JumpError(hr, error, "myGetAuthoritativeDomainDn");
  433. }
  434. }
  435. else
  436. {
  437. strDomainDN = SysAllocString(L"");
  438. strConfigDN = SysAllocString(L"");
  439. if (NULL == strDomainDN || NULL == strConfigDN)
  440. {
  441. hr = E_OUTOFMEMORY;
  442. _JumpError(hr, error, "SysAllocString");
  443. }
  444. }
  445. hr = myFormatCertsrvStringArray(
  446. TRUE, // fURL
  447. pwszServerName, // pwszServerName_p1_2
  448. pwszSanitizedName, // pwszSanitizedName_p3_7
  449. iCert, // iCert_p4
  450. strDomainDN, // pwszDomainDN_p5
  451. strConfigDN, // pwszConfigDN_p6
  452. iCRL, // iCRL_p8
  453. FALSE, // fDeltaCRL_p9
  454. TRUE, // fDSAttrib_p10_11
  455. cpwsz, // cStrings
  456. papwszTemplate, // apwszStringsIn
  457. papwszOut); // apwszStringsOut
  458. _JumpIfError(hr, error, "myFormatCertsrvStringArray");
  459. *pcpwsz = cpwsz;
  460. *ppapwszOut = papwszOut;
  461. papwszOut = NULL;
  462. error:
  463. if (NULL != pwszServerName)
  464. {
  465. LocalFree(pwszServerName);
  466. }
  467. if (NULL != pld)
  468. {
  469. ldap_unbind(pld);
  470. }
  471. if (NULL != strConfigDN)
  472. {
  473. SysFreeString(strConfigDN);
  474. }
  475. if (NULL != strDomainDN)
  476. {
  477. SysFreeString(strDomainDN);
  478. }
  479. if (NULL != papwszTemplate)
  480. {
  481. LocalFree(papwszTemplate);
  482. }
  483. if (NULL != papwszOut)
  484. {
  485. for (i = 0; i < cpwsz; i++)
  486. {
  487. if (papwszOut[i])
  488. {
  489. LocalFree(papwszOut[i]);
  490. }
  491. }
  492. LocalFree(papwszOut);
  493. }
  494. return(hr);
  495. }
  496. //+--------------------------------------------------------------------------
  497. // CreateRevocationExtension
  498. //
  499. // Return S_OK if extension has been constructed.
  500. // Return S_FALSE if empty section detected in INF file
  501. // Return other error if no section detected in INF file
  502. //+--------------------------------------------------------------------------
  503. HRESULT
  504. CreateRevocationExtension(
  505. IN HINF hInf,
  506. IN WCHAR const *pwszSanitizedName,
  507. IN DWORD iCert,
  508. IN DWORD iCRL,
  509. IN BOOL fUseDS,
  510. IN DWORD dwRevocationFlags,
  511. OUT BOOL *pfCritical,
  512. OUT BYTE **ppbEncoded,
  513. OUT DWORD *pcbEncoded)
  514. {
  515. HRESULT hr;
  516. DWORD i;
  517. WCHAR *pwszzCDP = NULL;
  518. WCHAR **papwszURL = NULL;
  519. CRL_DIST_POINTS_INFO CRLDistInfo;
  520. CRL_DIST_POINT CRLDistPoint;
  521. CERT_ALT_NAME_INFO *pAltInfo;
  522. ZeroMemory(&CRLDistPoint, sizeof(CRLDistPoint));
  523. pAltInfo = &CRLDistPoint.DistPointName.FullName;
  524. *ppbEncoded = NULL;
  525. *pcbEncoded = 0;
  526. hr = E_HANDLE;
  527. if (INVALID_HANDLE_VALUE != hInf)
  528. {
  529. hr = myInfGetCRLDistributionPoints(hInf, pfCritical, &pwszzCDP);
  530. }
  531. if (S_OK != hr)
  532. {
  533. if (S_FALSE == hr)
  534. {
  535. _JumpError2(hr, error, "myInfGetCRLDistributionPoints", hr);
  536. }
  537. hr = GetRegCRLDistributionPoints(
  538. pwszSanitizedName,
  539. fUseDS,
  540. &pwszzCDP);
  541. _JumpIfError(hr, error, "GetRegCRLDistributionPoints");
  542. }
  543. if (0 == (REVEXT_CDPENABLE & dwRevocationFlags))
  544. {
  545. hr = S_OK;
  546. goto error;
  547. }
  548. hr = FormatTemplateURLs(
  549. pwszSanitizedName,
  550. iCert,
  551. iCRL,
  552. fUseDS,
  553. pwszzCDP,
  554. &pAltInfo->cAltEntry,
  555. &papwszURL);
  556. _JumpIfError(hr, error, "FormatTemplateURLs");
  557. CRLDistInfo.cDistPoint = 1;
  558. CRLDistInfo.rgDistPoint = &CRLDistPoint;
  559. CRLDistPoint.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
  560. pAltInfo->rgAltEntry = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  561. LMEM_FIXED | LMEM_ZEROINIT,
  562. pAltInfo->cAltEntry * sizeof(pAltInfo->rgAltEntry[0]));
  563. if (NULL == pAltInfo->rgAltEntry)
  564. {
  565. hr = E_OUTOFMEMORY;
  566. _JumpError(hr, error, "LocalAlloc");
  567. }
  568. for (i = 0; i < pAltInfo->cAltEntry; i++)
  569. {
  570. pAltInfo->rgAltEntry[i].pwszURL = papwszURL[i];
  571. pAltInfo->rgAltEntry[i].dwAltNameChoice = CERT_ALT_NAME_URL;
  572. DBGPRINT((DBG_SS_CERTLIB, "CDP[%u] = '%ws'\n", i, papwszURL[i]));
  573. }
  574. if (!myEncodeObject(
  575. X509_ASN_ENCODING,
  576. X509_CRL_DIST_POINTS,
  577. &CRLDistInfo,
  578. 0,
  579. CERTLIB_USE_LOCALALLOC,
  580. ppbEncoded,
  581. pcbEncoded))
  582. {
  583. hr = myHLastError();
  584. _JumpIfError(hr, error, "myEncodeObject");
  585. }
  586. hr = S_OK;
  587. error:
  588. if (NULL != pAltInfo->rgAltEntry)
  589. {
  590. LocalFree(pAltInfo->rgAltEntry);
  591. }
  592. if (NULL != papwszURL)
  593. {
  594. for (i = 0; i < pAltInfo->cAltEntry; i++)
  595. {
  596. if (NULL != papwszURL[i])
  597. {
  598. LocalFree(papwszURL[i]);
  599. }
  600. }
  601. LocalFree(papwszURL);
  602. }
  603. if (NULL != pwszzCDP)
  604. {
  605. LocalFree(pwszzCDP);
  606. }
  607. return(hr);
  608. }
  609. //+--------------------------------------------------------------------------
  610. // CreateAuthorityInformationAccessExtension
  611. //
  612. // Return S_OK if extension has been constructed.
  613. // Return S_FALSE if empty section detected in INF file
  614. // Return other error if no section detected in INF file
  615. //+--------------------------------------------------------------------------
  616. HRESULT
  617. CreateAuthorityInformationAccessExtension(
  618. IN HINF hInf,
  619. IN WCHAR const *pwszSanitizedName,
  620. IN DWORD iCert,
  621. IN DWORD iCRL,
  622. IN BOOL fUseDS,
  623. OUT BOOL *pfCritical,
  624. OUT BYTE **ppbEncoded,
  625. OUT DWORD *pcbEncoded)
  626. {
  627. HRESULT hr;
  628. DWORD i;
  629. WCHAR *pwszzAIA = NULL;
  630. WCHAR **papwszURL = NULL;
  631. CERT_AUTHORITY_INFO_ACCESS caio;
  632. caio.cAccDescr = 0;
  633. caio.rgAccDescr = NULL;
  634. *ppbEncoded = NULL;
  635. *pcbEncoded = 0;
  636. hr = E_HANDLE;
  637. if (INVALID_HANDLE_VALUE != hInf)
  638. {
  639. hr = myInfGetAuthorityInformationAccess(hInf, pfCritical, &pwszzAIA);
  640. }
  641. _JumpIfError3(
  642. hr,
  643. error,
  644. "myInfGetAuthorityInformationAccess",
  645. E_HANDLE,
  646. S_FALSE);
  647. hr = FormatTemplateURLs(
  648. pwszSanitizedName,
  649. iCert,
  650. iCRL,
  651. fUseDS,
  652. pwszzAIA,
  653. &caio.cAccDescr,
  654. &papwszURL);
  655. _JumpIfError(hr, error, "FormatTemplateURLs");
  656. caio.rgAccDescr = (CERT_ACCESS_DESCRIPTION *) LocalAlloc(
  657. LMEM_FIXED | LMEM_ZEROINIT,
  658. caio.cAccDescr * sizeof(CERT_ACCESS_DESCRIPTION));
  659. if (NULL == caio.rgAccDescr)
  660. {
  661. hr = E_OUTOFMEMORY;
  662. _JumpIfError(hr, error, "LocalAlloc");
  663. }
  664. for (i = 0; i < caio.cAccDescr; i++)
  665. {
  666. caio.rgAccDescr[i].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
  667. caio.rgAccDescr[i].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  668. caio.rgAccDescr[i].AccessLocation.pwszURL = papwszURL[i];
  669. DBGPRINT((DBG_SS_CERTLIB, "AIA[%u] = '%ws'\n", i, papwszURL[i]));
  670. }
  671. if (!myEncodeObject(
  672. X509_ASN_ENCODING,
  673. X509_AUTHORITY_INFO_ACCESS,
  674. &caio,
  675. 0,
  676. CERTLIB_USE_LOCALALLOC,
  677. ppbEncoded,
  678. pcbEncoded))
  679. {
  680. hr = myHLastError();
  681. _JumpIfError(hr, error, "myEncodeObject");
  682. }
  683. error:
  684. if (NULL != caio.rgAccDescr)
  685. {
  686. LocalFree(caio.rgAccDescr);
  687. }
  688. if (NULL != papwszURL)
  689. {
  690. for (i = 0; i < caio.cAccDescr; i++)
  691. {
  692. if (NULL != papwszURL[i])
  693. {
  694. LocalFree(papwszURL[i]);
  695. }
  696. }
  697. LocalFree(papwszURL);
  698. }
  699. if (NULL != pwszzAIA)
  700. {
  701. LocalFree(pwszzAIA);
  702. }
  703. return(hr);
  704. }
  705. HRESULT
  706. FillRDN(
  707. IN char const *pszObjId,
  708. IN WCHAR const *pwszRDN,
  709. IN OUT CERT_RDN *prgRDN)
  710. {
  711. HRESULT hr;
  712. CERT_RDN_ATTR *prgAttr = NULL;
  713. prgAttr = (CERT_RDN_ATTR *) LocalAlloc(LMEM_FIXED, sizeof(*prgAttr));
  714. if (NULL == prgAttr)
  715. {
  716. hr = E_OUTOFMEMORY;
  717. _JumpError(hr, error, "LocalAlloc");
  718. }
  719. prgAttr->pszObjId = const_cast<char *>(pszObjId);
  720. prgAttr->dwValueType = 0;
  721. prgAttr->Value.pbData = (BYTE *) pwszRDN;
  722. prgAttr->Value.cbData = 0;
  723. prgRDN->cRDNAttr = 1;
  724. prgRDN->rgRDNAttr = prgAttr;
  725. hr = S_OK;
  726. error:
  727. return(hr);
  728. }
  729. VOID
  730. csiFreeCertNameInfo(
  731. CERT_NAME_INFO *pNameInfo)
  732. {
  733. DWORD iRDN;
  734. if (NULL != pNameInfo)
  735. {
  736. if (NULL != pNameInfo->rgRDN)
  737. {
  738. for (iRDN = 0; iRDN < pNameInfo->cRDN; ++iRDN)
  739. {
  740. if (NULL != pNameInfo->rgRDN[iRDN].rgRDNAttr)
  741. {
  742. LocalFree(pNameInfo->rgRDN[iRDN].rgRDNAttr);
  743. }
  744. }
  745. LocalFree(pNameInfo->rgRDN);
  746. }
  747. LocalFree(pNameInfo);
  748. }
  749. }
  750. HRESULT
  751. FillExtension(
  752. IN OUT CERT_EXTENSION *pDesExt,
  753. IN OUT DWORD *pdwIndex,
  754. IN CERT_EXTENSION *pSrcExt)
  755. {
  756. CSASSERT(NULL != pDesExt && NULL != pSrcExt);
  757. if (NULL != pSrcExt->Value.pbData && 0 != pSrcExt->Value.cbData)
  758. {
  759. pDesExt[*pdwIndex].pszObjId = pSrcExt->pszObjId;
  760. pDesExt[*pdwIndex].fCritical = pSrcExt->fCritical;
  761. pDesExt[*pdwIndex].Value = pSrcExt->Value;
  762. ++(*pdwIndex);
  763. }
  764. return(S_OK);
  765. }
  766. HRESULT
  767. EncodeCertAndSign(
  768. IN HCRYPTPROV hProv,
  769. IN CERT_INFO *pCert,
  770. IN char const *pszAlgId,
  771. OUT BYTE **ppbSigned,
  772. OUT DWORD *pcbSigned,
  773. IN HINSTANCE hInstance,
  774. IN BOOL fUnattended,
  775. IN HWND hwnd)
  776. {
  777. HRESULT hr;
  778. BYTE *pbEncoded = NULL;
  779. DWORD cbEncoded;
  780. *ppbSigned = NULL;
  781. if (!myEncodeToBeSigned(
  782. X509_ASN_ENCODING,
  783. pCert,
  784. CERTLIB_USE_LOCALALLOC,
  785. &pbEncoded,
  786. &cbEncoded))
  787. {
  788. hr = myHLastError();
  789. CertErrorMessageBox(
  790. hInstance,
  791. fUnattended,
  792. hwnd,
  793. IDS_ERR_ENCODETOBESIGNED,
  794. hr,
  795. NULL);
  796. _JumpError(hr, error, "myEncodeToBeSigned");
  797. }
  798. hr = myEncodeSignedContent(
  799. hProv,
  800. X509_ASN_ENCODING,
  801. pszAlgId,
  802. pbEncoded,
  803. cbEncoded,
  804. CERTLIB_USE_LOCALALLOC,
  805. ppbSigned,
  806. pcbSigned);
  807. _JumpIfError(hr, error, "myEncodeSignedContent");
  808. error:
  809. if (NULL != pbEncoded)
  810. {
  811. LocalFree(pbEncoded);
  812. }
  813. return(hr);
  814. }
  815. HRESULT
  816. EncodeCACert(
  817. IN CASERVERSETUPINFO const *pSetupInfo,
  818. IN HCRYPTPROV hProv,
  819. IN const WCHAR *pwszCAType,
  820. OUT BYTE **ppbEncoded,
  821. OUT DWORD *pcbEncoded,
  822. IN HINSTANCE hInstance,
  823. IN BOOL fUnattended,
  824. IN HWND hwnd)
  825. {
  826. HRESULT hr = E_FAIL;
  827. BYTE *pbSubjectEncoded = NULL;
  828. DWORD cbSubjectEncoded = 0;
  829. BYTE *pbIssuerEncoded = NULL;
  830. DWORD cbIssuerEncoded = 0;
  831. CERT_PUBLIC_KEY_INFO *pPubKey = NULL;
  832. DWORD cbPubKey;
  833. HINF hInf = INVALID_HANDLE_VALUE;
  834. DWORD ErrorLine;
  835. CERT_EXTENSIONS *pStdExts = NULL;
  836. CERT_EXTENSION *pAllExts = NULL;
  837. CERT_EXTENSION extKeyUsage =
  838. {szOID_KEY_USAGE, FALSE, 0, NULL};
  839. CERT_EXTENSION extBasicConstraints =
  840. {NULL, FALSE, 0, NULL};
  841. CERT_EXTENSION extAKI =
  842. {szOID_AUTHORITY_KEY_IDENTIFIER2, FALSE, 0, NULL};
  843. CERT_EXTENSION extSKI =
  844. {szOID_SUBJECT_KEY_IDENTIFIER, FALSE, 0, NULL};
  845. CERT_EXTENSION extCDP =
  846. {szOID_CRL_DIST_POINTS, FALSE, 0, NULL};
  847. CERT_EXTENSION extCCDP =
  848. {szOID_CROSS_CERT_DIST_POINTS, FALSE, 0, NULL};
  849. CERT_EXTENSION extVersion =
  850. {szOID_CERTSRV_CA_VERSION, FALSE, 0, NULL};
  851. CERT_EXTENSION extPolicy =
  852. {szOID_CERT_POLICIES, FALSE, 0, NULL};
  853. CERT_EXTENSION extAIA =
  854. {szOID_AUTHORITY_INFO_ACCESS, FALSE, 0, NULL};
  855. CERT_EXTENSION extEKU =
  856. {NULL, FALSE, 0, NULL};
  857. #ifdef USE_NETSCAPE_TYPE_EXTENSION
  858. CERT_EXTENSION extNetscape =
  859. {szOID_NETSCAPE_CERT_TYPE, FALSE, 0, NULL};
  860. #endif
  861. DWORD cExtension;
  862. HCERTTYPE hCertType = NULL;
  863. DWORD i;
  864. DWORD j;
  865. GUID guidSerialNumber;
  866. CERT_INFO Cert;
  867. *ppbEncoded = NULL;
  868. LPCWSTR pszErrorPtr;
  869. hr = myInfOpenFile(NULL, &hInf, &ErrorLine);
  870. _PrintIfError2(
  871. hr,
  872. "myInfOpenFile",
  873. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  874. if (INVALID_HANDLE_VALUE != hInf)
  875. {
  876. BOOL fUTF8;
  877. hr = myInfGetBooleanValue(
  878. hInf,
  879. wszINFSECTION_CERTSERVER,
  880. wszINFKEY_UTF8,
  881. TRUE,
  882. &fUTF8);
  883. if (S_OK == hr)
  884. {
  885. g_dwNameEncodeFlags = fUTF8? CERT_RDN_ENABLE_UTF8_UNICODE_FLAG : 0;
  886. }
  887. }
  888. // SUBJECT
  889. hr = AddCNAndEncode(
  890. pSetupInfo->pwszCACommonName,
  891. pSetupInfo->pwszDNSuffix,
  892. &pbSubjectEncoded,
  893. &cbSubjectEncoded);
  894. _JumpIfError(hr, error, "AddCNAndEncodeCertStrToName");
  895. // ISSUER
  896. hr = AddCNAndEncode(
  897. pSetupInfo->pwszCACommonName,
  898. pSetupInfo->pwszDNSuffix,
  899. &pbIssuerEncoded,
  900. &cbIssuerEncoded);
  901. _JumpIfError(hr, error, "AddCNAndEncodeCertStrToName");
  902. if (!myCryptExportPublicKeyInfo(
  903. hProv,
  904. AT_SIGNATURE,
  905. CERTLIB_USE_LOCALALLOC,
  906. &pPubKey,
  907. &cbPubKey))
  908. {
  909. hr = myHLastError();
  910. _JumpError(hr, error, "myCryptExportPublicKeyInfo");
  911. }
  912. // get cert type
  913. hr = CAFindCertTypeByName(
  914. pwszCAType,
  915. NULL,
  916. CT_FIND_LOCAL_SYSTEM |
  917. CT_ENUM_MACHINE_TYPES |
  918. CT_ENUM_USER_TYPES,
  919. &hCertType);
  920. if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr)
  921. {
  922. hr = CAFindCertTypeByName(
  923. pwszCAType,
  924. NULL,
  925. CT_FIND_LOCAL_SYSTEM |
  926. CT_ENUM_MACHINE_TYPES |
  927. CT_ENUM_USER_TYPES |
  928. CT_FIND_BY_OID,
  929. &hCertType);
  930. }
  931. if (S_OK == hr)
  932. {
  933. // get cert type standard extensions
  934. hr = CAGetCertTypeExtensions(hCertType, &pStdExts);
  935. _JumpIfErrorStr(hr, error, "CAGetCertTypeExtensions", pwszCAType);
  936. cExtension = pStdExts->cExtension;
  937. }
  938. else
  939. {
  940. cExtension = 0;
  941. DBGERRORPRINTLINE("CAFindCertTypeByName", hr);
  942. }
  943. if (NULL == pStdExts)
  944. {
  945. // standard extensions not available from CAGetCertTypeExtensions
  946. if (!CreateKeyUsageExtension(
  947. myCASIGN_KEY_USAGE,
  948. &extKeyUsage.Value.pbData,
  949. &extKeyUsage.Value.cbData,
  950. hInstance,
  951. fUnattended,
  952. hwnd))
  953. {
  954. hr = myHLastError();
  955. _JumpError(hr, error, "CreateKeyUsageExtension");
  956. }
  957. ++cExtension;
  958. }
  959. hr = myInfGetBasicConstraints2CAExtensionOrDefault(hInf, &extBasicConstraints);
  960. _JumpIfError(hr, error, "myInfGetBasicConstraints2CAExtensionOrDefault");
  961. ++cExtension;
  962. // Subject Key Identifier extension:
  963. hr = myCreateSubjectKeyIdentifierExtension(
  964. pPubKey,
  965. &extSKI.Value.pbData,
  966. &extSKI.Value.cbData);
  967. _JumpIfError(hr, error, "myCreateSubjectKeyIdentifierExtension");
  968. ++cExtension;
  969. hr = CreateRevocationExtension(
  970. hInf,
  971. pSetupInfo->pwszSanitizedName,
  972. 0, // iCert
  973. 0, // iCRL
  974. pSetupInfo->fUseDS,
  975. pSetupInfo->dwRevocationFlags,
  976. &extCDP.fCritical,
  977. &extCDP.Value.pbData,
  978. &extCDP.Value.cbData);
  979. _PrintIfError(hr, "CreateRevocationExtension");
  980. CSASSERT((NULL == extCDP.Value.pbData) ^ (S_OK == hr));
  981. if (S_OK == hr)
  982. {
  983. ++cExtension;
  984. }
  985. hr = myInfGetCrossCertDistributionPointsExtension(hInf, &extCCDP);
  986. _PrintIfError(hr, "myInfGetCrossCertDistributionPointsExtension");
  987. CSASSERT((NULL == extCCDP.Value.pbData) ^ (S_OK == hr));
  988. if (S_OK == hr)
  989. {
  990. ++cExtension;
  991. }
  992. // Build the CA Version extension
  993. if (!myEncodeObject(
  994. X509_ASN_ENCODING,
  995. X509_INTEGER,
  996. &pSetupInfo->dwCertNameId,
  997. 0,
  998. CERTLIB_USE_LOCALALLOC,
  999. &extVersion.Value.pbData,
  1000. &extVersion.Value.cbData))
  1001. {
  1002. hr = myHLastError();
  1003. _JumpError(hr, error, "myEncodeObject");
  1004. }
  1005. ++cExtension;
  1006. hr = myInfGetPolicyStatementExtension(hInf, &extPolicy);
  1007. _PrintIfError(hr, "myInfCreatePolicyStatementExtension");
  1008. CSASSERT((NULL == extPolicy.Value.pbData) ^ (S_OK == hr));
  1009. if (S_OK == hr)
  1010. {
  1011. ++cExtension;
  1012. }
  1013. hr = CreateAuthorityInformationAccessExtension(
  1014. hInf,
  1015. pSetupInfo->pwszSanitizedName,
  1016. 0, // iCert
  1017. 0, // iCRL
  1018. pSetupInfo->fUseDS,
  1019. &extAIA.fCritical,
  1020. &extAIA.Value.pbData,
  1021. &extAIA.Value.cbData);
  1022. _PrintIfError(hr, "CreateAuthorityInformationAccessExtension");
  1023. CSASSERT((NULL == extAIA.Value.pbData) ^ (S_OK == hr));
  1024. if (S_OK == hr)
  1025. {
  1026. ++cExtension;
  1027. }
  1028. hr = myInfGetEnhancedKeyUsageExtension(hInf, &extEKU);
  1029. _PrintIfError(hr, "myInfGetEnhancedKeyUsageExtension");
  1030. CSASSERT((NULL == extEKU.Value.pbData) ^ (S_OK == hr));
  1031. if (S_OK == hr)
  1032. {
  1033. ++cExtension;
  1034. }
  1035. #ifdef USE_NETSCAPE_TYPE_EXTENSION
  1036. // Netscape Cert Type extension:
  1037. if (!CreateNetscapeTypeExtension(
  1038. &extNetscape.Value.pbData,
  1039. &extNetscape.Value.cbData))
  1040. {
  1041. hr = myHLastError();
  1042. _JumpError(hr, error, "CreateNetscapeTypeExtension");
  1043. }
  1044. ++cExtension;
  1045. #endif
  1046. // put all extensions together
  1047. pAllExts = (CERT_EXTENSION*)LocalAlloc(
  1048. LMEM_FIXED | LMEM_ZEROINIT,
  1049. cExtension * sizeof(CERT_EXTENSION));
  1050. if (NULL == pAllExts)
  1051. {
  1052. hr = E_OUTOFMEMORY;
  1053. _JumpError(hr, error, "LocalAlloc");
  1054. }
  1055. i = 0;
  1056. if (NULL != pStdExts)
  1057. {
  1058. for (j = 0 ; j < pStdExts->cExtension; j++)
  1059. {
  1060. if (0 == strcmp(szOID_BASIC_CONSTRAINTS2, pStdExts->rgExtension[j].pszObjId))
  1061. {
  1062. continue;
  1063. }
  1064. pAllExts[i].pszObjId = pStdExts->rgExtension[j].pszObjId;
  1065. pAllExts[i].fCritical = pStdExts->rgExtension[j].fCritical;
  1066. pAllExts[i].Value = pStdExts->rgExtension[j].Value;
  1067. i++;
  1068. }
  1069. }
  1070. FillExtension(pAllExts, &i, &extKeyUsage);
  1071. FillExtension(pAllExts, &i, &extBasicConstraints);
  1072. FillExtension(pAllExts, &i, &extAKI);
  1073. FillExtension(pAllExts, &i, &extSKI);
  1074. FillExtension(pAllExts, &i, &extCDP);
  1075. FillExtension(pAllExts, &i, &extCCDP);
  1076. FillExtension(pAllExts, &i, &extVersion);
  1077. FillExtension(pAllExts, &i, &extPolicy);
  1078. FillExtension(pAllExts, &i, &extAIA);
  1079. FillExtension(pAllExts, &i, &extEKU);
  1080. #ifdef USE_NETSCAPE_TYPE_EXTENSION
  1081. FillExtension(pAllExts, &i, &extKeyNetscape);
  1082. #endif
  1083. CSASSERT(i <= cExtension);
  1084. // CERT
  1085. ZeroMemory(&Cert, sizeof(Cert));
  1086. Cert.dwVersion = CERT_V3;
  1087. myGenerateGuidSerialNumber(&guidSerialNumber);
  1088. Cert.SerialNumber.pbData = (BYTE *) &guidSerialNumber;
  1089. Cert.SerialNumber.cbData = sizeof(guidSerialNumber);
  1090. Cert.SignatureAlgorithm.pszObjId = pSetupInfo->pszAlgId;
  1091. Cert.Issuer.pbData = pbIssuerEncoded;
  1092. Cert.Issuer.cbData = cbIssuerEncoded;
  1093. GetSystemTimeAsFileTime(&Cert.NotBefore);
  1094. myMakeExprDateTime(
  1095. &Cert.NotBefore,
  1096. -CCLOCKSKEWMINUTESDEFAULT,
  1097. ENUM_PERIOD_MINUTES);
  1098. if (0 < CompareFileTime(&Cert.NotBefore, &pSetupInfo->NotBefore))
  1099. {
  1100. Cert.NotBefore = pSetupInfo->NotBefore;
  1101. }
  1102. Cert.NotAfter = pSetupInfo->NotAfter;
  1103. Cert.Subject.pbData = pbSubjectEncoded;
  1104. Cert.Subject.cbData = cbSubjectEncoded;
  1105. Cert.SubjectPublicKeyInfo = *pPubKey; // Structure assignment
  1106. Cert.cExtension = i;
  1107. Cert.rgExtension = pAllExts;
  1108. hr = EncodeCertAndSign(
  1109. hProv,
  1110. &Cert,
  1111. pSetupInfo->pszAlgId,
  1112. ppbEncoded,
  1113. pcbEncoded,
  1114. hInstance,
  1115. fUnattended,
  1116. hwnd);
  1117. _JumpIfError(hr, error, "EncodeCertAndSign");
  1118. error:
  1119. if (INVALID_HANDLE_VALUE != hInf)
  1120. {
  1121. myInfCloseFile(hInf);
  1122. }
  1123. if (NULL != extKeyUsage.Value.pbData)
  1124. {
  1125. LocalFree(extKeyUsage.Value.pbData);
  1126. }
  1127. if (NULL != extBasicConstraints.Value.pbData)
  1128. {
  1129. LocalFree(extBasicConstraints.Value.pbData);
  1130. }
  1131. if (NULL != extAKI.Value.pbData)
  1132. {
  1133. LocalFree(extAKI.Value.pbData);
  1134. }
  1135. if (NULL != extSKI.Value.pbData)
  1136. {
  1137. LocalFree(extSKI.Value.pbData);
  1138. }
  1139. if (NULL != extCDP.Value.pbData)
  1140. {
  1141. LocalFree(extCDP.Value.pbData);
  1142. }
  1143. if (NULL != extCCDP.Value.pbData)
  1144. {
  1145. LocalFree(extCCDP.Value.pbData);
  1146. }
  1147. if (NULL != extVersion.Value.pbData)
  1148. {
  1149. LocalFree(extVersion.Value.pbData);
  1150. }
  1151. if (NULL != extPolicy.Value.pbData)
  1152. {
  1153. LocalFree(extPolicy.Value.pbData);
  1154. }
  1155. if (NULL != extAIA.Value.pbData)
  1156. {
  1157. LocalFree(extAIA.Value.pbData);
  1158. }
  1159. if (NULL != extEKU.Value.pbData)
  1160. {
  1161. LocalFree(extEKU.Value.pbData);
  1162. }
  1163. #ifdef USE_NETSCAPE_TYPE_EXTENSION
  1164. if (NULL != extKeyNetscape.Value.pbData)
  1165. {
  1166. LocalFree(extKeyNetscape.Value.pbData);
  1167. }
  1168. #endif
  1169. if (NULL != hCertType)
  1170. {
  1171. if (NULL != pStdExts)
  1172. {
  1173. CAFreeCertTypeExtensions(hCertType, pStdExts);
  1174. }
  1175. CACloseCertType(hCertType);
  1176. }
  1177. if (NULL != pAllExts)
  1178. {
  1179. LocalFree(pAllExts);
  1180. }
  1181. if (NULL != pbSubjectEncoded)
  1182. {
  1183. LocalFree(pbSubjectEncoded);
  1184. }
  1185. if (NULL != pbIssuerEncoded)
  1186. {
  1187. LocalFree(pbIssuerEncoded);
  1188. }
  1189. if (NULL != pPubKey)
  1190. {
  1191. LocalFree(pPubKey);
  1192. }
  1193. CSILOG(hr, IDS_ILOG_BUILDCERT, NULL, NULL, NULL);
  1194. return(hr);
  1195. }
  1196. HRESULT
  1197. csiGetCRLPublicationParams(
  1198. BOOL fBase,
  1199. WCHAR** ppwszCRLPeriod,
  1200. DWORD* pdwCRLCount)
  1201. {
  1202. HRESULT hr;
  1203. HINF hInf = INVALID_HANDLE_VALUE;
  1204. DWORD ErrorLine;
  1205. hr = myInfOpenFile(NULL, &hInf, &ErrorLine);
  1206. _JumpIfError2(
  1207. hr,
  1208. error,
  1209. "myInfOpenFile",
  1210. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1211. if (INVALID_HANDLE_VALUE != hInf)
  1212. {
  1213. hr = myinfGetCRLPublicationParams(
  1214. hInf,
  1215. fBase? wszINFKEY_CRLPERIODSTRING : wszINFKEY_CRLDELTAPERIODSTRING,
  1216. fBase? wszINFKEY_CRLPERIODCOUNT : wszINFKEY_CRLDELTAPERIODCOUNT,
  1217. ppwszCRLPeriod,
  1218. pdwCRLCount);
  1219. _JumpIfError(hr, error, "myinfGetCRLPublicationParams");
  1220. }
  1221. error:
  1222. if (INVALID_HANDLE_VALUE != hInf)
  1223. {
  1224. myInfCloseFile(hInf);
  1225. }
  1226. return hr;
  1227. }
  1228. HRESULT
  1229. csiBuildFileName(
  1230. IN WCHAR const *pwszDirPath,
  1231. IN WCHAR const *pwszSanitizedName,
  1232. IN WCHAR const *pwszExt,
  1233. IN DWORD iCert,
  1234. OUT WCHAR **ppwszOut,
  1235. HINSTANCE hInstance,
  1236. BOOL fUnattended,
  1237. IN HWND hwnd)
  1238. {
  1239. HRESULT hr;
  1240. DWORD cwc;
  1241. WCHAR *pwszServerName = NULL;
  1242. WCHAR wszIndex[cwcFILENAMESUFFIXMAX]; // L"(%u)"
  1243. *ppwszOut = NULL;
  1244. wszIndex[0] = L'\0';
  1245. if (0 != iCert)
  1246. {
  1247. wsprintf(wszIndex, L"(%u)", iCert);
  1248. }
  1249. hr = myGetMachineDnsName(&pwszServerName);
  1250. if (S_OK != hr)
  1251. {
  1252. CertErrorMessageBox(
  1253. hInstance,
  1254. fUnattended,
  1255. hwnd,
  1256. IDS_ERR_GETCOMPUTERNAME,
  1257. hr,
  1258. NULL);
  1259. _JumpError(hr, error, "myGetMachineDnsName");
  1260. }
  1261. cwc = wcslen(pwszDirPath) +
  1262. WSZARRAYSIZE(g_szSlash) +
  1263. wcslen(pwszServerName) +
  1264. WSZARRAYSIZE(L"_") +
  1265. wcslen(pwszSanitizedName) +
  1266. wcslen(wszIndex) +
  1267. wcslen(pwszExt) +
  1268. 1; // NULL term
  1269. *ppwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  1270. if (NULL == *ppwszOut)
  1271. {
  1272. hr = E_OUTOFMEMORY;
  1273. _JumpError(hr, error, "LocalAlloc");
  1274. }
  1275. wcscpy(*ppwszOut, pwszDirPath);
  1276. wcscat(*ppwszOut, g_szSlash);
  1277. wcscat(*ppwszOut, pwszServerName);
  1278. wcscat(*ppwszOut, L"_");
  1279. wcscat(*ppwszOut, pwszSanitizedName);
  1280. wcscat(*ppwszOut, wszIndex);
  1281. wcscat(*ppwszOut, pwszExt);
  1282. hr = S_OK;
  1283. error:
  1284. if (NULL != pwszServerName)
  1285. {
  1286. LocalFree(pwszServerName);
  1287. }
  1288. return(hr);
  1289. }
  1290. HRESULT
  1291. csiBuildCACertFileName(
  1292. IN HINSTANCE hInstance,
  1293. IN HWND hwnd,
  1294. IN BOOL fUnattended,
  1295. OPTIONAL IN WCHAR const *pwszSharedFolder,
  1296. IN WCHAR const *pwszSanitizedName,
  1297. IN WCHAR const *pwszExt,
  1298. IN DWORD iCert,
  1299. OUT WCHAR **ppwszCACertFile)
  1300. {
  1301. HRESULT hr;
  1302. WCHAR *pwszCACertFile = NULL;
  1303. WCHAR const *pwszDir = pwszSharedFolder;
  1304. WCHAR *pwszDirAlloc = NULL;
  1305. CSASSERT(NULL != ppwszCACertFile);
  1306. *ppwszCACertFile = NULL;
  1307. if (NULL == pwszDir)
  1308. {
  1309. // no shared folder, go system drive
  1310. hr = myGetEnvString(&pwszDirAlloc, L"SystemDrive");
  1311. _JumpIfError(hr, error, "myGetEnvString");
  1312. pwszDir = pwszDirAlloc;
  1313. }
  1314. // build ca cert file name here
  1315. hr = csiBuildFileName(
  1316. pwszDir,
  1317. pwszSanitizedName,
  1318. pwszExt,
  1319. iCert,
  1320. &pwszCACertFile,
  1321. hInstance,
  1322. fUnattended,
  1323. hwnd);
  1324. _JumpIfError(hr, error, "csiBuildFileName");
  1325. CSASSERT(NULL != pwszCACertFile);
  1326. *ppwszCACertFile = pwszCACertFile;
  1327. hr = S_OK;
  1328. error:
  1329. if (NULL != pwszDirAlloc)
  1330. {
  1331. LocalFree(pwszDirAlloc);
  1332. }
  1333. return(hr);
  1334. }
  1335. HRESULT
  1336. csiBuildAndWriteCert(
  1337. IN HCRYPTPROV hCryptProv,
  1338. IN CASERVERSETUPINFO const *pServer,
  1339. OPTIONAL IN WCHAR const *pwszFile,
  1340. IN WCHAR const *pwszEnrollFile,
  1341. OPTIONAL IN CERT_CONTEXT const *pCertContextFromStore,
  1342. OPTIONAL OUT CERT_CONTEXT const **ppCertContextOut,
  1343. IN WCHAR const *pwszCAType,
  1344. IN HINSTANCE hInstance,
  1345. IN BOOL fUnattended,
  1346. IN HWND hwnd)
  1347. {
  1348. BYTE *pbEncoded = NULL;
  1349. DWORD cbEncoded;
  1350. CERT_CONTEXT const *pccCA = NULL;
  1351. HRESULT hr;
  1352. if (NULL != ppCertContextOut)
  1353. {
  1354. *ppCertContextOut = NULL;
  1355. }
  1356. if (NULL == pCertContextFromStore)
  1357. {
  1358. // create cert
  1359. hr = EncodeCACert(
  1360. pServer,
  1361. hCryptProv,
  1362. pwszCAType,
  1363. &pbEncoded,
  1364. &cbEncoded,
  1365. hInstance,
  1366. fUnattended,
  1367. hwnd);
  1368. _JumpIfError(hr, error, "EncodeCACert");
  1369. pccCA = CertCreateCertificateContext(
  1370. X509_ASN_ENCODING,
  1371. pbEncoded,
  1372. cbEncoded);
  1373. if (NULL == pccCA)
  1374. {
  1375. hr = myHLastError();
  1376. _JumpError(hr, error, "CertCreateCertificateContext");
  1377. }
  1378. }
  1379. else
  1380. {
  1381. pccCA = CertDuplicateCertificateContext(pCertContextFromStore);
  1382. if (NULL == pccCA)
  1383. {
  1384. hr = myHLastError();
  1385. _JumpError(hr, error, "CertDuplicateCertificateContext");
  1386. }
  1387. }
  1388. if (NULL != pwszFile && !csiWriteDERToFile(
  1389. pwszFile,
  1390. pccCA->pbCertEncoded,
  1391. pccCA->cbCertEncoded,
  1392. hInstance,
  1393. fUnattended,
  1394. hwnd))
  1395. {
  1396. hr = myHLastError();
  1397. _JumpError(hr, error, "csiWriteDERToFile");
  1398. }
  1399. if (!csiWriteDERToFile(
  1400. pwszEnrollFile,
  1401. pccCA->pbCertEncoded,
  1402. pccCA->cbCertEncoded,
  1403. hInstance,
  1404. fUnattended,
  1405. hwnd))
  1406. {
  1407. hr = myHLastError();
  1408. _JumpError(hr, error, "csiWriteDERToFile(enroll)");
  1409. }
  1410. if (NULL != ppCertContextOut)
  1411. {
  1412. *ppCertContextOut = pccCA;
  1413. pccCA = NULL;
  1414. }
  1415. hr = S_OK;
  1416. error:
  1417. if (NULL != pccCA)
  1418. {
  1419. if (!CertFreeCertificateContext(pccCA))
  1420. {
  1421. HRESULT hr2;
  1422. hr2 = myHLastError();
  1423. _PrintError(hr2, "CertFreeCertificateContext");
  1424. CSASSERT(S_OK == hr2);
  1425. }
  1426. }
  1427. if (NULL != pbEncoded)
  1428. {
  1429. LocalFree(pbEncoded);
  1430. }
  1431. return(hr);
  1432. }
  1433. HRESULT
  1434. IsCACert(
  1435. IN HINSTANCE hInstance,
  1436. IN BOOL fUnattended,
  1437. IN HWND hwnd,
  1438. IN CERT_CONTEXT const *pCert)
  1439. {
  1440. HRESULT hr;
  1441. BOOL fCA;
  1442. CERT_EXTENSION *pExt;
  1443. DWORD cb;
  1444. CERT_BASIC_CONSTRAINTS2_INFO Constraints;
  1445. fCA = FALSE;
  1446. pExt = CertFindExtension(
  1447. szOID_BASIC_CONSTRAINTS2,
  1448. pCert->pCertInfo->cExtension,
  1449. pCert->pCertInfo->rgExtension);
  1450. if (NULL == pExt)
  1451. {
  1452. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1453. _PrintError(hr, "CertFindExtension");
  1454. }
  1455. else
  1456. {
  1457. cb = sizeof(Constraints);
  1458. if (!CryptDecodeObject(
  1459. X509_ASN_ENCODING,
  1460. X509_BASIC_CONSTRAINTS2,
  1461. pExt->Value.pbData,
  1462. pExt->Value.cbData,
  1463. 0,
  1464. &Constraints,
  1465. &cb))
  1466. {
  1467. hr = myHLastError();
  1468. _PrintError(hr, "CryptDecodeObject");
  1469. }
  1470. else
  1471. {
  1472. fCA = Constraints.fCA;
  1473. if (!fCA)
  1474. {
  1475. hr = CERTSRV_E_INVALID_CA_CERTIFICATE;
  1476. _PrintError(hr, "fCA not set");
  1477. }
  1478. }
  1479. }
  1480. if (!fCA)
  1481. {
  1482. CertMessageBox(
  1483. hInstance,
  1484. fUnattended,
  1485. hwnd,
  1486. IDS_ERR_NOTCACERT,
  1487. S_OK,
  1488. MB_OK | MB_ICONERROR | CMB_NOERRFROMSYS,
  1489. NULL);
  1490. _JumpError(hr, error, "not a CA cert");
  1491. }
  1492. hr = S_OK;
  1493. error:
  1494. return(hr);
  1495. }
  1496. HRESULT
  1497. ExtractCACertFromPKCS7(
  1498. IN WCHAR const *pwszCommonName,
  1499. IN BYTE const *pbPKCS7,
  1500. IN DWORD cbPKCS7,
  1501. OPTIONAL OUT CERT_CONTEXT const **ppccCA)
  1502. {
  1503. HRESULT hr;
  1504. CERT_CONTEXT const *pCert = NULL;
  1505. HCERTSTORE hChainStore = NULL;
  1506. CRYPT_DATA_BLOB chainBlob;
  1507. CERT_RDN_ATTR rdnAttr = { szOID_COMMON_NAME, CERT_RDN_ANY_TYPE, };
  1508. CERT_RDN rdn = { 1, &rdnAttr };
  1509. CERT_CHAIN_PARA ChainPara;
  1510. CERT_CHAIN_CONTEXT const *pChainContext = NULL;
  1511. CERT_CHAIN_CONTEXT const *pLongestChainContext = NULL;
  1512. *ppccCA = NULL;
  1513. if (NULL == pbPKCS7 || 0 == cbPKCS7)
  1514. {
  1515. hr = E_INVALIDARG;
  1516. _JumpError(hr, error, "Invalid input parameters");
  1517. }
  1518. chainBlob.pbData = const_cast<BYTE *>(pbPKCS7);
  1519. chainBlob.cbData = cbPKCS7;
  1520. hChainStore = CertOpenStore(
  1521. CERT_STORE_PROV_PKCS7,
  1522. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1523. NULL, // hProv
  1524. 0,
  1525. (const void*) &chainBlob);
  1526. if (NULL == hChainStore)
  1527. {
  1528. hr = myHLastError();
  1529. _JumpError(hr, error, "CertOpenStore");
  1530. }
  1531. rdnAttr.Value.pbData = (BYTE *) pwszCommonName;
  1532. rdnAttr.Value.cbData = 0;
  1533. // Find the longest chain in the passed PKCS7 with a leaf CA cert that
  1534. // matches the passed common name
  1535. while (TRUE)
  1536. {
  1537. pCert = CertFindCertificateInStore(
  1538. hChainStore,
  1539. X509_ASN_ENCODING,
  1540. CERT_UNICODE_IS_RDN_ATTRS_FLAG |
  1541. CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG,
  1542. CERT_FIND_SUBJECT_ATTR,
  1543. &rdn,
  1544. pCert);
  1545. if (NULL == pCert)
  1546. {
  1547. if (NULL == pLongestChainContext)
  1548. {
  1549. hr = E_INVALIDARG;
  1550. _JumpError(hr, error, "can't find matched cert in chain");
  1551. }
  1552. break; // most common case, done here
  1553. }
  1554. ZeroMemory(&ChainPara, sizeof(ChainPara));
  1555. ChainPara.cbSize = sizeof(CERT_CHAIN_PARA);
  1556. ChainPara.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  1557. //ChainPara.RequestedUsage.Usage.cUsageIdentifier = 0;
  1558. //ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = NULL;
  1559. if (!CertGetCertificateChain(
  1560. HCCE_LOCAL_MACHINE,
  1561. pCert,
  1562. NULL,
  1563. hChainStore,
  1564. &ChainPara,
  1565. 0,
  1566. NULL,
  1567. &pChainContext))
  1568. {
  1569. // couldn't get the chain
  1570. if (NULL == pLongestChainContext)
  1571. {
  1572. // fail to find a chain
  1573. hr = myHLastError();
  1574. _JumpError(hr, error, "CertGetCertificateChain");
  1575. }
  1576. break; // done with it
  1577. }
  1578. // we have assumed each chain context contains
  1579. // only one simple chain, ie. pChainContext->cChain = 1
  1580. CSASSERT(1 == pChainContext->cChain);
  1581. if (NULL == pLongestChainContext ||
  1582. pChainContext->rgpChain[0]->cElement >
  1583. pLongestChainContext->rgpChain[0]->cElement)
  1584. {
  1585. if (NULL != pLongestChainContext)
  1586. {
  1587. CertFreeCertificateChain(pLongestChainContext);
  1588. }
  1589. // save pointer to this chain
  1590. pLongestChainContext = pChainContext;
  1591. }
  1592. else
  1593. {
  1594. CertFreeCertificateChain(pChainContext);
  1595. }
  1596. }
  1597. CSASSERT(NULL == pCert);
  1598. if (NULL != pLongestChainContext &&
  1599. 0 < pLongestChainContext->rgpChain[0]->cElement)
  1600. {
  1601. *ppccCA = CertDuplicateCertificateContext(
  1602. pLongestChainContext->rgpChain[0]->rgpElement[0]->pCertContext);
  1603. if (NULL == *ppccCA)
  1604. {
  1605. hr = myHLastError();
  1606. _JumpError(hr, error, "CertDuplicateCertificateContext");
  1607. }
  1608. }
  1609. hr = S_OK;
  1610. error:
  1611. if (NULL != pCert)
  1612. {
  1613. CertFreeCertificateContext(pCert);
  1614. }
  1615. if (NULL != pLongestChainContext)
  1616. {
  1617. CertFreeCertificateChain(pLongestChainContext);
  1618. }
  1619. if (hChainStore)
  1620. {
  1621. CertCloseStore(hChainStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1622. }
  1623. CSILOG(hr, IDS_ILOG_SAVECHAINANDKEYS, pwszCommonName, NULL, NULL);
  1624. return(hr);
  1625. }
  1626. #define ENTERPRISECATEMPLATELIST \
  1627. wszCERTTYPE_ADMIN, \
  1628. wszCERTTYPE_SUBORDINATE_CA, \
  1629. wszCERTTYPE_USER, \
  1630. wszCERTTYPE_MACHINE, \
  1631. wszCERTTYPE_WEBSERVER, \
  1632. wszCERTTYPE_DC, \
  1633. wszCERTTYPE_EFS, \
  1634. wszCERTTYPE_EFS_RECOVERY
  1635. WCHAR *s_apwszCertTypeServer[] =
  1636. {
  1637. ENTERPRISECATEMPLATELIST,
  1638. NULL
  1639. };
  1640. WCHAR *s_apwszCertTypeAdvancedServer[] =
  1641. {
  1642. ENTERPRISECATEMPLATELIST,
  1643. wszCERTTYPE_DC_AUTH,
  1644. wszCERTTYPE_DS_EMAIL_REPLICATION,
  1645. NULL
  1646. };
  1647. HRESULT
  1648. CreateCDPAndAIAAndKRAEntry(
  1649. IN WCHAR const *pwszSanitizedCAName,
  1650. IN WCHAR const *pwszSanitizedDSName,
  1651. IN WCHAR const *pwszServerName,
  1652. IN DWORD iCert,
  1653. IN DWORD iCRL,
  1654. IN BOOL fRenew,
  1655. IN BYTE const *pbCert,
  1656. IN DWORD cbCert,
  1657. IN PSECURITY_DESCRIPTOR pSD,
  1658. IN PSECURITY_DESCRIPTOR pContainerSD)
  1659. {
  1660. HRESULT hr;
  1661. LDAP *pld = NULL;
  1662. BSTR strConfigDN = NULL;
  1663. BSTR strDomainDN = NULL;
  1664. WCHAR *pwszCDPDN = NULL;
  1665. WCHAR *pwszAIADN;
  1666. WCHAR *pwszKRADN;
  1667. WCHAR const *apwszIn[3];
  1668. WCHAR *apwszOut[3];
  1669. DWORD i;
  1670. DWORD dwDisp;
  1671. WCHAR *pwszError = NULL;
  1672. ZeroMemory(apwszOut, sizeof(apwszOut));
  1673. hr = myRobustLdapBind(&pld, FALSE);
  1674. _JumpIfError(hr, error, "myRobustLdapBind");
  1675. hr = myGetAuthoritativeDomainDn(pld, &strDomainDN, &strConfigDN);
  1676. if (S_OK != hr)
  1677. {
  1678. hr = myHError(hr);
  1679. _JumpError(hr, error, "myGetAuthoritativeDomainDn");
  1680. }
  1681. DBGPRINT((DBG_SS_CERTLIBI, "DomainDN='%ws'\n", strDomainDN));
  1682. DBGPRINT((DBG_SS_CERTLIBI, "ConfigDN='%ws'\n", strConfigDN));
  1683. apwszIn[0] = g_wszCDPDNTemplate;
  1684. apwszIn[1] = g_wszAIADNTemplate;
  1685. apwszIn[2] = g_wszKRADNTemplate;
  1686. // Format the CDP and AIA templates into real names
  1687. hr = myFormatCertsrvStringArray(
  1688. FALSE, // fURL
  1689. pwszServerName, // pwszServerName_p1_2
  1690. pwszSanitizedCAName, // pwszSanitizedName_p3_7
  1691. iCert, // iCert_p4
  1692. strDomainDN, // pwszDomainDN_p5
  1693. strConfigDN, // pwszConfigDN_p6
  1694. iCRL, // iCRL_p8
  1695. FALSE, // fDeltaCRL_p9
  1696. FALSE, // fDSAttrib_p10_11
  1697. ARRAYSIZE(apwszIn), // cStrings
  1698. (LPCWSTR *) apwszIn, // apwszStringsIn
  1699. apwszOut); // apwszStringsOut
  1700. _JumpIfError(hr, error, "myFormatCertsrvStringArray");
  1701. pwszCDPDN = apwszOut[0];
  1702. pwszAIADN = apwszOut[1];
  1703. pwszKRADN = apwszOut[2];
  1704. DBGPRINT((DBG_SS_CERTLIBI, "CDPDN='%ws'\n", pwszCDPDN));
  1705. DBGPRINT((DBG_SS_CERTLIBI, "AIADN='%ws'\n", pwszAIADN));
  1706. DBGPRINT((DBG_SS_CERTLIBI, "KRADN='%ws'\n", pwszKRADN));
  1707. //+=====================================================================
  1708. // Create the CDP container and object:
  1709. hr = myLdapCreateContainer(
  1710. pld,
  1711. pwszCDPDN,
  1712. TRUE,
  1713. 1,
  1714. pContainerSD,
  1715. &pwszError);
  1716. _JumpIfError(hr, error, "myLdapCreateContainer");
  1717. CSASSERT(NULL == pwszError);
  1718. hr = myLdapCreateCDPObject(pld, pwszCDPDN, pSD, &dwDisp, &pwszError);
  1719. _JumpIfErrorStr(hr, error, "myLdapCreateCDPObject", pwszCDPDN);
  1720. CSASSERT(NULL == pwszError);
  1721. //+=====================================================================
  1722. // Create the container and AIA object:
  1723. hr = myLdapCreateContainer(
  1724. pld,
  1725. pwszAIADN,
  1726. TRUE,
  1727. 0,
  1728. pContainerSD,
  1729. &pwszError);
  1730. _JumpIfError(hr, error, "myLdapCreateContainer");
  1731. CSASSERT(NULL == pwszError);
  1732. hr = myLdapCreateCAObject(
  1733. pld,
  1734. pwszAIADN,
  1735. pbCert,
  1736. cbCert,
  1737. pSD,
  1738. &dwDisp,
  1739. &pwszError);
  1740. _JumpIfErrorStr(hr, error, "myLdapCreateCAObject", pwszAIADN);
  1741. CSASSERT(NULL == pwszError);
  1742. //+=====================================================================
  1743. // Create the KRA container and object:
  1744. hr = myLdapCreateContainer(
  1745. pld,
  1746. pwszKRADN,
  1747. TRUE,
  1748. 0,
  1749. pContainerSD,
  1750. &pwszError);
  1751. _JumpIfError(hr, error, "myLdapCreateContainer");
  1752. CSASSERT(NULL == pwszError);
  1753. hr = myLdapCreateUserObject(
  1754. pld,
  1755. pwszKRADN,
  1756. NULL,
  1757. 0,
  1758. pSD,
  1759. LPC_KRAOBJECT,
  1760. &dwDisp,
  1761. &pwszError);
  1762. //_JumpIfErrorStr(hr, error, "myLdapCreateUserObject", pwszKRADN);
  1763. _PrintIfErrorStr(hr, "myLdapCreateUserObject", pwszKRADN);
  1764. CSASSERT(S_OK == hr || NULL == pwszError);
  1765. hr = S_OK;
  1766. error:
  1767. CSILOG(hr, IDS_ILOG_CREATECDP, pwszCDPDN, pwszError, NULL);
  1768. if (NULL != pwszError)
  1769. {
  1770. LocalFree(pwszError);
  1771. }
  1772. for (i = 0; i < ARRAYSIZE(apwszOut); i++)
  1773. {
  1774. if (NULL != apwszOut[i])
  1775. {
  1776. LocalFree(apwszOut[i]);
  1777. }
  1778. }
  1779. if (NULL != strConfigDN)
  1780. {
  1781. SysFreeString(strConfigDN);
  1782. }
  1783. if (NULL != strDomainDN)
  1784. {
  1785. SysFreeString(strDomainDN);
  1786. }
  1787. if (NULL != pld)
  1788. {
  1789. ldap_unbind(pld);
  1790. }
  1791. return(hr);
  1792. }
  1793. HRESULT
  1794. CreateEnterpriseAndRootEntry(
  1795. IN WCHAR const *pwszSanitizedDSName,
  1796. IN CERT_CONTEXT const *pccPublish,
  1797. IN ENUM_CATYPES caType,
  1798. IN PSECURITY_DESCRIPTOR pSD,
  1799. IN PSECURITY_DESCRIPTOR pContainerSD)
  1800. {
  1801. HRESULT hr;
  1802. LDAP *pld = NULL;
  1803. BSTR strConfig = NULL;
  1804. BSTR strDomainDN = NULL;
  1805. WCHAR *pwszRootDN = NULL;
  1806. WCHAR *pwszEnterpriseDN = NULL;
  1807. PSECURITY_DESCRIPTOR pNTAuthSD = NULL;
  1808. DWORD cwc;
  1809. DWORD dwDisp;
  1810. WCHAR *pwszError = NULL;
  1811. if (!IsEnterpriseCA(caType) && !IsRootCA(caType))
  1812. {
  1813. hr = S_OK;
  1814. goto error;
  1815. }
  1816. hr = myRobustLdapBind(&pld, FALSE);
  1817. _JumpIfError(hr, error, "myRobustLdapBind");
  1818. hr = myGetAuthoritativeDomainDn(pld, &strDomainDN, &strConfig);
  1819. if (S_OK != hr)
  1820. {
  1821. hr = myHError(hr);
  1822. _JumpError(hr, error, "myGetAuthoritativeDomainDn");
  1823. }
  1824. cwc = WSZARRAYSIZE(L"CN=") +
  1825. wcslen(pwszSanitizedDSName) +
  1826. WSZARRAYSIZE(s_wszRootCAs) +
  1827. wcslen(strConfig);
  1828. pwszRootDN = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  1829. if (pwszRootDN == NULL)
  1830. {
  1831. hr = E_OUTOFMEMORY;
  1832. _JumpIfError(hr, error, "LocalAlloc");
  1833. }
  1834. wcscpy(pwszRootDN, L"CN=");
  1835. wcscat(pwszRootDN, pwszSanitizedDSName);
  1836. wcscat(pwszRootDN, s_wszRootCAs);
  1837. wcscat(pwszRootDN, strConfig);
  1838. CSASSERT(wcslen(pwszRootDN) == cwc);
  1839. cwc = wcslen(s_wszEnterpriseCAs) + wcslen(strConfig) ;
  1840. pwszEnterpriseDN = (WCHAR *) LocalAlloc(
  1841. LMEM_FIXED,
  1842. (cwc + 1) * sizeof(WCHAR));
  1843. if (pwszEnterpriseDN == NULL)
  1844. {
  1845. hr = E_OUTOFMEMORY;
  1846. _JumpIfError(hr, error, "LocalAlloc");
  1847. }
  1848. wcscpy(pwszEnterpriseDN, s_wszEnterpriseCAs);
  1849. wcscat(pwszEnterpriseDN, strConfig);
  1850. CSASSERT(wcslen(pwszEnterpriseDN) == cwc);
  1851. //+=====================================================================
  1852. // Create the root trust CA container and entry (Root only):
  1853. if (IsRootCA(caType))
  1854. {
  1855. DBGPRINT((DBG_SS_CERTLIBI, "Creating Services Containers: '%ws'\n", pwszRootDN));
  1856. hr = myLdapCreateContainer(
  1857. pld,
  1858. pwszRootDN,
  1859. TRUE,
  1860. 1,
  1861. pContainerSD,
  1862. &pwszError);
  1863. _JumpIfError(hr, error, "myLdapCreateContainer");
  1864. CSASSERT(NULL == pwszError);
  1865. DBGPRINT((DBG_SS_CERTLIBI, "Creating DS Root Trust: '%ws'\n", pwszRootDN));
  1866. hr = myLdapCreateCAObject(
  1867. pld,
  1868. pwszRootDN,
  1869. pccPublish->pbCertEncoded,
  1870. pccPublish->cbCertEncoded,
  1871. pSD,
  1872. &dwDisp,
  1873. &pwszError);
  1874. _JumpIfErrorStr(hr, error, "myLdapCreateCAObject", pwszRootDN);
  1875. }
  1876. //+=====================================================================
  1877. // Create the NTAuth trust entry (Enterprise only):
  1878. if (IsEnterpriseCA(caType))
  1879. {
  1880. DBGPRINT((
  1881. DBG_SS_CERTLIBI,
  1882. "Creating DS Enterprise Trust: '%ws'\n",
  1883. pwszEnterpriseDN));
  1884. hr = myGetSDFromTemplate(WSZ_DEFAULT_NTAUTH_SECURITY, NULL, &pNTAuthSD);
  1885. _JumpIfError(hr, error, "myGetSDFromTemplate");
  1886. hr = myLdapCreateCAObject(
  1887. pld,
  1888. pwszEnterpriseDN,
  1889. NULL,
  1890. 0,
  1891. pNTAuthSD,
  1892. &dwDisp,
  1893. &pwszError);
  1894. _JumpIfErrorStr(hr, error, "myLdapCreateCAObject", pwszEnterpriseDN);
  1895. hr = AddCertToAttribute(
  1896. pld,
  1897. pccPublish,
  1898. pwszEnterpriseDN,
  1899. wszDSCACERTATTRIBUTE,
  1900. &dwDisp,
  1901. &pwszError);
  1902. _JumpIfErrorStr(hr, error, "AddCertToAttribute", pwszEnterpriseDN);
  1903. CSILOG(S_OK, IDS_ILOG_CREATENTAUTHTRUST, pwszEnterpriseDN, NULL, NULL);
  1904. }
  1905. error:
  1906. CSILOG(hr, IDS_ILOG_CREATEROOTTRUST, pwszRootDN, pwszError, NULL);
  1907. if (NULL != pwszError)
  1908. {
  1909. LocalFree(pwszError);
  1910. }
  1911. if (NULL != pwszEnterpriseDN)
  1912. {
  1913. LocalFree(pwszEnterpriseDN);
  1914. }
  1915. if (NULL != pwszRootDN)
  1916. {
  1917. LocalFree(pwszRootDN);
  1918. }
  1919. if (NULL != strConfig)
  1920. {
  1921. SysFreeString(strConfig);
  1922. }
  1923. if (NULL != strDomainDN)
  1924. {
  1925. SysFreeString(strDomainDN);
  1926. }
  1927. if (NULL != pld)
  1928. {
  1929. ldap_unbind(pld);
  1930. }
  1931. if (NULL != pNTAuthSD)
  1932. {
  1933. LocalFree(pNTAuthSD);
  1934. }
  1935. return(hr);
  1936. }
  1937. #define wszCOLON L":"
  1938. // Suppress FILE URLs if a DS is available, as LDAP access within the
  1939. // enterprise should suffice, and http: should work outside the enterprise.
  1940. // Certs with too many URLs don't always fit on smart cards.
  1941. #define wszCRLPATHDEFAULT \
  1942. wszCERTENROLLSHAREPATH \
  1943. L"\\" \
  1944. wszFCSAPARM_SANITIZEDCANAME \
  1945. wszFCSAPARM_CRLFILENAMESUFFIX \
  1946. wszFCSAPARM_CRLDELTAFILENAMESUFFIX \
  1947. L".crl"
  1948. CSURLTEMPLATE const s_aRevURL[] = {
  1949. {
  1950. CSURL_SERVERPUBLISH | CSURL_ADDSYSTEM32DIR,
  1951. wszCRLPATHDEFAULT,
  1952. },
  1953. {
  1954. CSURL_SERVERPUBLISH | CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP | CSURL_DSONLY,
  1955. const_cast<WCHAR *>(g_wszzLDAPRevocationURLTemplate),
  1956. },
  1957. {
  1958. CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP,
  1959. const_cast<WCHAR *>(g_wszHTTPRevocationURLTemplate),
  1960. },
  1961. {
  1962. CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL | CSURL_ADDTOCRLCDP | CSURL_NODS,
  1963. const_cast<WCHAR *>(g_wszFILERevocationURLTemplate),
  1964. },
  1965. #if 0
  1966. {
  1967. CSURL_SERVERPUBLISH | CSURL_DSONLY,
  1968. const_cast<WCHAR *>(g_wszCDPDNTemplate),
  1969. },
  1970. #endif
  1971. { 0, NULL }
  1972. };
  1973. #define wszCACERTPATHDEFAULT \
  1974. wszCERTENROLLSHAREPATH \
  1975. L"\\" \
  1976. wszFCSAPARM_SERVERDNSNAME \
  1977. L"_" \
  1978. wszFCSAPARM_SANITIZEDCANAME \
  1979. wszFCSAPARM_CERTFILENAMESUFFIX \
  1980. L".crt"
  1981. CSURLTEMPLATE const s_aCACertURL[] = {
  1982. {
  1983. CSURL_SERVERPUBLISH | CSURL_ADDSYSTEM32DIR,
  1984. wszCACERTPATHDEFAULT,
  1985. },
  1986. {
  1987. CSURL_SERVERPUBLISH | CSURL_ADDTOCERTCDP | CSURL_DSONLY,
  1988. const_cast<WCHAR *>(g_wszzLDAPIssuerCertURLTemplate),
  1989. },
  1990. {
  1991. CSURL_ADDTOCERTCDP,
  1992. const_cast<WCHAR *>(g_wszHTTPIssuerCertURLTemplate),
  1993. },
  1994. {
  1995. CSURL_ADDTOCERTCDP | CSURL_NODS,
  1996. const_cast<WCHAR *>(g_wszFILEIssuerCertURLTemplate),
  1997. },
  1998. #if 0
  1999. {
  2000. CSURL_SERVERPUBLISH | CSURL_DSONLY,
  2001. const_cast<WCHAR *>(g_wszAIADNTemplate),
  2002. },
  2003. #endif
  2004. { 0, NULL }
  2005. };
  2006. #define CSURL_DSDEPENDENT (CSURL_SERVERPUBLISH | CSURL_ADDTOCERTCDP | CSURL_ADDTOFRESHESTCRL)
  2007. HRESULT
  2008. GetPublicationURLTemplates(
  2009. IN CSURLTEMPLATE const *aTemplate,
  2010. IN BOOL fUseDS,
  2011. IN WCHAR const *pwszSystem32,
  2012. OUT WCHAR **ppwszz)
  2013. {
  2014. HRESULT hr;
  2015. WCHAR *pwszz;
  2016. DWORD cwc;
  2017. CSURLTEMPLATE const *pTemplate;
  2018. WCHAR awc[22];
  2019. DWORD Flags;
  2020. *ppwszz = NULL;
  2021. cwc = 1; // final trailing L'\0'
  2022. for (pTemplate = aTemplate; NULL != pTemplate->pwszURL; pTemplate++)
  2023. {
  2024. Flags = ~CSURL_INITMASK & pTemplate->Flags;
  2025. if ((!fUseDS && (CSURL_DSONLY & pTemplate->Flags)) ||
  2026. (fUseDS && (CSURL_NODS & pTemplate->Flags)))
  2027. {
  2028. Flags &= ~CSURL_DSDEPENDENT;
  2029. }
  2030. cwc += wsprintf(awc, L"%u", Flags);
  2031. cwc += WSZARRAYSIZE(wszCOLON);
  2032. if (CSURL_ADDSYSTEM32DIR & pTemplate->Flags)
  2033. {
  2034. cwc += wcslen(pwszSystem32);
  2035. }
  2036. cwc += wcslen(pTemplate->pwszURL);
  2037. cwc += 1; // trailing L'\0'
  2038. }
  2039. pwszz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  2040. if (NULL == pwszz)
  2041. {
  2042. hr = E_OUTOFMEMORY;
  2043. _JumpError(hr, error, "LocalAlloc");
  2044. }
  2045. *ppwszz = pwszz;
  2046. for (pTemplate = aTemplate; NULL != pTemplate->pwszURL; pTemplate++)
  2047. {
  2048. Flags = ~CSURL_INITMASK & pTemplate->Flags;
  2049. if ((!fUseDS && (CSURL_DSONLY & pTemplate->Flags)) ||
  2050. (fUseDS && (CSURL_NODS & pTemplate->Flags)))
  2051. {
  2052. Flags &= ~CSURL_DSDEPENDENT;
  2053. }
  2054. DBGPRINT((
  2055. DBG_SS_CERTLIB,
  2056. "URL Template: %x %x:%ws\n",
  2057. Flags,
  2058. pTemplate->Flags,
  2059. pTemplate->pwszURL));
  2060. wsprintf(pwszz, L"%u", Flags);
  2061. wcscat(pwszz, wszCOLON);
  2062. if (CSURL_ADDSYSTEM32DIR & pTemplate->Flags)
  2063. {
  2064. wcscat(pwszz, pwszSystem32);
  2065. }
  2066. wcscat(pwszz, pTemplate->pwszURL);
  2067. pwszz += wcslen(pwszz) + 1; // skip L'\0'
  2068. }
  2069. *pwszz = L'\0';
  2070. CSASSERT(cwc == (DWORD) (pwszz - *ppwszz + 1));
  2071. #ifdef DBG_CERTSRV_DEBUG_PRINT
  2072. {
  2073. DWORD i = 0;
  2074. WCHAR const *pwsz;
  2075. for (pwsz = *ppwszz; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  2076. {
  2077. DBGPRINT((
  2078. DBG_SS_CERTLIB,
  2079. "URL Template[%u]: %ws\n",
  2080. i,
  2081. pwsz));
  2082. i++;
  2083. }
  2084. }
  2085. #endif // DBG_CERTSRV_DEBUG_PRINT
  2086. hr = S_OK;
  2087. error:
  2088. return(hr);
  2089. }
  2090. HRESULT
  2091. csiGetCRLPublicationURLTemplates(
  2092. IN BOOL fUseDS,
  2093. IN WCHAR const *pwszSystem32,
  2094. OUT WCHAR **ppwszz)
  2095. {
  2096. HRESULT hr;
  2097. hr = GetPublicationURLTemplates(s_aRevURL, fUseDS, pwszSystem32, ppwszz);
  2098. _JumpIfError(hr, error, "GetPublicationURLTemplates");
  2099. error:
  2100. return(hr);
  2101. }
  2102. HRESULT
  2103. csiGetCACertPublicationURLTemplates(
  2104. IN BOOL fUseDS,
  2105. IN WCHAR const *pwszSystem32,
  2106. OUT WCHAR **ppwszz)
  2107. {
  2108. HRESULT hr;
  2109. hr = GetPublicationURLTemplates(s_aCACertURL, fUseDS, pwszSystem32, ppwszz);
  2110. _JumpIfError(hr, error, "GetPublicationURLTemplates");
  2111. error:
  2112. return(hr);
  2113. }
  2114. HRESULT
  2115. csiSetupCAInDS(
  2116. IN HWND hwnd,
  2117. IN WCHAR const *pwszCAServer,
  2118. IN WCHAR const *pwszSanitizedCAName,
  2119. IN WCHAR const *pwszCADisplayName,
  2120. IN WCHAR const *pwszCADescription,
  2121. IN ENUM_CATYPES caType,
  2122. IN DWORD iCert,
  2123. IN DWORD iCRL,
  2124. IN BOOL fRenew,
  2125. IN CERT_CONTEXT const *pCert)
  2126. {
  2127. HRESULT hr;
  2128. HCAINFO hCAInfo = NULL;
  2129. WCHAR *pCAProp[2];
  2130. WCHAR *pCertSubjectString = NULL;
  2131. WCHAR wszNameBuffer[MAX_COMPUTER_DNS_NAME + 1];
  2132. DWORD cNameBuffer;
  2133. WCHAR wszDomainNameBuffer[MAX_PATH];
  2134. DWORD cDomainNameBuffer;
  2135. DWORD cbSid;
  2136. BYTE pSid[MAX_SID_LEN];
  2137. SID_NAME_USE SidUse;
  2138. WCHAR *pwszStringSid = NULL;
  2139. PSECURITY_DESCRIPTOR pContainerSD = NULL;
  2140. PSECURITY_DESCRIPTOR pCDPSD = NULL;
  2141. CERT_CONTEXT const *pCertForDS = NULL;
  2142. WCHAR *pwszSanitizedDSName = NULL;
  2143. hr = mySanitizedNameToDSName(pwszSanitizedCAName, &pwszSanitizedDSName);
  2144. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  2145. // Get the SID of the local machine.
  2146. cNameBuffer = ARRAYSIZE(wszNameBuffer);
  2147. if (!GetComputerObjectName(NameSamCompatible, wszNameBuffer, &cNameBuffer))
  2148. {
  2149. hr = myHLastError();
  2150. _JumpError(hr, error, "GetComputerObjectName");
  2151. }
  2152. DBGPRINT((DBG_SS_CERTLIB, "GetComputerObjectName: '%ws'\n", wszNameBuffer));
  2153. cbSid = sizeof(pSid);
  2154. cDomainNameBuffer = ARRAYSIZE(wszDomainNameBuffer);
  2155. if (!LookupAccountName(NULL,
  2156. wszNameBuffer,
  2157. pSid,
  2158. &cbSid,
  2159. wszDomainNameBuffer,
  2160. &cDomainNameBuffer,
  2161. &SidUse))
  2162. {
  2163. hr = myHLastError();
  2164. _JumpErrorStr(hr, error, "LookupAccountName", wszNameBuffer);
  2165. }
  2166. if (!myConvertSidToStringSid(pSid, &pwszStringSid))
  2167. {
  2168. hr = myHLastError();
  2169. _JumpError(hr, error, "myConvertSidToStringSid");
  2170. }
  2171. // get default DS CDP security descriptor
  2172. hr = myGetSDFromTemplate(WSZ_DEFAULT_CDP_DS_SECURITY,
  2173. pwszStringSid,
  2174. &pCDPSD);
  2175. _JumpIfError(hr, error, "myGetSDFromTemplate");
  2176. // get default DS AIA security descriptor
  2177. hr = myGetSDFromTemplate(WSZ_DEFAULT_CA_DS_SECURITY,
  2178. NULL,
  2179. &pContainerSD);
  2180. _JumpIfError(hr, error, "myGetSDFromTemplate");
  2181. hr = CreateEnterpriseAndRootEntry(
  2182. pwszSanitizedDSName,
  2183. pCert,
  2184. caType,
  2185. pContainerSD,
  2186. pContainerSD);
  2187. _JumpIfError(hr, error, "CreateEnterpriseAndRootEntry");
  2188. hr = CreateCDPAndAIAAndKRAEntry(
  2189. pwszSanitizedCAName,
  2190. pwszSanitizedDSName,
  2191. pwszCAServer,
  2192. iCert,
  2193. iCRL,
  2194. fRenew,
  2195. pCert->pbCertEncoded,
  2196. pCert->cbCertEncoded,
  2197. pCDPSD,
  2198. pContainerSD);
  2199. _JumpIfError(hr, error, "CreateCDPAndAIAAndKRAEntry");
  2200. // Add enterprise
  2201. // service publish entry
  2202. hr = CAFindByName(
  2203. pwszSanitizedDSName,
  2204. NULL,
  2205. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  2206. &hCAInfo);
  2207. if (S_OK != hr || NULL == hCAInfo)
  2208. {
  2209. hCAInfo = NULL;
  2210. fRenew = FALSE; // recreate security settings, etc.
  2211. hr = CACreateNewCA(pwszSanitizedDSName, NULL, NULL, &hCAInfo);
  2212. _JumpIfError(hr, error, "CACreateNewCA");
  2213. if (NULL == hCAInfo)
  2214. {
  2215. hr = E_INVALIDARG;
  2216. _JumpError(hr, error, "hCAInfo(NULL)");
  2217. }
  2218. }
  2219. if (!fRenew)
  2220. {
  2221. pCAProp[0] = const_cast<WCHAR *>(pwszCAServer);
  2222. pCAProp[1] = NULL;
  2223. hr = CASetCAProperty(hCAInfo, CA_PROP_DNSNAME, pCAProp);
  2224. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_DNSNAME)");
  2225. pCAProp[0] = const_cast<WCHAR *>(pwszCADisplayName);
  2226. pCAProp[1] = NULL;
  2227. hr = CASetCAProperty(hCAInfo, CA_PROP_DISPLAY_NAME, pCAProp);
  2228. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_DISPLAY_NAME)");
  2229. if (NULL != pwszCADescription)
  2230. {
  2231. pCAProp[0] = const_cast<WCHAR *>(pwszCADescription);
  2232. pCAProp[1] = NULL;
  2233. hr = CASetCAProperty(hCAInfo, CA_PROP_DESCRIPTION, pCAProp);
  2234. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_DESCRIPTION)");
  2235. }
  2236. hr = myCertNameToStr(
  2237. X509_ASN_ENCODING,
  2238. &pCert->pCertInfo->Subject,
  2239. CERT_X500_NAME_STR | CERT_NAME_STR_NO_QUOTING_FLAG,
  2240. &pCertSubjectString);
  2241. _JumpIfError(hr, error, "myCertNameToStr");
  2242. pCAProp[0] = pCertSubjectString;
  2243. pCAProp[1] = NULL;
  2244. hr = CASetCAProperty(hCAInfo, CA_PROP_CERT_DN, pCAProp);
  2245. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_CERT_DN)");
  2246. switch (caType)
  2247. {
  2248. case ENUM_ENTERPRISE_ROOTCA:
  2249. hr = CASetCAFlags(hCAInfo, CA_FLAG_SUPPORTS_NT_AUTHENTICATION);
  2250. _JumpIfError(hr, error, "CASetCAFlags");
  2251. break;
  2252. case ENUM_ENTERPRISE_SUBCA:
  2253. hr = CASetCAFlags(hCAInfo, CA_FLAG_SUPPORTS_NT_AUTHENTICATION);
  2254. _JumpIfError(hr, error, "CASetCAFlags");
  2255. break;
  2256. case ENUM_STANDALONE_ROOTCA:
  2257. hr = CASetCAFlags(hCAInfo, CA_FLAG_NO_TEMPLATE_SUPPORT | CA_FLAG_CA_SUPPORTS_MANUAL_AUTHENTICATION);
  2258. _JumpIfError(hr, error, "CASetCAFlags");
  2259. break;
  2260. case ENUM_STANDALONE_SUBCA:
  2261. hr = CASetCAFlags(hCAInfo, CA_FLAG_NO_TEMPLATE_SUPPORT | CA_FLAG_CA_SUPPORTS_MANUAL_AUTHENTICATION);
  2262. _JumpIfError(hr, error, "CASetCAFlags");
  2263. break;
  2264. default:
  2265. hr = E_INVALIDARG;
  2266. _JumpError(hr, error, "Invalid CA Type");
  2267. }
  2268. if (IsEnterpriseCA(caType))
  2269. {
  2270. hr = CASetCAProperty(
  2271. hCAInfo,
  2272. CA_PROP_CERT_TYPES,
  2273. FIsAdvancedServer()?
  2274. s_apwszCertTypeAdvancedServer :
  2275. s_apwszCertTypeServer);
  2276. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_CERT_TYPES)");
  2277. }
  2278. }
  2279. // create a new cert context without key prov info
  2280. pCertForDS = CertCreateCertificateContext(X509_ASN_ENCODING,
  2281. pCert->pbCertEncoded,
  2282. pCert->cbCertEncoded);
  2283. if (NULL == pCertForDS)
  2284. {
  2285. hr = myHLastError();
  2286. _JumpError(hr, error, "CertCreateCertificateContext");
  2287. }
  2288. hr = CASetCACertificate(hCAInfo, pCertForDS);
  2289. _JumpIfError(hr, error, "CASetCACertificate");
  2290. if (!fRenew)
  2291. {
  2292. hr = CASetCASecurity(hCAInfo, pCDPSD);
  2293. _JumpIfError(hr, error, "CASetCASecurity");
  2294. }
  2295. hr = CAUpdateCA(hCAInfo);
  2296. _JumpIfError(hr, error, "CAUpdateCA");
  2297. error:
  2298. if (NULL != pwszStringSid)
  2299. {
  2300. LocalFree(pwszStringSid);
  2301. }
  2302. if (NULL != pwszSanitizedDSName)
  2303. {
  2304. LocalFree(pwszSanitizedDSName);
  2305. }
  2306. if (NULL != pCertSubjectString)
  2307. {
  2308. LocalFree(pCertSubjectString);
  2309. }
  2310. if (NULL != hCAInfo)
  2311. {
  2312. CACloseCA(hCAInfo);
  2313. }
  2314. if (NULL != pCDPSD)
  2315. {
  2316. LocalFree(pCDPSD);
  2317. }
  2318. if (NULL != pContainerSD)
  2319. {
  2320. LocalFree(pContainerSD);
  2321. }
  2322. if (NULL != pCertForDS)
  2323. {
  2324. CertFreeCertificateContext(pCertForDS);
  2325. }
  2326. CSILOG(hr, IDS_ILOG_PUBLISHCA, NULL, NULL, NULL);
  2327. return(hr);
  2328. }
  2329. BOOL
  2330. csiIsAnyDSCAAvailable(VOID)
  2331. {
  2332. // this is an expensive call; cache result
  2333. static BOOL available = FALSE; // static inits to FALSE
  2334. static BOOL fKnowAvailable = FALSE; // static inits to FALSE
  2335. HCAINFO hCAInfo = NULL;
  2336. if (!fKnowAvailable)
  2337. {
  2338. HRESULT hr;
  2339. fKnowAvailable = TRUE;
  2340. hr = CAEnumFirstCA(
  2341. NULL,
  2342. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  2343. &hCAInfo);
  2344. _JumpIfError(hr, error, "CAEnumFirstCA");
  2345. if (NULL == hCAInfo)
  2346. {
  2347. goto error;
  2348. }
  2349. available = TRUE;
  2350. }
  2351. error:
  2352. if (NULL != hCAInfo)
  2353. CACloseCA(hCAInfo);
  2354. return available;
  2355. }
  2356. HRESULT
  2357. csiSetKeyContainerSecurity(
  2358. IN HCRYPTPROV hProv)
  2359. {
  2360. HRESULT hr;
  2361. PSECURITY_DESCRIPTOR pSD = NULL;
  2362. hr = myGetSDFromTemplate(WSZ_DEFAULT_KEYCONTAINER_SECURITY, NULL, &pSD);
  2363. _JumpIfError(hr, error, "myGetSDFromTemplate");
  2364. // apply the security descriptor to the key container
  2365. if (!CryptSetProvParam(
  2366. hProv,
  2367. PP_KEYSET_SEC_DESCR,
  2368. (BYTE *) pSD,
  2369. (DWORD) DACL_SECURITY_INFORMATION))
  2370. {
  2371. hr = myHLastError();
  2372. _JumpError(hr, error, "CryptSetProvParam");
  2373. }
  2374. hr = S_OK;
  2375. error:
  2376. if (NULL != pSD)
  2377. {
  2378. LocalFree(pSD);
  2379. }
  2380. CSILOG(hr, IDS_ILOG_SETKEYSECURITY, NULL, NULL, NULL);
  2381. return(hr);
  2382. }
  2383. HRESULT
  2384. csiSetAdminOnlyFolderSecurity(
  2385. IN LPCWSTR szFolderPath,
  2386. IN BOOL fAllowEveryoneRead,
  2387. IN BOOL fUseDS)
  2388. {
  2389. HRESULT hr;
  2390. PSECURITY_DESCRIPTOR pSD = NULL;
  2391. // choose which access we want to allow
  2392. LPCWSTR pwszDescriptor;
  2393. if (fUseDS)
  2394. if (fAllowEveryoneRead)
  2395. pwszDescriptor = WSZ_DEFAULT_SF_USEDS_EVERYONEREAD_SECURITY;
  2396. else
  2397. pwszDescriptor = WSZ_DEFAULT_SF_USEDS_SECURITY;
  2398. else
  2399. if (fAllowEveryoneRead)
  2400. pwszDescriptor = WSZ_DEFAULT_SF_EVERYONEREAD_SECURITY;
  2401. else
  2402. pwszDescriptor = WSZ_DEFAULT_SF_SECURITY;
  2403. hr = myGetSDFromTemplate(pwszDescriptor, NULL, &pSD);
  2404. _JumpIfError(hr, error, "myGetSDFromTemplate");
  2405. if (!SetFileSecurity(
  2406. szFolderPath,
  2407. DACL_SECURITY_INFORMATION,
  2408. pSD))
  2409. {
  2410. hr = myHLastError();
  2411. _JumpError(hr, error, "SetFileSecurity");
  2412. }
  2413. hr = S_OK;
  2414. error:
  2415. if (NULL != pSD)
  2416. {
  2417. LocalFree(pSD);
  2418. }
  2419. CSILOG(hr, IDS_ILOG_SETADMINONLYFOLDERSECURITY, szFolderPath, NULL, NULL);
  2420. return(hr);
  2421. }
  2422. HRESULT
  2423. csiSaveCertAndKeys(
  2424. IN CERT_CONTEXT const *pCert,
  2425. IN HCERTSTORE hAdditionalStore,
  2426. IN CRYPT_KEY_PROV_INFO const *pkpi,
  2427. IN ENUM_CATYPES CAType)
  2428. {
  2429. HRESULT hr;
  2430. DWORD i;
  2431. CERT_CHAIN_CONTEXT const *pCertChain = NULL;
  2432. CERT_CHAIN_PARA CertChainPara;
  2433. HCERTSTORE hNTAuthStore = NULL;
  2434. ZeroMemory(&CertChainPara, sizeof(CertChainPara));
  2435. CertChainPara.cbSize = sizeof(CertChainPara);
  2436. if (!CertGetCertificateChain(
  2437. HCCE_LOCAL_MACHINE,
  2438. pCert,
  2439. NULL,
  2440. hAdditionalStore,
  2441. &CertChainPara,
  2442. 0,
  2443. NULL,
  2444. &pCertChain))
  2445. {
  2446. hr = myHLastError();
  2447. _JumpError(hr, error, "CertGetCertificateChain");
  2448. }
  2449. // make sure there is at least 1 simple chain
  2450. if (0 == pCertChain->cChain)
  2451. {
  2452. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  2453. _JumpError(hr, error, "pCertChain->cChain");
  2454. }
  2455. hr = mySaveChainAndKeys(
  2456. pCertChain->rgpChain[0],
  2457. wszMY_CERTSTORE,
  2458. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  2459. pkpi,
  2460. NULL);
  2461. _JumpIfError(hr, error, "mySaveChainAndKeys");
  2462. if(ENUM_ENTERPRISE_ROOTCA==CAType)
  2463. {
  2464. hNTAuthStore = CertOpenStore(
  2465. CERT_STORE_PROV_SYSTEM_REGISTRY_W,
  2466. X509_ASN_ENCODING,
  2467. NULL, // hProv
  2468. CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE,
  2469. wszNTAUTH_CERTSTORE);
  2470. if (NULL == hNTAuthStore)
  2471. {
  2472. hr = myHLastError();
  2473. _JumpErrorStr(hr, error, "CertOpenStore", wszNTAUTH_CERTSTORE);
  2474. }
  2475. if (!CertAddEncodedCertificateToStore(
  2476. hNTAuthStore ,
  2477. X509_ASN_ENCODING,
  2478. pCert->pbCertEncoded,
  2479. pCert->cbCertEncoded,
  2480. CERT_STORE_ADD_REPLACE_EXISTING,
  2481. NULL))
  2482. {
  2483. hr = myHLastError();
  2484. _JumpError(hr, error, "CertAddEncodedCertificateToStore");
  2485. }
  2486. }
  2487. error:
  2488. if (pCertChain != NULL)
  2489. {
  2490. CertFreeCertificateChain(pCertChain);
  2491. }
  2492. if (NULL != hNTAuthStore)
  2493. {
  2494. CertCloseStore(hNTAuthStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2495. }
  2496. return(hr);
  2497. }
  2498. HRESULT
  2499. AddCertBlobToStore(
  2500. IN OUT HCERTSTORE hStore,
  2501. IN BYTE const *pb,
  2502. IN DWORD cb)
  2503. {
  2504. HRESULT hr;
  2505. CERT_CONTEXT const *pCert = NULL;
  2506. pCert = CertCreateCertificateContext(X509_ASN_ENCODING, pb, cb);
  2507. if (NULL == pCert)
  2508. {
  2509. hr = myHLastError();
  2510. _JumpError(hr, error, "CertCreateCertificateContext");
  2511. }
  2512. if (!CertAddCertificateContextToStore(
  2513. hStore,
  2514. pCert,
  2515. CERT_STORE_ADD_REPLACE_EXISTING,
  2516. NULL))
  2517. {
  2518. hr = myHLastError();
  2519. _JumpError(hr, error, "CertAddCertificateContextToStore");
  2520. }
  2521. hr = S_OK;
  2522. error:
  2523. if (NULL != pCert)
  2524. {
  2525. CertFreeCertificateContext(pCert);
  2526. }
  2527. return(hr);
  2528. }
  2529. HRESULT
  2530. LoadMissingCertBlob(
  2531. IN OUT HCERTSTORE hStore,
  2532. IN BYTE const *pb,
  2533. IN DWORD cb)
  2534. {
  2535. HRESULT hr;
  2536. BYTE *pbDecoded = NULL;
  2537. DWORD cbDecoded;
  2538. CERT_CONTEXT const *pCert = NULL;
  2539. HCERTSTORE hStorePKCS7 = NULL;
  2540. BOOL fTryPKCS7 = TRUE;
  2541. if (myDecodeObject(
  2542. X509_ASN_ENCODING,
  2543. X509_CERT_TO_BE_SIGNED,
  2544. pb,
  2545. cb,
  2546. CERTLIB_USE_LOCALALLOC,
  2547. (VOID **) &pbDecoded,
  2548. &cbDecoded))
  2549. {
  2550. hr = AddCertBlobToStore(hStore, pb, cb);
  2551. _JumpIfError(hr, error, "AddCertBlobToStore");
  2552. fTryPKCS7 = FALSE;
  2553. }
  2554. else
  2555. if (myDecodeObject(
  2556. X509_ASN_ENCODING,
  2557. PKCS_CONTENT_INFO_SEQUENCE_OF_ANY,
  2558. pb,
  2559. cb,
  2560. CERTLIB_USE_LOCALALLOC,
  2561. (VOID **) &pbDecoded,
  2562. &cbDecoded))
  2563. {
  2564. CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *pSeq;
  2565. DWORD iCert;
  2566. pSeq = (CRYPT_CONTENT_INFO_SEQUENCE_OF_ANY const *) pbDecoded;
  2567. if (0 == strcmp(szOID_NETSCAPE_CERT_SEQUENCE, pSeq->pszObjId))
  2568. {
  2569. fTryPKCS7 = FALSE;
  2570. for (iCert = 0; iCert < pSeq->cValue; iCert++)
  2571. {
  2572. hr = AddCertBlobToStore(
  2573. hStore,
  2574. pSeq->rgValue[iCert].pbData,
  2575. pSeq->rgValue[iCert].cbData);
  2576. _JumpIfError(hr, error, "AddCertBlobToStore");
  2577. }
  2578. }
  2579. }
  2580. if (fTryPKCS7)
  2581. {
  2582. CRYPT_DATA_BLOB blobPKCS7;
  2583. blobPKCS7.pbData = const_cast<BYTE *>(pb);
  2584. blobPKCS7.cbData = cb;
  2585. hStorePKCS7 = CertOpenStore(
  2586. CERT_STORE_PROV_PKCS7,
  2587. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  2588. NULL, // hCryptProv
  2589. 0, // dwFlags
  2590. &blobPKCS7);
  2591. if (NULL == hStorePKCS7)
  2592. {
  2593. hr = myHLastError();
  2594. _JumpError(hr, error, "CertOpenStore");
  2595. }
  2596. while (TRUE)
  2597. {
  2598. pCert = CertEnumCertificatesInStore(hStorePKCS7, pCert);
  2599. if (NULL == pCert)
  2600. {
  2601. break;
  2602. }
  2603. if (!CertAddCertificateContextToStore(
  2604. hStore,
  2605. pCert,
  2606. CERT_STORE_ADD_REPLACE_EXISTING,
  2607. NULL))
  2608. {
  2609. hr = myHLastError();
  2610. _JumpError(hr, error, "CertAddCertificateContextToStore");
  2611. }
  2612. }
  2613. }
  2614. hr = S_OK;
  2615. error:
  2616. if (NULL != pbDecoded)
  2617. {
  2618. LocalFree(pbDecoded);
  2619. }
  2620. if (NULL != pCert)
  2621. {
  2622. CertFreeCertificateContext(pCert);
  2623. }
  2624. if (NULL != hStorePKCS7)
  2625. {
  2626. CertCloseStore(hStorePKCS7, CERT_CLOSE_STORE_CHECK_FLAG);
  2627. }
  2628. return(hr);
  2629. }
  2630. HRESULT
  2631. LoadMissingCert(
  2632. IN HINSTANCE hInstance,
  2633. IN HWND hwnd,
  2634. IN OUT HCERTSTORE hStore,
  2635. IN OPTIONAL WCHAR const *pwszMissingIssuer)
  2636. {
  2637. HRESULT hr;
  2638. WCHAR *pwszFile = NULL;
  2639. BYTE *pb = NULL;
  2640. DWORD cb;
  2641. hr = myGetOpenFileNameEx(
  2642. hwnd,
  2643. hInstance,
  2644. IDS_CAHIER_INSTALL_MISIINGCERT_TITLE,
  2645. pwszMissingIssuer,
  2646. IDS_CAHIER_CERTFILE_FILTER,
  2647. 0, // no def ext
  2648. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY,
  2649. NULL, // no default file
  2650. &pwszFile);
  2651. if (S_OK == hr && NULL == pwszFile)
  2652. {
  2653. hr = E_INVALIDARG;
  2654. }
  2655. _JumpIfError(hr, error, "myGetOpenFileName");
  2656. hr = DecodeFileW(pwszFile, &pb, &cb, CRYPT_STRING_ANY);
  2657. _JumpIfError(hr, error, "DecodeFileW");
  2658. hr = LoadMissingCertBlob(hStore, pb, cb);
  2659. _JumpIfError(hr, error, "LoadMissingCertBlob");
  2660. error:
  2661. if (NULL != pb)
  2662. {
  2663. LocalFree(pb);
  2664. }
  2665. if (NULL != pwszFile)
  2666. {
  2667. LocalFree(pwszFile);
  2668. }
  2669. return(hr);
  2670. }
  2671. HRESULT
  2672. InstallCAChain(
  2673. IN HINSTANCE hInstance,
  2674. IN BOOL fUnattended,
  2675. IN HWND hwnd,
  2676. IN PCCERT_CONTEXT pCert,
  2677. IN CRYPT_KEY_PROV_INFO const *pKeyProvInfo,
  2678. IN ENUM_CATYPES CAType,
  2679. OPTIONAL IN BYTE const *pbChain,
  2680. IN DWORD cbChain)
  2681. {
  2682. HRESULT hr;
  2683. WCHAR *pwszMissingIssuer = NULL;
  2684. HCERTSTORE hTempMemoryStore = NULL;
  2685. if (IsSubordinateCA(CAType))
  2686. {
  2687. hTempMemoryStore = CertOpenStore(
  2688. CERT_STORE_PROV_MEMORY,
  2689. X509_ASN_ENCODING,
  2690. NULL,
  2691. 0,
  2692. NULL);
  2693. if (NULL == hTempMemoryStore)
  2694. {
  2695. hr = myHLastError();
  2696. _JumpError(hr, error, "CertOpenSystemStore");
  2697. }
  2698. if (NULL != pbChain)
  2699. {
  2700. hr = LoadMissingCertBlob(hTempMemoryStore, pbChain, cbChain);
  2701. _JumpIfError(hr, error, "LoadMissingCertBlob");
  2702. }
  2703. // see if CA chain can be built
  2704. while (TRUE)
  2705. {
  2706. if (NULL != pwszMissingIssuer)
  2707. {
  2708. LocalFree(pwszMissingIssuer);
  2709. pwszMissingIssuer = NULL;
  2710. }
  2711. hr = myVerifyCertContext(
  2712. pCert, // pCert
  2713. 0, // dwFlags
  2714. 0, // cUsageOids
  2715. NULL, // apszUsageOids
  2716. HCCE_LOCAL_MACHINE, // hChainEngine
  2717. hTempMemoryStore, // hAdditionalStore
  2718. &pwszMissingIssuer);
  2719. if (S_OK != hr)
  2720. {
  2721. if (NULL != pwszMissingIssuer)
  2722. {
  2723. if (IDCANCEL == CertMessageBox(
  2724. hInstance,
  2725. fUnattended,
  2726. hwnd,
  2727. IDS_ERR_INCOMPLETECHAIN,
  2728. hr,
  2729. MB_OKCANCEL | MB_ICONWARNING,
  2730. pwszMissingIssuer) ||
  2731. fUnattended)
  2732. {
  2733. _JumpError(hr, error, "cannot build CA chain");
  2734. }
  2735. hr = LoadMissingCert(
  2736. hInstance,
  2737. hwnd,
  2738. hTempMemoryStore,
  2739. pwszMissingIssuer);
  2740. _PrintIfError(hr, "LoadMissingCert");
  2741. continue;
  2742. }
  2743. else
  2744. {
  2745. // recommend not continue
  2746. if (IDCANCEL == CertMessageBox(
  2747. hInstance,
  2748. fUnattended,
  2749. hwnd,
  2750. CERT_E_UNTRUSTEDROOT == hr?
  2751. IDS_ERR_UNTRUSTEDROOT :
  2752. IDS_ERR_INVALIDCHAIN,
  2753. hr,
  2754. MB_OKCANCEL | MB_ICONWARNING,
  2755. NULL))
  2756. {
  2757. _JumpError(hr, error, "cannot verify CA chain");
  2758. }
  2759. break;
  2760. }
  2761. }
  2762. break;
  2763. }
  2764. }
  2765. hr = csiSaveCertAndKeys(pCert, hTempMemoryStore, pKeyProvInfo, CAType);
  2766. if (S_OK != hr)
  2767. {
  2768. CertErrorMessageBox(
  2769. hInstance,
  2770. fUnattended,
  2771. hwnd,
  2772. IDS_ERR_CERTADDCERTIFICATECONTEXTTOSTORE,
  2773. hr,
  2774. NULL);
  2775. _JumpError(hr, error, "csiSaveCertAndKeys");
  2776. }
  2777. error:
  2778. if (NULL != pwszMissingIssuer)
  2779. {
  2780. LocalFree(pwszMissingIssuer);
  2781. }
  2782. if (NULL != hTempMemoryStore)
  2783. {
  2784. CertCloseStore(hTempMemoryStore, CERT_CLOSE_STORE_CHECK_FLAG);
  2785. }
  2786. return(hr);
  2787. }
  2788. HRESULT
  2789. BuildCAChainFromCert(
  2790. IN HINSTANCE hInstance,
  2791. IN BOOL fUnattended,
  2792. IN HWND hwnd,
  2793. IN CRYPT_KEY_PROV_INFO const *pKeyProvInfo,
  2794. IN WCHAR const *pwszCommonName,
  2795. IN const ENUM_CATYPES CAType,
  2796. OPTIONAL IN BYTE const *pbChain,
  2797. IN DWORD cbChain,
  2798. IN CERT_CONTEXT const *pCert)
  2799. {
  2800. HRESULT hr;
  2801. CERT_NAME_INFO *pNameInfo = NULL;
  2802. DWORD cbNameInfo;
  2803. WCHAR const *pwszCN;
  2804. // make sure the cert file matches current ca name
  2805. if (!myDecodeName(
  2806. X509_ASN_ENCODING,
  2807. X509_UNICODE_NAME,
  2808. pCert->pCertInfo->Subject.pbData,
  2809. pCert->pCertInfo->Subject.cbData,
  2810. CERTLIB_USE_LOCALALLOC,
  2811. &pNameInfo,
  2812. &cbNameInfo))
  2813. {
  2814. hr = myHLastError();
  2815. CertErrorMessageBox(
  2816. hInstance,
  2817. fUnattended,
  2818. hwnd,
  2819. IDS_ERR_MYDECODENAME,
  2820. hr,
  2821. NULL);
  2822. _JumpError(hr, error, "myDecodeName");
  2823. }
  2824. hr = myGetCertNameProperty(pNameInfo, szOID_COMMON_NAME, &pwszCN);
  2825. _PrintIfError(hr, "myGetCertNameProperty");
  2826. if (S_OK == hr && 0 != lstrcmp(pwszCommonName, pwszCN))
  2827. {
  2828. hr = E_INVALIDARG;
  2829. }
  2830. if (S_OK != hr)
  2831. {
  2832. CertErrorMessageBox(
  2833. hInstance,
  2834. fUnattended,
  2835. hwnd,
  2836. IDS_ERR_NOT_MATCH_NAME,
  2837. hr,
  2838. NULL);
  2839. _JumpError(hr, error, "common name in cert not match");
  2840. }
  2841. hr = IsCACert(hInstance, fUnattended, hwnd, pCert);
  2842. _JumpIfError(hr, error, "IsCACert");
  2843. hr = InstallCAChain(
  2844. hInstance,
  2845. fUnattended,
  2846. hwnd,
  2847. pCert,
  2848. pKeyProvInfo,
  2849. CAType,
  2850. pbChain,
  2851. cbChain);
  2852. _JumpIfError(hr, error, "InstallCAChain");
  2853. error:
  2854. if (NULL != pNameInfo)
  2855. {
  2856. LocalFree(pNameInfo);
  2857. }
  2858. CSILOG(hr, IDS_ILOG_SAVECERTANDKEYS, NULL, NULL, NULL);
  2859. return(hr);
  2860. }
  2861. HRESULT
  2862. csiFinishInstallationFromPKCS7(
  2863. IN HINSTANCE hInstance,
  2864. IN BOOL fUnattended,
  2865. IN HWND hwnd,
  2866. IN WCHAR const *pwszSanitizedCAName,
  2867. IN WCHAR const *pwszCACommonName,
  2868. IN CRYPT_KEY_PROV_INFO const *pKeyProvInfo,
  2869. IN ENUM_CATYPES CAType,
  2870. IN DWORD iCert,
  2871. IN DWORD iCRL,
  2872. IN BOOL fUseDS,
  2873. IN BOOL fRenew,
  2874. IN WCHAR const *pwszServerName,
  2875. IN BYTE const *pbChainOrCert,
  2876. IN DWORD cbChainOrCert,
  2877. OPTIONAL IN WCHAR const *pwszCACertFile)
  2878. {
  2879. HRESULT hr;
  2880. CERT_CONTEXT const *pCert = NULL;
  2881. WCHAR *pwszWebCACertFile = NULL;
  2882. WCHAR *pwszKeyContainer = NULL;
  2883. WCHAR wszTemp[MAX_PATH];
  2884. WCHAR wszBuffer[MAX_PATH];
  2885. DWORD NameId;
  2886. WCHAR *pwszRequestFile = NULL;
  2887. hr = E_FAIL;
  2888. if (!IsRootCA(CAType)) // skip PKCS7 code for known raw X509 root cert
  2889. {
  2890. hr = ExtractCACertFromPKCS7(
  2891. pwszCACommonName,
  2892. pbChainOrCert,
  2893. cbChainOrCert,
  2894. &pCert);
  2895. _PrintIfError(hr, "ExtractCACertFromPKCS7");
  2896. }
  2897. if (NULL == pCert)
  2898. {
  2899. pCert = CertCreateCertificateContext(
  2900. X509_ASN_ENCODING,
  2901. pbChainOrCert,
  2902. cbChainOrCert);
  2903. if (NULL == pCert)
  2904. {
  2905. hr = myHLastError();
  2906. CertErrorMessageBox(
  2907. hInstance,
  2908. fUnattended,
  2909. hwnd,
  2910. IDS_ERR_CERTCREATECERTIFICATECONTEXT,
  2911. hr,
  2912. NULL);
  2913. _JumpError(hr, error, "CertCreateCertificateContext");
  2914. }
  2915. pbChainOrCert = NULL; // Don't need to process this cert any further
  2916. }
  2917. hr = myGetNameId(pCert, &NameId);
  2918. _PrintIfError(hr, "myGetNameId");
  2919. if (S_OK == hr && MAKECANAMEID(iCert, iCRL) != NameId)
  2920. {
  2921. // get request file name
  2922. hr = csiGetCARequestFileName(
  2923. hInstance,
  2924. hwnd,
  2925. pwszSanitizedCAName,
  2926. iCert,
  2927. iCRL,
  2928. &pwszRequestFile);
  2929. _PrintIfError(hr, "csiGetCARequestFileName");
  2930. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2931. CertErrorMessageBox(
  2932. hInstance,
  2933. fUnattended,
  2934. hwnd,
  2935. IDS_ERR_RENEWEDCERTCAVERSION,
  2936. hr,
  2937. pwszRequestFile);
  2938. _JumpError(hr, error, "CA Version");
  2939. }
  2940. // build a chain and install it
  2941. hr = BuildCAChainFromCert(
  2942. hInstance,
  2943. fUnattended,
  2944. hwnd,
  2945. pKeyProvInfo,
  2946. pwszCACommonName,
  2947. CAType,
  2948. pbChainOrCert,
  2949. cbChainOrCert,
  2950. pCert);
  2951. _JumpIfError(hr, error, "BuildCAChainFromCert");
  2952. if (fUseDS)
  2953. {
  2954. // save in ds
  2955. hr = csiSetupCAInDS(
  2956. hwnd,
  2957. pwszServerName,
  2958. pwszSanitizedCAName,
  2959. pwszCACommonName,
  2960. NULL, // pwszCADescription
  2961. CAType,
  2962. iCert,
  2963. iCRL,
  2964. fRenew,
  2965. pCert);
  2966. _JumpIfError(hr, error, "csiSetupCAInDS");
  2967. }
  2968. // store CA cert hash
  2969. hr = mySetCARegHash(pwszSanitizedCAName, CSRH_CASIGCERT, iCert, pCert);
  2970. _JumpIfError(hr, error, "mySetCARegHash");
  2971. if (NULL != pwszCACertFile)
  2972. {
  2973. // write this CA cert into shared folder
  2974. if (!DeleteFile(pwszCACertFile))
  2975. {
  2976. hr = myHLastError();
  2977. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  2978. {
  2979. _JumpError(hr, error, "DeleteFile");
  2980. }
  2981. }
  2982. if (!csiWriteDERToFile(
  2983. pwszCACertFile,
  2984. (BYTE *) pCert->pbCertEncoded,
  2985. pCert->cbCertEncoded,
  2986. hInstance,
  2987. fUnattended,
  2988. hwnd))
  2989. {
  2990. hr = myHLastError();
  2991. _JumpError(hr, error, "csiWriteDERToFile");
  2992. }
  2993. }
  2994. // write cert file for web pages
  2995. if (0 == GetEnvironmentVariable(L"SystemRoot", wszTemp, MAX_PATH))
  2996. {
  2997. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  2998. CertErrorMessageBox(
  2999. hInstance,
  3000. fUnattended,
  3001. hwnd,
  3002. IDS_ERR_ENV_NOT_SET,
  3003. hr,
  3004. NULL);
  3005. _JumpError(hr, error, "GetEnvironmentVariable");
  3006. }
  3007. if(ARRAYSIZE(wszBuffer)<wcslen(wszTemp)+wcslen(L"\\System32\\")+
  3008. wcslen(wszCERTENROLLSHAREPATH)+1)
  3009. {
  3010. hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  3011. _JumpError(hr, error, "file name too long");
  3012. }
  3013. wcscpy(wszBuffer, wszTemp);
  3014. wcscat(wszBuffer, L"\\System32\\" wszCERTENROLLSHAREPATH);
  3015. hr = csiBuildFileName(
  3016. wszBuffer,
  3017. pwszSanitizedCAName,
  3018. L".crt",
  3019. iCert,
  3020. &pwszWebCACertFile,
  3021. hInstance,
  3022. fUnattended,
  3023. NULL);
  3024. _JumpIfError(hr, error, "csiBuildFileName");
  3025. hr = EncodeToFileW(
  3026. pwszWebCACertFile,
  3027. pCert->pbCertEncoded,
  3028. pCert->cbCertEncoded,
  3029. DECF_FORCEOVERWRITE | CRYPT_STRING_BINARY);
  3030. if (S_OK != hr)
  3031. {
  3032. CertErrorMessageBox(
  3033. hInstance,
  3034. fUnattended,
  3035. hwnd,
  3036. IDS_ERR_WRITEDERTOFILE,
  3037. hr,
  3038. pwszWebCACertFile);
  3039. _JumpError(hr, error, "EncodeToFileW");
  3040. }
  3041. // Set the security on the ds/registry/files etc.
  3042. if (!fRenew)
  3043. {
  3044. hr = myAllocIndexedName(
  3045. pwszSanitizedCAName,
  3046. iCRL,
  3047. &pwszKeyContainer);
  3048. _JumpIfError(hr, error, "myAllocIndexedName");
  3049. hr = csiInitializeCertSrvSecurity(
  3050. pwszSanitizedCAName,
  3051. fUseDS,
  3052. fUseDS); // set DS security if using DS
  3053. _JumpIfError(hr, error, "csiInitializeCertSrvSecurity");
  3054. }
  3055. error:
  3056. if (NULL != pCert)
  3057. {
  3058. CertFreeCertificateContext(pCert);
  3059. }
  3060. if (NULL != pwszRequestFile)
  3061. {
  3062. LocalFree(pwszRequestFile);
  3063. }
  3064. if (NULL != pwszKeyContainer)
  3065. {
  3066. LocalFree(pwszKeyContainer);
  3067. }
  3068. if (NULL != pwszWebCACertFile)
  3069. {
  3070. LocalFree(pwszWebCACertFile);
  3071. }
  3072. return(hr);
  3073. }
  3074. HRESULT
  3075. FormRequestHelpMessage(
  3076. IN HINSTANCE hInstance,
  3077. IN BOOL fUnattended,
  3078. IN HWND hwnd,
  3079. IN LONG lRequestId,
  3080. IN BSTR bStrMsgFromServer,
  3081. IN WCHAR const *pwszParentConfig,
  3082. OUT WCHAR **ppwszHelpMsg)
  3083. {
  3084. #define wszHELPNEWLINE L"\n"
  3085. #define wszCOMMASPACE L", "
  3086. HRESULT hr;
  3087. WCHAR wszRequestIdValue[16];
  3088. WCHAR *pwszMsgConfigPrefix = NULL;
  3089. WCHAR *pwszMsgRequestIdPrefix = NULL;
  3090. WCHAR *pwszHelpMsg = NULL;
  3091. DWORD cwc;
  3092. *ppwszHelpMsg = NULL;
  3093. // load some format strings in help msg
  3094. hr = myLoadRCString(hInstance, IDS_MSG_PARENTCA_CONFIG, &pwszMsgConfigPrefix);
  3095. _JumpIfError(hr, error, "myLoadRCString");
  3096. hr = myLoadRCString(hInstance, IDS_MSG_REQUEST_ID, &pwszMsgRequestIdPrefix);
  3097. _JumpIfError(hr, error, "myLoadRCString");
  3098. swprintf(wszRequestIdValue, L"%ld", lRequestId);
  3099. cwc = wcslen(pwszMsgConfigPrefix) +
  3100. wcslen(pwszParentConfig) +
  3101. WSZARRAYSIZE(wszCOMMASPACE) +
  3102. wcslen(pwszMsgRequestIdPrefix) +
  3103. wcslen(wszRequestIdValue) +
  3104. 1;
  3105. if (NULL != bStrMsgFromServer)
  3106. {
  3107. cwc += SysStringLen(bStrMsgFromServer) + WSZARRAYSIZE(wszHELPNEWLINE);
  3108. }
  3109. pwszHelpMsg = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  3110. if (NULL == pwszHelpMsg)
  3111. {
  3112. hr = E_OUTOFMEMORY;
  3113. _JumpError(hr, error, "LocalAlloc");
  3114. }
  3115. // form help message
  3116. pwszHelpMsg[0] = L'\0';
  3117. if (NULL != bStrMsgFromServer)
  3118. {
  3119. wcscpy(pwszHelpMsg, bStrMsgFromServer);
  3120. wcscat(pwszHelpMsg, wszHELPNEWLINE);
  3121. }
  3122. wcscat(pwszHelpMsg, pwszMsgConfigPrefix);
  3123. wcscat(pwszHelpMsg, pwszParentConfig);
  3124. wcscat(pwszHelpMsg, wszCOMMASPACE);
  3125. wcscat(pwszHelpMsg, pwszMsgRequestIdPrefix);
  3126. wcscat(pwszHelpMsg, wszRequestIdValue);
  3127. CSASSERT(wcslen(pwszHelpMsg) + 1 == cwc);
  3128. *ppwszHelpMsg = pwszHelpMsg;
  3129. pwszHelpMsg = NULL;
  3130. hr = S_OK;
  3131. error:
  3132. if (NULL != pwszMsgConfigPrefix)
  3133. {
  3134. LocalFree(pwszMsgConfigPrefix);
  3135. }
  3136. if (NULL != pwszMsgRequestIdPrefix)
  3137. {
  3138. LocalFree(pwszMsgRequestIdPrefix);
  3139. }
  3140. if (NULL != pwszHelpMsg)
  3141. {
  3142. LocalFree(pwszHelpMsg);
  3143. }
  3144. return(hr);
  3145. }
  3146. HRESULT
  3147. HandleSubmitOrRetrieveNotIssued(
  3148. IN HWND hwnd,
  3149. IN HINSTANCE hInstance,
  3150. IN BOOL fUnattended,
  3151. IN WCHAR const *pwszSanitizedCAName,
  3152. IN WCHAR const *pwszParentCAConfig,
  3153. IN ICertRequest *pICertRequest,
  3154. IN LONG disposition,
  3155. IN BSTR strDispositionMessage,
  3156. IN BOOL fRenew,
  3157. IN LONG requestId,
  3158. IN HRESULT hrSubmit,
  3159. IN HRESULT hrLastStatus,
  3160. IN int iMsgId)
  3161. {
  3162. HRESULT hr;
  3163. WCHAR *pwszHelpMsg = NULL;
  3164. DWORD dwStatusDisable;
  3165. DWORD dwStatusEnable;
  3166. BOOL fPopup = FALSE;
  3167. CSASSERT(NULL != pICertRequest);
  3168. // form custom message
  3169. hr = FormRequestHelpMessage(
  3170. hInstance,
  3171. fUnattended,
  3172. hwnd,
  3173. requestId,
  3174. strDispositionMessage,
  3175. pwszParentCAConfig,
  3176. &pwszHelpMsg);
  3177. _JumpIfError(hr, error, "FromRequestHelpMessage");
  3178. // Assume suspended install, denied request:
  3179. dwStatusEnable = SETUP_DENIED_FLAG | SETUP_REQUEST_FLAG;
  3180. if (!fRenew)
  3181. {
  3182. dwStatusEnable |= SETUP_SUSPEND_FLAG;
  3183. }
  3184. // Assume the pending request is denied, don't use online parent any more
  3185. dwStatusDisable = SETUP_ONLINE_FLAG;
  3186. // now handle disposition
  3187. switch (disposition)
  3188. {
  3189. case CR_DISP_UNDER_SUBMISSION:
  3190. // the online request is pending, not denied
  3191. dwStatusEnable &= ~SETUP_DENIED_FLAG;
  3192. dwStatusEnable |= SETUP_ONLINE_FLAG;
  3193. // online is still enabled
  3194. dwStatusDisable &= ~SETUP_ONLINE_FLAG;
  3195. iMsgId = IDS_ERR_REQUEST_PENDING;
  3196. break;
  3197. case CR_DISP_DENIED:
  3198. // request id is no good any more
  3199. hr = myDeleteCertRegValue(
  3200. pwszSanitizedCAName,
  3201. NULL,
  3202. NULL,
  3203. wszREGREQUESTID);
  3204. _PrintIfErrorStr(hr, "myDeleteCertRegValue", wszREGREQUESTID);
  3205. if (0 == iMsgId)
  3206. {
  3207. iMsgId = IDS_ERR_REQUEST_DENIED;
  3208. }
  3209. break;
  3210. case CR_DISP_INCOMPLETE:
  3211. iMsgId = IDS_ERR_REQUEST_INCOMPLETE;
  3212. break;
  3213. case CR_DISP_ERROR:
  3214. iMsgId = IDS_ERR_REQUEST_ERROR;
  3215. break;
  3216. case CR_DISP_ISSUED_OUT_OF_BAND:
  3217. // same as pending request, but not denied
  3218. dwStatusEnable &= ~SETUP_DENIED_FLAG;
  3219. iMsgId = IDS_ERR_REQUEST_OUTOFBAND;
  3220. break;
  3221. case CR_DISP_REVOKED:
  3222. iMsgId = IDS_ERR_REQUEST_REVOKED;
  3223. break;
  3224. default:
  3225. hr = E_INVALIDARG;
  3226. _JumpError(hr, error, "Internal error");
  3227. }
  3228. if (0 != dwStatusDisable)
  3229. {
  3230. // fix status, unset
  3231. hr = SetSetupStatus(pwszSanitizedCAName, dwStatusDisable, FALSE);
  3232. _JumpIfError(hr, error, "SetSetupStatus");
  3233. }
  3234. if (0 != dwStatusEnable)
  3235. {
  3236. // fix status, set
  3237. hr = SetSetupStatus(pwszSanitizedCAName, dwStatusEnable, TRUE);
  3238. _JumpIfError(hr, error, "SetSetupStatus");
  3239. }
  3240. // pop up a warning for generic error
  3241. CertWarningMessageBox(
  3242. hInstance,
  3243. fUnattended,
  3244. hwnd,
  3245. iMsgId,
  3246. hrLastStatus,
  3247. pwszHelpMsg);
  3248. fPopup = TRUE;
  3249. // use proper error code
  3250. if (S_OK == hrSubmit)
  3251. {
  3252. // for any disposition, use not ready as error
  3253. hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
  3254. }
  3255. else
  3256. {
  3257. // use submit error
  3258. hr = hrSubmit;
  3259. }
  3260. // note, never return S_OK
  3261. error:
  3262. if (!fPopup)
  3263. {
  3264. // a generic one because we won't have any popup later
  3265. CertWarningMessageBox(
  3266. hInstance,
  3267. fUnattended,
  3268. hwnd,
  3269. IDS_ERR_SUBMIT_REQUEST_FAIL,
  3270. hr,
  3271. L"");
  3272. }
  3273. if (NULL != pwszHelpMsg)
  3274. {
  3275. LocalFree(pwszHelpMsg);
  3276. }
  3277. CSILOG(hr, IDS_ILOG_RETRIEVECERT, NULL, NULL, NULL);
  3278. return(hr);
  3279. }
  3280. HRESULT
  3281. csiSubmitCARequest(
  3282. IN HINSTANCE hInstance,
  3283. IN BOOL fUnattended,
  3284. IN HWND hwnd,
  3285. IN BOOL fRenew,
  3286. IN BOOL fRetrievePending,
  3287. IN WCHAR const *pwszSanitizedCAName,
  3288. IN WCHAR const *pwszParentCAMachine,
  3289. IN WCHAR const *pwszParentCAName,
  3290. IN BYTE const *pbRequest,
  3291. IN DWORD cbRequest,
  3292. OUT BSTR *pbStrChain)
  3293. {
  3294. HRESULT hr;
  3295. HRESULT hrSubmit;
  3296. HRESULT hrLastStatus;
  3297. WCHAR *pwszParentCAConfig = NULL;
  3298. LONG disposition = CR_DISP_INCOMPLETE;
  3299. LONG requestId = 0;
  3300. int iMsgId;
  3301. ICertRequest *pICertRequest = NULL;
  3302. BOOL fCoInit = FALSE;
  3303. BSTR bstrConfig = NULL;
  3304. BSTR bstrRequest = NULL;
  3305. BSTR strDispositionMessage = NULL;
  3306. // register parent ca config
  3307. hr = mySetCertRegStrValue(
  3308. pwszSanitizedCAName,
  3309. NULL,
  3310. NULL,
  3311. wszREGPARENTCAMACHINE,
  3312. pwszParentCAMachine);
  3313. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", wszREGPARENTCAMACHINE);
  3314. hr = mySetCertRegStrValue(
  3315. pwszSanitizedCAName,
  3316. NULL,
  3317. NULL,
  3318. wszREGPARENTCANAME,
  3319. pwszParentCAName);
  3320. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", wszREGPARENTCANAME);
  3321. if (fRetrievePending)
  3322. {
  3323. // get request id
  3324. hr = myGetCertRegDWValue(
  3325. pwszSanitizedCAName,
  3326. NULL,
  3327. NULL,
  3328. wszREGREQUESTID,
  3329. (DWORD *) &requestId);
  3330. if (S_OK != hr)
  3331. {
  3332. fRetrievePending = FALSE;
  3333. requestId = 0;
  3334. }
  3335. }
  3336. hr = CoInitialize(NULL);
  3337. if (S_OK != hr && S_FALSE != hr)
  3338. {
  3339. _JumpError(hr, error, "CoInitialize");
  3340. }
  3341. fCoInit = TRUE;
  3342. hr = CoCreateInstance(
  3343. CLSID_CCertRequest,
  3344. NULL,
  3345. CLSCTX_INPROC_SERVER,
  3346. IID_ICertRequest,
  3347. (VOID **) &pICertRequest);
  3348. _JumpIfError(hr, error, "CoCreateInstance");
  3349. // get config string
  3350. hr = myFormConfigString(
  3351. pwszParentCAMachine,
  3352. pwszParentCAName,
  3353. &pwszParentCAConfig);
  3354. _JumpIfError(hr, error, "myFormConfigString");
  3355. // to bstr
  3356. bstrConfig = SysAllocString(pwszParentCAConfig);
  3357. if (NULL == bstrConfig)
  3358. {
  3359. hr = E_OUTOFMEMORY;
  3360. _JumpError(hr, error, "LocalAlloc");
  3361. }
  3362. // request to bstr
  3363. bstrRequest = SysAllocStringByteLen((CHAR *) pbRequest, cbRequest);
  3364. if (NULL == bstrRequest)
  3365. {
  3366. hr = E_OUTOFMEMORY;
  3367. _JumpError(hr, error, "LocalAlloc");
  3368. }
  3369. myDeleteCertRegValue(pwszSanitizedCAName, NULL, NULL, wszREGREQUESTID);
  3370. {
  3371. CWaitCursor cwait;
  3372. if (fRetrievePending)
  3373. {
  3374. // retrieve the request
  3375. hr = pICertRequest->RetrievePending(
  3376. requestId,
  3377. bstrConfig,
  3378. &disposition);
  3379. }
  3380. else
  3381. {
  3382. hr = pICertRequest->Submit(
  3383. CR_IN_BINARY | CR_IN_PKCS10,
  3384. bstrRequest,
  3385. NULL,
  3386. bstrConfig,
  3387. &disposition);
  3388. }
  3389. hrSubmit = hr;
  3390. hrLastStatus = hr;
  3391. }
  3392. hr = pICertRequest->GetDispositionMessage(&strDispositionMessage);
  3393. _PrintIfError(hr, "pICertRequest->GetDispositionMessage");
  3394. if (S_OK == hrSubmit)
  3395. {
  3396. hr = pICertRequest->GetLastStatus(&hrLastStatus);
  3397. _PrintIfError(hr, "pICertRequest->GetLastStatus");
  3398. }
  3399. CSILOG(
  3400. hrLastStatus,
  3401. fRetrievePending? IDS_ILOG_RETRIEVEPENDING : IDS_ILOG_SUBMITREQUEST,
  3402. bstrConfig,
  3403. strDispositionMessage,
  3404. (DWORD const *) &disposition);
  3405. iMsgId = 0;
  3406. if (S_OK != hrSubmit)
  3407. {
  3408. // default to a generic message
  3409. iMsgId = fRetrievePending?
  3410. IDS_ERR_RETRIEVE_PENDING : IDS_ERR_SUBMIT_REQUEST_FAIL;
  3411. if (HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER) == hrSubmit)
  3412. {
  3413. iMsgId = IDS_ERR_NOT_ENTERPRISE_USER;
  3414. }
  3415. // if failed, treat as denied
  3416. disposition = CR_DISP_DENIED;
  3417. }
  3418. if (CR_DISP_ISSUED != disposition)
  3419. {
  3420. if (!fRetrievePending)
  3421. {
  3422. pICertRequest->GetRequestId(&requestId);
  3423. }
  3424. hr = mySetCertRegDWValue(
  3425. pwszSanitizedCAName,
  3426. NULL,
  3427. NULL,
  3428. wszREGREQUESTID,
  3429. requestId);
  3430. _JumpIfErrorStr(hr, error, "mySetCertRegDWValue", wszREGREQUESTID);
  3431. hr = HandleSubmitOrRetrieveNotIssued(
  3432. hwnd,
  3433. hInstance,
  3434. fUnattended,
  3435. pwszSanitizedCAName,
  3436. pwszParentCAConfig,
  3437. pICertRequest,
  3438. disposition,
  3439. strDispositionMessage,
  3440. fRenew,
  3441. requestId,
  3442. hrSubmit,
  3443. hrLastStatus,
  3444. iMsgId);
  3445. // not issued, always exit with error
  3446. _JumpError(hr, error, "Cert is not issued");
  3447. }
  3448. // get pkcs7 chain
  3449. hr = pICertRequest->GetCertificate(
  3450. CR_OUT_CHAIN | CR_OUT_BINARY,
  3451. pbStrChain);
  3452. _JumpIfError(hr, error, "pICertRequest->GetCertificate");
  3453. error:
  3454. if (NULL != strDispositionMessage)
  3455. {
  3456. SysFreeString(strDispositionMessage);
  3457. }
  3458. if (NULL != pwszParentCAConfig)
  3459. {
  3460. LocalFree(pwszParentCAConfig);
  3461. }
  3462. if (NULL != bstrConfig)
  3463. {
  3464. SysFreeString(bstrConfig);
  3465. }
  3466. if (NULL != bstrRequest)
  3467. {
  3468. SysFreeString(bstrRequest);
  3469. }
  3470. if (NULL != pICertRequest)
  3471. {
  3472. pICertRequest->Release();
  3473. }
  3474. if (fCoInit)
  3475. {
  3476. CoUninitialize();
  3477. }
  3478. CSILOG(
  3479. hr,
  3480. fRetrievePending? IDS_ILOG_RETRIEVEPENDING : IDS_ILOG_SUBMITREQUEST,
  3481. pwszParentCAMachine,
  3482. pwszParentCAName,
  3483. (DWORD const *) &disposition);
  3484. return(hr);
  3485. }
  3486. HRESULT
  3487. csiInitializeCertSrvSecurity(
  3488. IN WCHAR const *pwszSanitizedCAName,
  3489. BOOL fUseEnterpriseACL, // which ACL to use
  3490. BOOL fSetDsSecurity) // whether to set security on DS object
  3491. {
  3492. HRESULT hr;
  3493. PSECURITY_DESCRIPTOR pSD = NULL;
  3494. DWORD cbLength;
  3495. CCertificateAuthoritySD CASD;
  3496. hr = CASD.InitializeFromTemplate(
  3497. fUseEnterpriseACL?
  3498. WSZ_DEFAULT_CA_ENT_SECURITY :
  3499. WSZ_DEFAULT_CA_STD_SECURITY,
  3500. pwszSanitizedCAName);
  3501. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::InitializeFromTemplate");
  3502. hr = CASD.Save();
  3503. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::Save");
  3504. hr = CASD.MapAndSetDaclOnObjects(fSetDsSecurity?true:false);
  3505. _JumpIfError(hr, error, "CProtectedSecurityDescriptor::MapAndSetDaclOnObjects");
  3506. error:
  3507. if (pSD)
  3508. {
  3509. LocalFree(pSD);
  3510. }
  3511. CSILOG(hr, IDS_ILOG_SETSECURITY, NULL, NULL, NULL);
  3512. return(hr);
  3513. }
  3514. HRESULT
  3515. csiGenerateKeysOnly(
  3516. IN WCHAR const *pwszContainer,
  3517. IN WCHAR const *pwszProvName,
  3518. IN DWORD dwProvType,
  3519. IN BOOL fMachineKeyset,
  3520. IN DWORD dwKeyLength,
  3521. IN BOOL fUnattended,
  3522. OUT HCRYPTPROV *phProv,
  3523. OUT int *piMsg)
  3524. {
  3525. HRESULT hr;
  3526. HCRYPTKEY hKey = NULL;
  3527. DWORD dwKeyGenFlags;
  3528. DWORD dwAcquireFlags;
  3529. BOOL fExists;
  3530. *phProv = NULL;
  3531. *piMsg = 0;
  3532. // see if the container already exists
  3533. dwAcquireFlags = 0;
  3534. if (fMachineKeyset)
  3535. {
  3536. dwAcquireFlags |= CRYPT_MACHINE_KEYSET;
  3537. }
  3538. if (fUnattended)
  3539. {
  3540. dwAcquireFlags |= CRYPT_SILENT;
  3541. }
  3542. fExists = CryptAcquireContext(
  3543. phProv,
  3544. pwszContainer,
  3545. pwszProvName,
  3546. dwProvType,
  3547. CRYPT_SILENT | dwAcquireFlags);
  3548. if (NULL != *phProv)
  3549. {
  3550. CryptReleaseContext(*phProv, 0);
  3551. *phProv = NULL;
  3552. }
  3553. if (fExists)
  3554. {
  3555. // container exists, but we did not choose to reuse keys,
  3556. // so remove old keys and generate new ones.
  3557. if (!CryptAcquireContext(
  3558. phProv,
  3559. pwszContainer,
  3560. pwszProvName,
  3561. dwProvType,
  3562. CRYPT_DELETEKEYSET | dwAcquireFlags))
  3563. {
  3564. hr = myHLastError();
  3565. *piMsg = IDS_ERR_DELETEKEY;
  3566. _JumpError(hr, error, "CryptAcquireContext");
  3567. }
  3568. }
  3569. // create new container
  3570. if (!CryptAcquireContext(
  3571. phProv,
  3572. pwszContainer,
  3573. pwszProvName,
  3574. dwProvType,
  3575. CRYPT_NEWKEYSET | dwAcquireFlags)) // force new container
  3576. {
  3577. hr = myHLastError();
  3578. if (NTE_TOKEN_KEYSET_STORAGE_FULL == hr)
  3579. {
  3580. // Smart cards can only hold a limited number of keys
  3581. // The user must pick an existing key or use a blank card
  3582. *piMsg = IDS_ERR_FULL_TOKEN;
  3583. _JumpError(hr, error, "CryptAcquireContext");
  3584. }
  3585. else if (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr)
  3586. {
  3587. // user must have clicked cancel on a smart card dialog.
  3588. // go to previous page, and display no error message
  3589. _JumpError(hr, error, "CryptAcquireContext");
  3590. }
  3591. else if (NTE_EXISTS == hr)
  3592. {
  3593. // since fExists shows NOT, it is likely the current user
  3594. // doesn't have access permission for this existing key
  3595. *piMsg = IDS_ERR_NO_KEY_ACCESS;
  3596. _JumpError(hr, error, "CryptAcquireContext");
  3597. }
  3598. else
  3599. {
  3600. // Unexpected error in CryptAcquireContext.
  3601. *piMsg = IDS_ERR_BADCSP;
  3602. _JumpError(hr, error, "CryptAcquireContext");
  3603. }
  3604. }
  3605. // set key length
  3606. dwKeyGenFlags = (dwKeyLength << 16) | CRYPT_EXPORTABLE;
  3607. // create signature keys
  3608. if (!CryptGenKey(*phProv, AT_SIGNATURE, dwKeyGenFlags, &hKey))
  3609. {
  3610. hr = myHLastError();
  3611. *piMsg = IDS_ERR_GENKEYFAIL;
  3612. _JumpError(hr, error, "CryptGenKey");
  3613. }
  3614. hr = S_OK;
  3615. error:
  3616. if (NULL != hKey)
  3617. {
  3618. CryptDestroyKey(hKey);
  3619. }
  3620. CSILOG(hr, IDS_ILOG_GENERATEKEYS, pwszContainer, pwszProvName, &dwKeyLength);
  3621. return(hr);
  3622. }
  3623. HRESULT
  3624. csiGenerateCAKeys(
  3625. IN WCHAR const *pwszContainer,
  3626. IN WCHAR const *pwszProvName,
  3627. IN DWORD dwProvType,
  3628. IN BOOL fMachineKeyset,
  3629. IN DWORD dwKeyLength,
  3630. IN HINSTANCE hInstance,
  3631. IN BOOL fUnattended,
  3632. IN HWND hwnd,
  3633. OUT BOOL *pfKeyGenFailed)
  3634. {
  3635. HRESULT hr;
  3636. HCRYPTPROV hProv = NULL;
  3637. int iMsg;
  3638. // generate key first
  3639. hr = csiGenerateKeysOnly(
  3640. pwszContainer,
  3641. pwszProvName,
  3642. dwProvType,
  3643. fMachineKeyset,
  3644. dwKeyLength,
  3645. fUnattended,
  3646. &hProv,
  3647. &iMsg);
  3648. if (S_OK != hr)
  3649. {
  3650. CertWarningMessageBox(
  3651. hInstance,
  3652. fUnattended,
  3653. hwnd,
  3654. iMsg,
  3655. hr,
  3656. pwszContainer);
  3657. *pfKeyGenFailed = TRUE;
  3658. _JumpError(hr, error, "csiGenerateKeysOnly");
  3659. }
  3660. *pfKeyGenFailed = FALSE;
  3661. // now apply acl on key
  3662. // BUG, this is not necessary, CertSrvSetSecurity will reset
  3663. hr = csiSetKeyContainerSecurity(hProv);
  3664. if (S_OK != hr)
  3665. {
  3666. CertWarningMessageBox(
  3667. hInstance,
  3668. fUnattended,
  3669. hwnd,
  3670. IDS_ERR_KEYSECURITY,
  3671. hr,
  3672. pwszContainer);
  3673. _PrintError(hr, "csiSetKeyContainerSecurity");
  3674. }
  3675. hr = S_OK;
  3676. error:
  3677. if (NULL != hProv)
  3678. {
  3679. CryptReleaseContext(hProv, 0);
  3680. }
  3681. return(hr);
  3682. }
  3683. HRESULT
  3684. csiGetProviderTypeFromProviderName(
  3685. IN WCHAR const *pwszName,
  3686. OUT DWORD *pdwType)
  3687. {
  3688. HRESULT hr;
  3689. DWORD i;
  3690. DWORD dwProvType;
  3691. WCHAR *pwszProvName = NULL;
  3692. // Provider name should not be null. This could be changed to ...
  3693. CSASSERT(NULL != pwszName);
  3694. *pdwType = 0;
  3695. dwProvType = 0;
  3696. for (i = 0; ; i++)
  3697. {
  3698. // get provider name
  3699. hr = myEnumProviders(i, NULL, 0, &dwProvType, &pwszProvName);
  3700. if (S_OK != hr)
  3701. {
  3702. hr = myHLastError();
  3703. CSASSERT(
  3704. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  3705. NTE_FAIL == hr);
  3706. if(HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  3707. NTE_FAIL == hr)
  3708. {
  3709. // no more providers, terminate loop
  3710. hr = E_INVALIDARG;
  3711. CSILOG(
  3712. hr,
  3713. IDS_ILOG_MISSING_PROVIDER,
  3714. pwszName,
  3715. NULL,
  3716. NULL);
  3717. _JumpErrorStr(hr, error, "not found", pwszName);
  3718. }
  3719. }
  3720. else
  3721. {
  3722. CSASSERT(NULL != pwszProvName);
  3723. if (0 == lstrcmpi(pwszName, pwszProvName))
  3724. {
  3725. break; // found it
  3726. }
  3727. LocalFree(pwszProvName);
  3728. pwszProvName = NULL;
  3729. }
  3730. }
  3731. *pdwType = dwProvType;
  3732. hr = S_OK;
  3733. error:
  3734. if (NULL != pwszProvName)
  3735. {
  3736. LocalFree(pwszProvName);
  3737. }
  3738. return(hr);
  3739. }
  3740. HRESULT
  3741. csiUpgradeCertSrvSecurity(
  3742. IN WCHAR const *pwszSanitizedCAName,
  3743. BOOL fUseEnterpriseACL, // which ACL to use
  3744. BOOL fSetDsSecurity, // whether to set security on DS object
  3745. CS_ENUM_UPGRADE UpgradeType)
  3746. {
  3747. HRESULT hr = S_OK;
  3748. CertSrv::CCertificateAuthoritySD CASD;
  3749. PSECURITY_DESCRIPTOR pDefaultSD = NULL;
  3750. hr = CASD.Initialize(pwszSanitizedCAName);
  3751. _PrintIfError(hr, "CASD.Initialize");
  3752. if(S_OK==hr)
  3753. {
  3754. if(CS_UPGRADE_WHISTLER==UpgradeType)
  3755. {
  3756. // validate the SD
  3757. hr = CASD.Validate(CASD.Get());
  3758. _PrintIfError(hr, "CASD.Validate");
  3759. }
  3760. else // win2k
  3761. {
  3762. hr = CASD.UpgradeWin2k(fUseEnterpriseACL?true:false);
  3763. _PrintIfError(hr, "CASD.UpgradeWin2k");
  3764. }
  3765. }
  3766. // never fail, fall back to a default SD
  3767. if(S_OK!=hr)
  3768. {
  3769. CASD.Uninitialize();
  3770. hr = CASD.InitializeFromTemplate(
  3771. fUseEnterpriseACL?
  3772. WSZ_DEFAULT_CA_ENT_SECURITY :
  3773. WSZ_DEFAULT_CA_STD_SECURITY,
  3774. pwszSanitizedCAName);
  3775. _JumpIfError(hr, error,
  3776. "CProtectedSecurityDescriptor::InitializeFromTemplate");
  3777. }
  3778. hr = CASD.Save();
  3779. _JumpIfError(hr, error, "CASD.Save");
  3780. hr = CASD.MapAndSetDaclOnObjects(fSetDsSecurity? true:false);
  3781. _PrintIfError(hr, "CASD::MapAndSetDaclOnObjects");
  3782. if ((hr != S_OK) && fSetDsSecurity && (UpgradeType != CS_UPGRADE_NO))
  3783. {
  3784. // if asked to set security on DS and this is UPGRADE, we can't touch DS.
  3785. // Leave security changes to the certsrv snapin
  3786. // set a flag so certmmc knows to do something
  3787. hr = SetSetupStatus(pwszSanitizedCAName, SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG, TRUE);
  3788. _JumpIfError(hr, error, "SetSetupStatus");
  3789. hr = HRESULT_FROM_WIN32(ERROR_CAN_NOT_COMPLETE);
  3790. _PrintError(hr, "DS unavailable");
  3791. }
  3792. else
  3793. {
  3794. // make sure this bit is cleared
  3795. hr = SetSetupStatus(pwszSanitizedCAName, SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG, FALSE);
  3796. _JumpIfError(hr, error, "SetSetupStatus");
  3797. }
  3798. error:
  3799. LOCAL_FREE(pDefaultSD);
  3800. return hr;
  3801. }
  3802. DefineAutoClass(CAutoPCERT_NAME_INFO, PCERT_NAME_INFO, LocalFree);
  3803. DefineAutoClass(CAutoPCERT_RDN, PCERT_RDN, LocalFree);
  3804. HRESULT AddCNAndEncode(
  3805. LPCWSTR pcwszName,
  3806. LPCWSTR pcwszDNSuffix,
  3807. BYTE** ppbEncodedDN,
  3808. DWORD *pcbEncodedDN)
  3809. {
  3810. HRESULT hr;
  3811. CAutoPBYTE pbDNSuffix;
  3812. DWORD cbDNSuffix;
  3813. CAutoPCERT_NAME_INFO pCertNameInfo;
  3814. DWORD cbCertNameInfo;
  3815. CAutoPCERT_RDN pCertRDN;
  3816. CERT_RDN_ATTR attrDN;
  3817. CAutoPBYTE pbEncodedDN;
  3818. DWORD cbEncodedDN;
  3819. attrDN.pszObjId = szOID_COMMON_NAME;
  3820. attrDN.dwValueType = CERT_RDN_ANY_TYPE;
  3821. attrDN.Value.cbData = 0;
  3822. attrDN.Value.pbData = (PBYTE)pcwszName;
  3823. hr = myCertStrToName(
  3824. X509_ASN_ENCODING,
  3825. pcwszDNSuffix,
  3826. CERT_X500_NAME_STR |
  3827. CERT_NAME_STR_COMMA_FLAG |
  3828. CERT_NAME_STR_REVERSE_FLAG |
  3829. ((g_dwNameEncodeFlags&CERT_RDN_ENABLE_UTF8_UNICODE_FLAG)?
  3830. CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG:0),
  3831. NULL,
  3832. &pbEncodedDN,
  3833. &cbEncodedDN,
  3834. NULL);
  3835. _JumpIfError(hr, error, "myCertStrToName");
  3836. if (!myDecodeName(
  3837. X509_ASN_ENCODING,
  3838. X509_UNICODE_NAME,
  3839. pbEncodedDN,
  3840. cbEncodedDN,
  3841. CERTLIB_USE_LOCALALLOC,
  3842. &pCertNameInfo,
  3843. &cbCertNameInfo))
  3844. {
  3845. hr = myHLastError();
  3846. _JumpError(hr, error, "myDecodeName");
  3847. }
  3848. pCertRDN = (PCERT_RDN)LocalAlloc(
  3849. LMEM_FIXED,
  3850. (pCertNameInfo->cRDN+1)*sizeof(CERT_RDN));
  3851. _JumpIfAllocFailed(pCertRDN, error);
  3852. CopyMemory(
  3853. pCertRDN,
  3854. pCertNameInfo->rgRDN,
  3855. pCertNameInfo->cRDN*sizeof(CERT_RDN));
  3856. pCertRDN[pCertNameInfo->cRDN].cRDNAttr = 1;
  3857. pCertRDN[pCertNameInfo->cRDN].rgRDNAttr = &attrDN;
  3858. pCertNameInfo->cRDN++;
  3859. pCertNameInfo->rgRDN = pCertRDN;
  3860. if (!myEncodeName(
  3861. X509_ASN_ENCODING,
  3862. pCertNameInfo,
  3863. g_dwNameEncodeFlags,
  3864. CERTLIB_USE_LOCALALLOC,
  3865. ppbEncodedDN,
  3866. pcbEncodedDN))
  3867. {
  3868. hr = myHLastError();
  3869. _JumpError(hr, error, "myEncodeName");
  3870. }
  3871. error:
  3872. return hr;
  3873. }
  3874. /*
  3875. * Add/remove computer account to the Cert Publishers group for the forest
  3876. */
  3877. HRESULT
  3878. AddOrRemoveCAMachineToCertPublishers(bool fAdd)
  3879. {
  3880. HRESULT hr = S_OK;
  3881. LPWSTR pwszComputerDN = NULL;
  3882. LDAP *pld = NULL;
  3883. LPWSTR pcwszComputerDomainDN; // no free
  3884. LPWSTR pcwszCertPublishersFilter =
  3885. L"(&(objectClass=group)(CN=Cert Publishers))";
  3886. LDAPMessage* pResult = NULL;
  3887. LDAPMessage *pEntry;
  3888. LPWSTR pwszAttrArray[2];
  3889. BerElement *pber;
  3890. LPWSTR pwszDNAttr = L"distinguishedName";
  3891. LPWSTR pwszMemberAttr = L"member";
  3892. LPWSTR* pwszCertPublishersDN = NULL;
  3893. LDAPMod *mods[2];
  3894. LDAPMod member;
  3895. LPWSTR memberVals[2];
  3896. hr = myGetComputerObjectName(
  3897. NameFullyQualifiedDN,
  3898. &pwszComputerDN);
  3899. _JumpIfError(hr, error, "myGetComputerObjectName");
  3900. pcwszComputerDomainDN = wcsstr(pwszComputerDN, L"DC=");
  3901. pwszAttrArray[0] = pwszDNAttr;
  3902. pwszAttrArray[1] = NULL;
  3903. hr = myRobustLdapBind(
  3904. &pld,
  3905. FALSE); // no GC
  3906. _JumpIfError(hr, error, "myRobustLdapBind");
  3907. hr = ldap_search_s(
  3908. pld,
  3909. pcwszComputerDomainDN,
  3910. LDAP_SCOPE_SUBTREE,
  3911. pcwszCertPublishersFilter,
  3912. pwszAttrArray,
  3913. FALSE,
  3914. &pResult);
  3915. hr = myHLdapError(pld, hr, NULL);
  3916. _JumpIfError(hr, error, "ldap_search_sW");
  3917. pEntry = ldap_first_entry(pld, pResult);
  3918. if (NULL == pEntry)
  3919. {
  3920. hr = myHLdapLastError(pld, NULL);
  3921. _JumpError(hr, error, "ldap_first_entry");
  3922. }
  3923. pwszCertPublishersDN = ldap_get_values(
  3924. pld,
  3925. pEntry,
  3926. pwszDNAttr);
  3927. if (NULL == pwszCertPublishersDN || NULL==*pwszCertPublishersDN)
  3928. {
  3929. hr = myHLdapLastError(pld, NULL);
  3930. _JumpError(hr, error, "ldap_get_values");
  3931. }
  3932. memberVals[0] = pwszComputerDN;
  3933. memberVals[1] = NULL;
  3934. member.mod_op = fAdd?LDAP_MOD_ADD:LDAP_MOD_DELETE;
  3935. member.mod_type = pwszMemberAttr;
  3936. member.mod_values = memberVals;
  3937. mods[0] = &member;
  3938. mods[1] = NULL;
  3939. hr = ldap_modify_ext_s(
  3940. pld,
  3941. *pwszCertPublishersDN,
  3942. mods,
  3943. NULL,
  3944. NULL);
  3945. // don't fail if already member of cert publishers
  3946. if(((HRESULT)LDAP_ALREADY_EXISTS)==hr)
  3947. hr = LDAP_SUCCESS;
  3948. hr = myHLdapError(pld, hr, NULL);
  3949. _JumpIfErrorStr(hr, error, "ldap_modify_exts", *pwszCertPublishersDN);
  3950. error:
  3951. LOCAL_FREE(pwszComputerDN);
  3952. if(pwszCertPublishersDN)
  3953. {
  3954. ldap_value_free(pwszCertPublishersDN);
  3955. }
  3956. if (NULL != pResult)
  3957. {
  3958. ldap_msgfree(pResult);
  3959. }
  3960. if (pld)
  3961. ldap_unbind(pld);
  3962. return hr;
  3963. }
  3964. HRESULT
  3965. AddCAMachineToCertPublishers(VOID)
  3966. {
  3967. return AddOrRemoveCAMachineToCertPublishers(true);
  3968. }
  3969. HRESULT
  3970. RemoveCAMachineFromCertPublishers(VOID)
  3971. {
  3972. return AddOrRemoveCAMachineToCertPublishers(false);
  3973. }