Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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