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.

2362 lines
57 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // copied from K2 SDK policy.cpp.
  7. // modified by GregKr for expolicy.
  8. //
  9. // File: expolicy.cpp
  10. //
  11. // Contents: KMS-specific Cert Server Policy Module implementation
  12. //
  13. //---------------------------------------------------------------------------
  14. #include "pch.cpp"
  15. #pragma hdrstop
  16. #include "policy.h"
  17. #include "celib.h"
  18. //#include "newcert.h"
  19. #include <assert.h>
  20. #include <exver.h> // Exchange build version (rmj et al)
  21. #include <kmsattr.h> // strings used by both KMS and ExPolicy
  22. #ifndef DBG_CERTSRV
  23. #error -- DBG_CERTSRV not defined!
  24. #endif
  25. BOOL fDebug = DBG_CERTSRV;
  26. #if DBG_CERTSRV
  27. #define EXP_FLAVOR L" debug"
  28. #else
  29. #define EXP_FLAVOR
  30. #endif
  31. #define MAKEFILEVERSION(_rmaj, _rmin, _bmaj, _bmin) \
  32. L#_rmaj L"." L#_rmin L"." L#_bmaj L"." L#_bmin EXP_FLAVOR
  33. #define MAKE_FILEVERSION_STR(_rmaj, _rmin, _bmaj, _bmin) \
  34. MAKEFILEVERSION(_rmaj, _rmin, _bmaj, _bmin)
  35. #define VER_FILEVERSION_STR \
  36. MAKE_FILEVERSION_STR(rmj, rmn, rmm, rup)
  37. const WCHAR g_wszDescription[] =
  38. L"Microsoft Exchange KMServer Policy Module " VER_FILEVERSION_STR;
  39. // worker
  40. HRESULT
  41. GetServerCallbackInterface(
  42. OUT ICertServerPolicy **ppServer,
  43. IN LONG Context)
  44. {
  45. HRESULT hr;
  46. if (NULL == ppServer)
  47. {
  48. hr = E_POINTER;
  49. _JumpError(hr, error, "NULL parm");
  50. }
  51. hr = CoCreateInstance(
  52. CLSID_CCertServerPolicy,
  53. NULL, // pUnkOuter
  54. CLSCTX_INPROC_SERVER,
  55. IID_ICertServerPolicy,
  56. (VOID **) ppServer);
  57. _JumpIfError(hr, error, "CoCreateInstance");
  58. if (*ppServer == NULL)
  59. {
  60. hr = E_UNEXPECTED;
  61. _JumpError(hr, error, "NULL *ppServer");
  62. }
  63. // only set context if nonzero
  64. if (0 != Context)
  65. {
  66. hr = (*ppServer)->SetContext(Context);
  67. _JumpIfError(hr, error, "Policy:SetContext");
  68. }
  69. error:
  70. return(hr);
  71. }
  72. WCHAR const * const s_rgpwszRegMultiStrValues[] =
  73. {
  74. wszREGLDAPISSUERCERTURL_OLD,
  75. wszREGISSUERCERTURL_OLD,
  76. wszREGFTPISSUERCERTURL_OLD,
  77. wszREGFILEISSUERCERTURL_OLD,
  78. wszREGLDAPREVOCATIONCRLURL_OLD,
  79. wszREGREVOCATIONCRLURL_OLD,
  80. wszREGFTPREVOCATIONCRLURL_OLD,
  81. wszREGFILEREVOCATIONCRLURL_OLD,
  82. };
  83. typedef struct _REGDWORDVALUE
  84. {
  85. WCHAR const *pwszName;
  86. DWORD dwValueDefault;
  87. } REGDWORDVALUE;
  88. const REGDWORDVALUE s_rgRegDWordValues[] =
  89. {
  90. {
  91. wszREGREQUESTDISPOSITION,
  92. REQDISP_ISSUE
  93. },
  94. {
  95. wszREGISSUERCERTURLFLAGS,
  96. ISSCERT_ENABLE |
  97. ISSCERT_LDAPURL_OLD |
  98. ISSCERT_HTTPURL_OLD |
  99. ISSCERT_FTPURL_OLD |
  100. ISSCERT_FILEURL_OLD
  101. },
  102. {
  103. wszREGREVOCATIONTYPE,
  104. REVEXT_CDPENABLE |
  105. REVEXT_CDPLDAPURL_OLD |
  106. REVEXT_CDPHTTPURL_OLD |
  107. REVEXT_CDPFTPURL_OLD |
  108. REVEXT_CDPFILEURL_OLD
  109. },
  110. };
  111. HRESULT
  112. CopyMultiStrRegValue(
  113. IN HKEY hkeySrc,
  114. IN HKEY hkeyDest,
  115. IN WCHAR const *pwszName)
  116. {
  117. HRESULT hr;
  118. DWORD cbValue;
  119. DWORD dwType;
  120. WCHAR *pwszzAlloc = NULL;
  121. WCHAR *pwszzValue;
  122. hr = RegQueryValueEx(hkeyDest, pwszName, NULL, &dwType, NULL, &cbValue);
  123. if (S_OK == hr && REG_MULTI_SZ == dwType)
  124. {
  125. goto error; // preserve existing value
  126. }
  127. hr = RegQueryValueEx(hkeySrc, pwszName, NULL, &dwType, NULL, &cbValue);
  128. if (S_OK == hr && REG_MULTI_SZ == dwType && sizeof(WCHAR) < cbValue)
  129. {
  130. pwszzAlloc = (WCHAR *) LocalAlloc(LMEM_FIXED, cbValue);
  131. if (NULL == pwszzAlloc)
  132. {
  133. hr = E_OUTOFMEMORY;
  134. _JumpError(hr, error, "LocalAlloc");
  135. }
  136. hr = RegQueryValueEx(
  137. hkeySrc,
  138. pwszName,
  139. NULL,
  140. &dwType,
  141. (BYTE *) pwszzAlloc,
  142. &cbValue);
  143. _JumpIfError(hr, error, "RegQueryValueEx");
  144. pwszzValue = pwszzAlloc;
  145. }
  146. else
  147. {
  148. pwszzValue = L"\0";
  149. cbValue = 2 * sizeof(WCHAR);
  150. }
  151. hr = RegSetValueEx(
  152. hkeyDest,
  153. pwszName,
  154. NULL,
  155. REG_MULTI_SZ,
  156. (BYTE const *) pwszzValue,
  157. cbValue);
  158. _JumpIfError(hr, error, "RegSetValueEx");
  159. error:
  160. if (NULL != pwszzAlloc)
  161. {
  162. LocalFree(pwszzAlloc);
  163. }
  164. return(ceHError(hr));
  165. }
  166. HRESULT
  167. CopyDWordRegValue(
  168. IN HKEY hkeySrc,
  169. IN HKEY hkeyDest,
  170. IN REGDWORDVALUE const *prdv)
  171. {
  172. HRESULT hr;
  173. DWORD cbValue;
  174. DWORD dwType;
  175. DWORD dwValue;
  176. hr = RegQueryValueEx(hkeyDest, prdv->pwszName, NULL, &dwType, NULL, &cbValue);
  177. if (S_OK == hr && REG_DWORD == dwType)
  178. {
  179. goto error; // preserve existing value
  180. }
  181. cbValue = sizeof(dwValue);
  182. hr = RegQueryValueEx(
  183. hkeySrc,
  184. prdv->pwszName,
  185. NULL,
  186. &dwType,
  187. (BYTE *) &dwValue,
  188. &cbValue);
  189. if (S_OK != hr || REG_DWORD != dwType || sizeof(dwValue) != cbValue)
  190. {
  191. dwValue = prdv->dwValueDefault;
  192. }
  193. hr = RegSetValueEx(
  194. hkeyDest,
  195. prdv->pwszName,
  196. NULL,
  197. REG_DWORD,
  198. (BYTE const *) &dwValue,
  199. sizeof(dwValue));
  200. _JumpIfError(hr, error, "RegSetValueEx");
  201. error:
  202. return(ceHError(hr));
  203. }
  204. HRESULT
  205. PopulateRegistryDefaults(
  206. OPTIONAL IN WCHAR const *pwszMachine,
  207. IN WCHAR const *pwszStorageLocation)
  208. {
  209. HRESULT hr;
  210. HRESULT hr2;
  211. HKEY hkeyHKLM = NULL;
  212. HKEY hkeyDest = NULL;
  213. HKEY hkeySrc = NULL;
  214. DWORD dwDisposition;
  215. WCHAR const *pwsz;
  216. WCHAR *pwszSrc = NULL;
  217. DWORD cwcPrefix;
  218. DWORD cwc;
  219. DWORD i;
  220. DBGPRINT((TRUE, "pwszDest: '%ws'\n", pwszStorageLocation));
  221. pwsz = wcsrchr(pwszStorageLocation, L'\\');
  222. if (NULL == pwsz)
  223. {
  224. hr = E_INVALIDARG;
  225. _JumpError(hr, error, "Invalid registry path");
  226. }
  227. pwsz++;
  228. cwcPrefix = SAFE_SUBTRACT_POINTERS(pwsz, pwszStorageLocation);
  229. cwc = cwcPrefix + WSZARRAYSIZE(wszCLASS_CERTPOLICY);
  230. pwszSrc = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  231. if (NULL == pwszSrc)
  232. {
  233. hr = E_OUTOFMEMORY;
  234. _JumpError(hr, error, "LocalAlloc");
  235. }
  236. CopyMemory(pwszSrc, pwszStorageLocation, cwcPrefix * sizeof(WCHAR));
  237. wcscpy(&pwszSrc[cwcPrefix], wszCLASS_CERTPOLICY);
  238. assert(wcslen(pwszSrc) == cwc);
  239. DBGPRINT((TRUE, "pwszSrc: '%ws'\n", pwszSrc));
  240. if (NULL != pwszMachine)
  241. {
  242. hr = RegConnectRegistry(
  243. pwszMachine,
  244. HKEY_LOCAL_MACHINE,
  245. &hkeyHKLM);
  246. _JumpIfError(hr, error, "RegConnectRegistry");
  247. }
  248. // open destination storage location for write
  249. hr = RegCreateKeyEx(
  250. NULL == pwszMachine? HKEY_LOCAL_MACHINE : hkeyHKLM,
  251. pwszStorageLocation,
  252. 0,
  253. NULL,
  254. 0,
  255. KEY_READ | KEY_WRITE,
  256. NULL,
  257. &hkeyDest,
  258. &dwDisposition);
  259. if (hr != S_OK)
  260. {
  261. _JumpError(hr, error, "RegOpenKeyEx");
  262. }
  263. // open source storage location for read
  264. hr = RegOpenKeyEx(
  265. NULL == pwszMachine? HKEY_LOCAL_MACHINE : hkeyHKLM,
  266. pwszSrc,
  267. 0,
  268. KEY_READ,
  269. &hkeySrc);
  270. _JumpIfError(hr, error, "RegOpenKeyEx");
  271. hr = S_OK;
  272. for (i = 0; i < ARRAYSIZE(s_rgpwszRegMultiStrValues); i++)
  273. {
  274. hr2 = CopyMultiStrRegValue(
  275. hkeySrc,
  276. hkeyDest,
  277. s_rgpwszRegMultiStrValues[i]);
  278. if (S_OK != hr2)
  279. {
  280. _PrintErrorStr(
  281. hr2,
  282. "CopyMultiStrRegValue",
  283. s_rgpwszRegMultiStrValues[i]);
  284. if (S_OK == hr)
  285. {
  286. hr = hr2;
  287. }
  288. }
  289. }
  290. for (i = 0; i < ARRAYSIZE(s_rgRegDWordValues); i++)
  291. {
  292. hr2 = CopyDWordRegValue(
  293. hkeySrc,
  294. hkeyDest,
  295. &s_rgRegDWordValues[i]);
  296. if (S_OK != hr2)
  297. {
  298. _PrintErrorStr(
  299. hr2,
  300. "CopyDWordRegValue",
  301. s_rgRegDWordValues[i].pwszName);
  302. if (S_OK == hr)
  303. {
  304. hr = hr2;
  305. }
  306. }
  307. }
  308. error:
  309. if (NULL != pwszSrc)
  310. {
  311. LocalFree(pwszSrc);
  312. }
  313. if (NULL != hkeyHKLM)
  314. {
  315. RegCloseKey(hkeyHKLM);
  316. }
  317. if (NULL != hkeyDest)
  318. {
  319. RegCloseKey(hkeyDest);
  320. }
  321. if (NULL != hkeySrc)
  322. {
  323. RegCloseKey(hkeySrc);
  324. }
  325. return(ceHError(hr));
  326. }
  327. //+--------------------------------------------------------------------------
  328. // CCertPolicyExchange::~CCertPolicyExchange -- destructor
  329. //
  330. // free memory associated with this instance
  331. //+--------------------------------------------------------------------------
  332. CCertPolicyExchange::~CCertPolicyExchange()
  333. {
  334. _Cleanup();
  335. }
  336. VOID
  337. CCertPolicyExchange::_FreeStringArray(
  338. IN OUT DWORD *pcString,
  339. IN OUT LPWSTR **papstr)
  340. {
  341. BSTR *apstr = *papstr;
  342. DWORD i;
  343. if (NULL != apstr)
  344. {
  345. for (i = *pcString; i-- > 0; )
  346. {
  347. if (NULL != apstr[i])
  348. {
  349. DBGPRINT((fDebug, "_FreeStringArray[%u]: '%ws'\n", i, apstr[i]));
  350. LocalFree(apstr[i]);
  351. }
  352. }
  353. LocalFree(apstr);
  354. *papstr = NULL;
  355. }
  356. *pcString = 0;
  357. }
  358. //+--------------------------------------------------------------------------
  359. // CCertPolicyExchange::_Cleanup -- free memory associated with this instance
  360. //
  361. // free memory associated with this instance
  362. //+--------------------------------------------------------------------------
  363. VOID
  364. CCertPolicyExchange::_Cleanup()
  365. {
  366. // RevocationExtension variables:
  367. _FreeStringArray(&m_cCDPRevocationURL, &m_ppwszCDPRevocationURL);
  368. if (NULL != m_pwszASPRevocationURL)
  369. {
  370. LocalFree(m_pwszASPRevocationURL);
  371. m_pwszASPRevocationURL = NULL;
  372. }
  373. // AuthorityInfoAccessExtension variables:
  374. _FreeStringArray(&m_cIssuerCertURL, &m_ppwszIssuerCertURL);
  375. if (NULL != m_bstrMachineDNSName)
  376. {
  377. SysFreeString(m_bstrMachineDNSName);
  378. m_bstrMachineDNSName = NULL;
  379. }
  380. if (NULL != m_bstrCASanitizedName)
  381. {
  382. SysFreeString(m_bstrCASanitizedName);
  383. m_bstrCASanitizedName = NULL;
  384. }
  385. }
  386. HRESULT
  387. CCertPolicyExchange::_ReadRegistryString(
  388. IN HKEY hkey,
  389. IN BOOL fURL,
  390. IN WCHAR const *pwszRegName,
  391. IN WCHAR const *pwszSuffix,
  392. OUT LPWSTR *ppwszOut)
  393. {
  394. HRESULT hr;
  395. WCHAR *pwszRegValue = NULL;
  396. DWORD cbValue;
  397. DWORD dwType;
  398. *ppwszOut = NULL;
  399. hr = RegQueryValueEx(
  400. hkey,
  401. pwszRegName,
  402. NULL, // lpdwReserved
  403. &dwType,
  404. NULL,
  405. &cbValue);
  406. _JumpIfErrorStr2(hr, error, "RegQueryValueEx", pwszRegName, ERROR_FILE_NOT_FOUND);
  407. if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
  408. {
  409. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  410. _JumpErrorStr(hr, error, "RegQueryValueEx TYPE", pwszRegName);
  411. }
  412. if (NULL != pwszSuffix)
  413. {
  414. cbValue += wcslen(pwszSuffix) * sizeof(WCHAR);
  415. }
  416. pwszRegValue = (WCHAR *) LocalAlloc(LMEM_FIXED, cbValue + sizeof(WCHAR));
  417. if (NULL == pwszRegValue)
  418. {
  419. hr = E_OUTOFMEMORY;
  420. _JumpErrorStr(hr, error, "LocalAlloc", pwszRegName);
  421. }
  422. hr = RegQueryValueEx(
  423. hkey,
  424. pwszRegName,
  425. NULL, // lpdwReserved
  426. &dwType,
  427. (BYTE *) pwszRegValue,
  428. &cbValue);
  429. _JumpIfErrorStr(hr, error, "RegQueryValueEx", pwszRegName);
  430. // Handle malformed registry values cleanly:
  431. pwszRegValue[cbValue / sizeof(WCHAR)] = L'\0';
  432. if (NULL != pwszSuffix)
  433. {
  434. wcscat(pwszRegValue, pwszSuffix);
  435. }
  436. hr = ceFormatCertsrvStringArray(
  437. fURL, // fURL
  438. m_bstrMachineDNSName, // pwszServerName_p1_2
  439. m_bstrCASanitizedName, // pwszSanitizedName_p3_7
  440. m_iCert, // iCert_p4
  441. MAXDWORD, // iCertTarget_p4
  442. L"", // pwszDomainDN_p5
  443. L"", // pwszConfigDN_p6
  444. m_iCRL, // iCRL_p8
  445. FALSE, // fDeltaCRL_p9,
  446. FALSE, // fDSAttrib_p10_11,
  447. 1, // cStrings
  448. (LPCWSTR *) &pwszRegValue, // apwszStringsIn
  449. ppwszOut); // apwszStringsOut
  450. _JumpIfError(hr, error, "ceFormatCertsrvStringArray");
  451. error:
  452. if (NULL != pwszRegValue)
  453. {
  454. LocalFree(pwszRegValue);
  455. }
  456. return(ceHError(hr));
  457. }
  458. #if DBG_CERTSRV
  459. VOID
  460. CCertPolicyExchange::_DumpStringArray(
  461. IN char const *pszType,
  462. IN DWORD cpwsz,
  463. IN WCHAR const * const *ppwsz)
  464. {
  465. DWORD i;
  466. WCHAR const *pwszName;
  467. for (i = 0; i < cpwsz; i++)
  468. {
  469. pwszName = L"";
  470. if (iswdigit(ppwsz[i][0]))
  471. {
  472. pwszName = ceGetOIDName(ppwsz[i]); // Static: do not free!
  473. }
  474. DBGPRINT((
  475. fDebug,
  476. "%hs[%u]: %ws%hs%ws\n",
  477. pszType,
  478. i,
  479. ppwsz[i],
  480. L'\0' != *pwszName? " -- " : "",
  481. pwszName));
  482. }
  483. }
  484. #endif // DBG_CERTSRV
  485. HRESULT
  486. CCertPolicyExchange::_AddStringArray(
  487. IN WCHAR const *pwszzValue,
  488. IN BOOL fURL,
  489. IN OUT DWORD *pcStrings,
  490. IN OUT LPWSTR **papstrRegValues)
  491. {
  492. HRESULT hr = S_OK;
  493. DWORD cString = 0;
  494. WCHAR const *pwsz;
  495. LPCWSTR *awszFormatStrings = NULL;
  496. LPWSTR *awszOutputStrings = NULL;
  497. // Count the number of strings we're adding
  498. for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  499. {
  500. cString++;
  501. }
  502. if (0 == cString) // no strings
  503. {
  504. goto error;
  505. }
  506. awszFormatStrings = (LPCWSTR *) LocalAlloc(
  507. LMEM_FIXED | LMEM_ZEROINIT,
  508. cString * sizeof(LPWSTR));
  509. if (NULL == awszFormatStrings)
  510. {
  511. hr = E_OUTOFMEMORY;
  512. _JumpError(hr, error, "LocalAlloc");
  513. }
  514. cString = 0;
  515. for (pwsz = pwszzValue; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  516. {
  517. // Skip strings that start with a an unescaped minus sign.
  518. // Strings with an escaped minus sign (2 minus signs) are not skipped.
  519. if (L'-' == *pwsz)
  520. {
  521. pwsz++;
  522. if (L'-' != *pwsz)
  523. {
  524. continue;
  525. }
  526. }
  527. awszFormatStrings[cString++] = pwsz;
  528. }
  529. // if no strings to add, don't modify
  530. if (cString > 0)
  531. {
  532. awszOutputStrings = (LPWSTR *) LocalAlloc(
  533. LMEM_FIXED | LMEM_ZEROINIT,
  534. (cString + *pcStrings) * sizeof(LPWSTR));
  535. if (NULL == awszOutputStrings)
  536. {
  537. hr = E_OUTOFMEMORY;
  538. _JumpError(hr, error, "LocalAlloc");
  539. }
  540. if (0 != *pcStrings)
  541. {
  542. assert(NULL != *papstrRegValues);
  543. CopyMemory(awszOutputStrings, *papstrRegValues, *pcStrings * sizeof(LPWSTR));
  544. }
  545. hr = ceFormatCertsrvStringArray(
  546. fURL, // fURL
  547. m_bstrMachineDNSName, // pwszServerName_p1_2
  548. m_bstrCASanitizedName, // pwszSanitizedName_p3_7
  549. m_iCert, // iCert_p4
  550. MAXDWORD, // iCertTarget_p4
  551. L"", // pwszDomainDN_p5
  552. L"", // pwszConfigDN_p6
  553. m_iCRL, // iCRL_p8
  554. FALSE, // fDeltaCRL_p9,
  555. FALSE, // fDSAttrib_p10_11,
  556. cString, // cStrings
  557. awszFormatStrings, // apwszStringsIn
  558. &awszOutputStrings[*pcStrings]); // apwszStringsOut
  559. _JumpIfError(hr, error, "ceFormatCertsrvStringArray");
  560. *pcStrings = (*pcStrings) + cString;
  561. if (*papstrRegValues)
  562. {
  563. LocalFree(*papstrRegValues);
  564. }
  565. *papstrRegValues = awszOutputStrings;
  566. awszOutputStrings = NULL;
  567. }
  568. error:
  569. if (awszOutputStrings)
  570. {
  571. LocalFree(awszOutputStrings);
  572. }
  573. if (awszFormatStrings)
  574. {
  575. LocalFree(awszFormatStrings);
  576. }
  577. return(ceHError(hr));
  578. }
  579. HRESULT
  580. CCertPolicyExchange::_ReadRegistryStringArray(
  581. IN HKEY hkey,
  582. IN BOOL fURL,
  583. IN DWORD dwFlags,
  584. IN DWORD cRegNames,
  585. IN DWORD *aFlags,
  586. IN WCHAR const * const *apwszRegNames,
  587. IN OUT DWORD *pcStrings,
  588. IN OUT LPWSTR **papstrRegValues)
  589. {
  590. HRESULT hr;
  591. DWORD i;
  592. WCHAR *pwszzValue = NULL;
  593. DWORD cbValue;
  594. DWORD dwType;
  595. for (i = 0; i < cRegNames; i++)
  596. {
  597. if (0 == (dwFlags & aFlags[i]))
  598. {
  599. continue;
  600. }
  601. if (NULL != pwszzValue)
  602. {
  603. LocalFree(pwszzValue);
  604. pwszzValue = NULL;
  605. }
  606. hr = RegQueryValueEx(
  607. hkey,
  608. apwszRegNames[i],
  609. NULL, // lpdwReserved
  610. &dwType,
  611. NULL,
  612. &cbValue);
  613. if (S_OK != hr)
  614. {
  615. _PrintErrorStr2(hr, "RegQueryValueEx", apwszRegNames[i], ERROR_FILE_NOT_FOUND);
  616. continue;
  617. }
  618. if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
  619. {
  620. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  621. _PrintErrorStr(hr, "RegQueryValueEx TYPE", apwszRegNames[i]);
  622. continue;
  623. }
  624. // Handle malformed registry values cleanly by adding two WCHAR L'\0's
  625. // allocate space for 3 WCHARs to allow for unaligned (odd) cbValue;
  626. pwszzValue = (WCHAR *) LocalAlloc(
  627. LMEM_FIXED,
  628. cbValue + 3 * sizeof(WCHAR));
  629. if (NULL == pwszzValue)
  630. {
  631. hr = E_OUTOFMEMORY;
  632. _JumpErrorStr(hr, error, "LocalAlloc", apwszRegNames[i]);
  633. }
  634. hr = RegQueryValueEx(
  635. hkey,
  636. apwszRegNames[i],
  637. NULL, // lpdwReserved
  638. &dwType,
  639. (BYTE *) pwszzValue,
  640. &cbValue);
  641. if (S_OK != hr)
  642. {
  643. _PrintErrorStr(hr, "RegQueryValueEx", apwszRegNames[i]);
  644. continue;
  645. }
  646. // Handle malformed registry values cleanly:
  647. pwszzValue[cbValue / sizeof(WCHAR)] = L'\0';
  648. pwszzValue[cbValue / sizeof(WCHAR) + 1] = L'\0';
  649. hr = _AddStringArray(pwszzValue, fURL, pcStrings, papstrRegValues);
  650. _JumpIfErrorStr(hr, error, "_AddStringArray", apwszRegNames[i]);
  651. }
  652. hr = S_OK;
  653. error:
  654. if (NULL != pwszzValue)
  655. {
  656. LocalFree(pwszzValue);
  657. }
  658. return(hr);
  659. }
  660. //+--------------------------------------------------------------------------
  661. // CCertPolicyExchange::_InitRevocationExtension
  662. //
  663. //+--------------------------------------------------------------------------
  664. VOID
  665. CCertPolicyExchange::_InitRevocationExtension(
  666. IN HKEY hkey)
  667. {
  668. HRESULT hr;
  669. DWORD dwType;
  670. DWORD cb;
  671. DWORD adwFlags[] = {
  672. REVEXT_CDPLDAPURL_OLD,
  673. REVEXT_CDPHTTPURL_OLD,
  674. REVEXT_CDPFTPURL_OLD,
  675. REVEXT_CDPFILEURL_OLD,
  676. };
  677. WCHAR *apwszRegNames[] = {
  678. wszREGLDAPREVOCATIONCRLURL_OLD,
  679. wszREGREVOCATIONCRLURL_OLD,
  680. wszREGFTPREVOCATIONCRLURL_OLD,
  681. wszREGFILEREVOCATIONCRLURL_OLD,
  682. };
  683. cb = sizeof(m_dwRevocationFlags);
  684. hr = RegQueryValueEx(
  685. hkey,
  686. wszREGREVOCATIONTYPE,
  687. NULL, // lpdwReserved
  688. &dwType,
  689. (BYTE *) &m_dwRevocationFlags,
  690. &cb);
  691. if (S_OK != hr ||
  692. REG_DWORD != dwType ||
  693. sizeof(m_dwRevocationFlags) != cb)
  694. {
  695. goto error;
  696. }
  697. DBGPRINT((fDebug, "Revocation Flags = %x\n", m_dwRevocationFlags));
  698. // clean up from previous call
  699. if (NULL != m_ppwszCDPRevocationURL)
  700. {
  701. _FreeStringArray(&m_cCDPRevocationURL, &m_ppwszCDPRevocationURL);
  702. }
  703. if (NULL != m_pwszASPRevocationURL)
  704. {
  705. LocalFree(m_pwszASPRevocationURL);
  706. m_pwszASPRevocationURL = NULL;
  707. }
  708. if (REVEXT_CDPENABLE & m_dwRevocationFlags)
  709. {
  710. assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames));
  711. hr = _ReadRegistryStringArray(
  712. hkey,
  713. TRUE, // fURL
  714. m_dwRevocationFlags,
  715. ARRAYSIZE(adwFlags),
  716. adwFlags,
  717. apwszRegNames,
  718. &m_cCDPRevocationURL,
  719. &m_ppwszCDPRevocationURL);
  720. _JumpIfError(hr, error, "_ReadRegistryStringArray");
  721. _DumpStringArray("CDP", m_cCDPRevocationURL, m_ppwszCDPRevocationURL);
  722. }
  723. if (REVEXT_ASPENABLE & m_dwRevocationFlags)
  724. {
  725. hr = _ReadRegistryString(
  726. hkey,
  727. TRUE, // fURL
  728. wszREGREVOCATIONURL, // pwszRegName
  729. L"?", // pwszSuffix
  730. &m_pwszASPRevocationURL); // pstrRegValue
  731. _JumpIfErrorStr(hr, error, "_ReadRegistryString", wszREGREVOCATIONCRLURL_OLD);
  732. _DumpStringArray("ASP", 1, &m_pwszASPRevocationURL);
  733. }
  734. error:
  735. ;
  736. }
  737. //+--------------------------------------------------------------------------
  738. // CCertPolicyExchange::_InitAuthorityInfoAccessExtension
  739. //
  740. //+--------------------------------------------------------------------------
  741. VOID
  742. CCertPolicyExchange::_InitAuthorityInfoAccessExtension(
  743. IN HKEY hkey)
  744. {
  745. HRESULT hr;
  746. DWORD dwType;
  747. DWORD cb;
  748. DWORD adwFlags[] = {
  749. ISSCERT_LDAPURL_OLD,
  750. ISSCERT_HTTPURL_OLD,
  751. ISSCERT_FTPURL_OLD,
  752. ISSCERT_FILEURL_OLD,
  753. };
  754. WCHAR *apwszRegNames[] = {
  755. wszREGLDAPISSUERCERTURL_OLD,
  756. wszREGISSUERCERTURL_OLD,
  757. wszREGFTPISSUERCERTURL_OLD,
  758. wszREGFILEISSUERCERTURL_OLD,
  759. };
  760. // clean up from previous call
  761. if (NULL != m_ppwszIssuerCertURL)
  762. {
  763. _FreeStringArray(&m_cIssuerCertURL, &m_ppwszIssuerCertURL);
  764. }
  765. cb = sizeof(m_dwIssuerCertURLFlags);
  766. hr = RegQueryValueEx(
  767. hkey,
  768. wszREGISSUERCERTURLFLAGS,
  769. NULL, // lpdwReserved
  770. &dwType,
  771. (BYTE *) &m_dwIssuerCertURLFlags,
  772. &cb);
  773. if (S_OK != hr ||
  774. REG_DWORD != dwType ||
  775. sizeof(m_dwIssuerCertURLFlags) != cb)
  776. {
  777. goto error;
  778. }
  779. DBGPRINT((fDebug, "Issuer Cert Flags = %x\n", m_dwIssuerCertURLFlags));
  780. if (ISSCERT_ENABLE & m_dwIssuerCertURLFlags)
  781. {
  782. assert(ARRAYSIZE(adwFlags) == ARRAYSIZE(apwszRegNames));
  783. hr = _ReadRegistryStringArray(
  784. hkey,
  785. TRUE, // fURL
  786. m_dwIssuerCertURLFlags,
  787. ARRAYSIZE(adwFlags),
  788. adwFlags,
  789. apwszRegNames,
  790. &m_cIssuerCertURL,
  791. &m_ppwszIssuerCertURL);
  792. _JumpIfError(hr, error, "_ReadRegistryStringArray");
  793. _DumpStringArray("Issuer Cert", m_cIssuerCertURL, m_ppwszIssuerCertURL);
  794. }
  795. error:
  796. ;
  797. }
  798. //+--------------------------------------------------------------------------
  799. // CCertPolicyExchange::Initialize
  800. //
  801. // Returns S_OK on success.
  802. //+--------------------------------------------------------------------------
  803. STDMETHODIMP
  804. CCertPolicyExchange::Initialize(
  805. /* [in] */ BSTR const strConfig)
  806. {
  807. HRESULT hr;
  808. HKEY hkey = NULL;
  809. VARIANT varValue;
  810. ICertServerPolicy *pServer = NULL;
  811. BSTR strName = NULL;
  812. VariantInit(&varValue);
  813. _Cleanup();
  814. hr = GetServerCallbackInterface(&pServer, 0);
  815. _JumpIfError(hr, error, "GetServerCallbackInterface");
  816. // get storage location
  817. strName = SysAllocString(wszPROPMODULEREGLOC);
  818. if (NULL == strName)
  819. {
  820. hr = E_OUTOFMEMORY;
  821. _JumpIfError(hr, error, "SysAllocString");
  822. }
  823. hr = pServer->GetCertificateProperty(
  824. strName,
  825. PROPTYPE_STRING,
  826. &varValue);
  827. _JumpIfError(hr, error, "GetCertificateProperty : wszPROPMODULEREGLOC");
  828. m_pwszRegStorageLoc = (WCHAR *) LocalAlloc(
  829. LMEM_FIXED,
  830. (wcslen(varValue.bstrVal) + 1) * sizeof(WCHAR));
  831. if (NULL == m_pwszRegStorageLoc)
  832. {
  833. hr = E_OUTOFMEMORY;
  834. _JumpIfError(hr, error, "LocalAlloc");
  835. }
  836. wcscpy(m_pwszRegStorageLoc, varValue.bstrVal);
  837. VariantClear(&varValue);
  838. hr = PopulateRegistryDefaults(NULL, m_pwszRegStorageLoc);
  839. _PrintIfError(hr, "Policy:PopulateRegistryDefaults");
  840. hr = RegOpenKeyEx(
  841. HKEY_LOCAL_MACHINE,
  842. m_pwszRegStorageLoc,
  843. 0, // dwReserved
  844. KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE,
  845. &hkey);
  846. if ((HRESULT) ERROR_SUCCESS != hr)
  847. {
  848. hr = HRESULT_FROM_WIN32(hr);
  849. _JumpIfError(hr, error, "RegOpenKeyEx");
  850. }
  851. // Initialize the insertion string array.
  852. // Machine DNS name (%1)
  853. SysFreeString(strName);
  854. strName = SysAllocString(wszPROPMACHINEDNSNAME);
  855. if (NULL == strName)
  856. {
  857. hr = E_OUTOFMEMORY;
  858. _JumpIfError(hr, error, "SysAllocString");
  859. }
  860. hr = pServer->GetCertificateProperty(
  861. strName,
  862. PROPTYPE_STRING,
  863. &varValue);
  864. _JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
  865. m_bstrMachineDNSName = SysAllocString(varValue.bstrVal);
  866. if (NULL == m_bstrMachineDNSName)
  867. {
  868. hr = E_OUTOFMEMORY;
  869. _JumpIfError(hr, error, "SysAllocString");
  870. }
  871. VariantClear(&varValue);
  872. SysFreeString(strName);
  873. strName = SysAllocString(wszPROPCERTCOUNT);
  874. if (NULL == strName)
  875. {
  876. hr = E_OUTOFMEMORY;
  877. _JumpIfError(hr, error, "SysAllocString");
  878. }
  879. hr = pServer->GetCertificateProperty(
  880. strName,
  881. PROPTYPE_LONG,
  882. &varValue);
  883. _JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
  884. m_iCert = varValue.lVal - 1;
  885. SysFreeString(strName);
  886. strName = SysAllocString(wszPROPCRLINDEX);
  887. if (NULL == strName)
  888. {
  889. hr = E_OUTOFMEMORY;
  890. _JumpIfError(hr, error, "SysAllocString");
  891. }
  892. hr = pServer->GetCertificateProperty(
  893. strName,
  894. PROPTYPE_LONG,
  895. &varValue);
  896. _JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
  897. m_iCRL = varValue.lVal;
  898. // get sanitized name
  899. SysFreeString(strName);
  900. strName = SysAllocString(wszPROPSANITIZEDCANAME);
  901. if (NULL == strName)
  902. {
  903. hr = E_OUTOFMEMORY;
  904. _JumpIfError(hr, error, "SysAllocString");
  905. }
  906. hr = pServer->GetCertificateProperty(
  907. strName,
  908. PROPTYPE_STRING,
  909. &varValue);
  910. _JumpIfErrorStr(hr, error, "GetCertificateProperty", strName);
  911. m_bstrCASanitizedName = SysAllocString(varValue.bstrVal);
  912. if (NULL == m_bstrCASanitizedName)
  913. {
  914. hr = E_OUTOFMEMORY;
  915. _JumpIfError(hr, error, "SysAllocString");
  916. }
  917. VariantClear(&varValue);
  918. _InitRevocationExtension(hkey);
  919. _InitAuthorityInfoAccessExtension(hkey);
  920. hr = S_OK;
  921. error:
  922. VariantClear(&varValue);
  923. if (NULL != strName)
  924. {
  925. SysFreeString(strName);
  926. }
  927. if (NULL != hkey)
  928. {
  929. RegCloseKey(hkey);
  930. }
  931. if (NULL != pServer)
  932. {
  933. pServer->Release();
  934. }
  935. return(hr);
  936. }
  937. HRESULT
  938. EnumerateExtensions(
  939. IN ICertServerPolicy *pServer)
  940. {
  941. HRESULT hr;
  942. HRESULT hr2;
  943. BSTR strName = NULL;
  944. LONG ExtFlags;
  945. VARIANT varValue;
  946. BOOL fClose = FALSE;
  947. VariantInit(&varValue);
  948. hr = pServer->EnumerateExtensionsSetup(0);
  949. _JumpIfError(hr, error, "EnumerateExtensionsSetup");
  950. fClose = TRUE;
  951. while (TRUE)
  952. {
  953. hr = pServer->EnumerateExtensions(&strName);
  954. if (S_OK != hr)
  955. {
  956. if (S_FALSE == hr)
  957. {
  958. hr = S_OK;
  959. break;
  960. }
  961. _JumpError(hr, error, "EnumerateExtensions");
  962. }
  963. hr = pServer->GetCertificateExtension(
  964. strName,
  965. PROPTYPE_BINARY,
  966. &varValue);
  967. _JumpIfError(hr, error, "GetCertificateExtension");
  968. hr = pServer->GetCertificateExtensionFlags(&ExtFlags);
  969. _JumpIfError(hr, error, "GetCertificateExtensionFlags");
  970. if (fDebug)
  971. {
  972. wprintf(
  973. L"Policy:EnumerateExtensions(%ws, Flags=%x, %x bytes)\n",
  974. strName,
  975. ExtFlags,
  976. SysStringByteLen(varValue.bstrVal));
  977. }
  978. VariantClear(&varValue);
  979. }
  980. error:
  981. if (fClose)
  982. {
  983. hr2 = pServer->EnumerateExtensionsClose();
  984. if (S_OK != hr2)
  985. {
  986. _PrintError(hr2, "Policy:EnumerateExtensionsClose");
  987. if (S_OK == hr)
  988. {
  989. hr = hr2;
  990. }
  991. }
  992. }
  993. if (NULL != strName)
  994. {
  995. SysFreeString(strName);
  996. }
  997. VariantClear(&varValue);
  998. return(hr);
  999. }
  1000. HRESULT
  1001. EnumerateAttributes(
  1002. IN ICertServerPolicy *pServer)
  1003. {
  1004. HRESULT hr;
  1005. HRESULT hr2;
  1006. BSTR strName = NULL;
  1007. BOOL fClose = FALSE;
  1008. BSTR strValue = NULL;
  1009. hr = pServer->EnumerateAttributesSetup(0);
  1010. _JumpIfError(hr, error, "EnumerateAttributesSetup");
  1011. fClose = TRUE;
  1012. while (TRUE)
  1013. {
  1014. hr = pServer->EnumerateAttributes(&strName);
  1015. if (S_OK != hr)
  1016. {
  1017. if (S_FALSE == hr)
  1018. {
  1019. hr = S_OK;
  1020. break;
  1021. }
  1022. _JumpError(hr, error, "EnumerateAttributes");
  1023. }
  1024. hr = pServer->GetRequestAttribute(strName, &strValue);
  1025. _JumpIfError(hr, error, "GetRequestAttribute");
  1026. if (fDebug)
  1027. {
  1028. wprintf(
  1029. L"Policy:EnumerateAttributes(%ws = %ws)\n",
  1030. strName,
  1031. strValue);
  1032. }
  1033. if (NULL != strValue)
  1034. {
  1035. SysFreeString(strValue);
  1036. strValue = NULL;
  1037. }
  1038. }
  1039. error:
  1040. if (fClose)
  1041. {
  1042. hr2 = pServer->EnumerateAttributesClose();
  1043. if (S_OK != hr2)
  1044. {
  1045. _PrintError(hr2, "Policy:EnumerateAttributesClose");
  1046. if (S_OK == hr)
  1047. {
  1048. hr = hr2;
  1049. }
  1050. }
  1051. }
  1052. if (NULL != strName)
  1053. {
  1054. SysFreeString(strName);
  1055. }
  1056. if (NULL != strValue)
  1057. {
  1058. SysFreeString(strValue);
  1059. }
  1060. return(hr);
  1061. }
  1062. HRESULT
  1063. CheckRequestProperties(
  1064. IN ICertServerPolicy *pServer)
  1065. {
  1066. HRESULT hr;
  1067. VARIANT varValue;
  1068. BSTR strName = NULL;
  1069. VariantInit(&varValue);
  1070. strName = SysAllocString(wszPROPREQUESTREQUESTID);
  1071. if (NULL == strName)
  1072. {
  1073. hr = E_OUTOFMEMORY;
  1074. _JumpError(hr, error, "SysAllocString");
  1075. }
  1076. hr = pServer->GetRequestProperty(strName, PROPTYPE_LONG, &varValue);
  1077. _JumpIfError(hr, error, "GetRequestProperty");
  1078. if (fDebug)
  1079. {
  1080. wprintf(
  1081. L"Policy:CheckRequestProperties(%ws = %x)\n",
  1082. strName,
  1083. varValue.lVal);
  1084. }
  1085. VariantClear(&varValue);
  1086. error:
  1087. if (NULL != strName)
  1088. {
  1089. SysFreeString(strName);
  1090. }
  1091. return(hr);
  1092. }
  1093. //+--------------------------------------------------------------------------
  1094. // CCertPolicyExchange::_AddRevocationExtension
  1095. //
  1096. // Returns S_OK on success.
  1097. //+--------------------------------------------------------------------------
  1098. HRESULT
  1099. CCertPolicyExchange::_AddRevocationExtension(
  1100. IN ICertServerPolicy *pServer)
  1101. {
  1102. HRESULT hr = S_OK;
  1103. ICertEncodeCRLDistInfo *pCRLDist = NULL;
  1104. BSTR strCDPName = NULL;
  1105. BSTR strCDPExtension = NULL;
  1106. BSTR strName = NULL;
  1107. BSTR strExtension = NULL;
  1108. VARIANT varExtension;
  1109. DWORD i;
  1110. varExtension.vt = VT_BSTR;
  1111. if (NULL != m_ppwszCDPRevocationURL)
  1112. {
  1113. hr = CoCreateInstance(
  1114. CLSID_CCertEncodeCRLDistInfo,
  1115. NULL, // pUnkOuter
  1116. CLSCTX_INPROC_SERVER,
  1117. IID_ICertEncodeCRLDistInfo,
  1118. (VOID **) &pCRLDist);
  1119. _JumpIfError(hr, error, "CoCreateInstance");
  1120. hr = pCRLDist->Reset(m_cCDPRevocationURL);
  1121. _JumpIfError(hr, error, "Reset");
  1122. for (i = 0; i < m_cCDPRevocationURL; i++)
  1123. {
  1124. DWORD j;
  1125. hr = pCRLDist->SetNameCount(i, 1);
  1126. _JumpIfError(hr, error, "SetNameCount");
  1127. for (j = 0; j < 1; j++)
  1128. {
  1129. BSTR str = SysAllocString(m_ppwszCDPRevocationURL[i]);
  1130. if (NULL == str)
  1131. {
  1132. hr = E_OUTOFMEMORY;
  1133. _JumpError(hr, error, "SysAllocString");
  1134. }
  1135. hr = pCRLDist->SetNameEntry(i, j, CERT_ALT_NAME_URL, str);
  1136. SysFreeString(str);
  1137. _JumpIfError(hr, error, "SetNameEntry");
  1138. }
  1139. }
  1140. hr = pCRLDist->Encode(&strCDPExtension);
  1141. _JumpIfError(hr, error, "Encode");
  1142. strCDPName = SysAllocString(TEXT(szOID_CRL_DIST_POINTS));
  1143. varExtension.bstrVal = strCDPExtension;
  1144. hr = pServer->SetCertificateExtension(
  1145. strCDPName,
  1146. PROPTYPE_BINARY,
  1147. 0,
  1148. &varExtension);
  1149. _JumpIfErrorStr(hr, error, "SetCertificateExtension", L"CDP");
  1150. }
  1151. if (NULL != m_pwszASPRevocationURL)
  1152. {
  1153. strName = SysAllocString(TEXT(szOID_NETSCAPE_REVOCATION_URL));
  1154. strExtension = SysAllocString(m_pwszASPRevocationURL);
  1155. if (NULL == strName || NULL == strExtension)
  1156. {
  1157. hr = E_OUTOFMEMORY;
  1158. _JumpError(hr, error, "SysAllocString");
  1159. }
  1160. varExtension.bstrVal = strExtension;
  1161. hr = pServer->SetCertificateExtension(
  1162. strName,
  1163. PROPTYPE_STRING,
  1164. 0,
  1165. &varExtension);
  1166. _JumpIfErrorStr(hr, error, "SetCertificateExtension", L"ASP");
  1167. VariantClear(&varExtension);
  1168. }
  1169. error:
  1170. if (NULL != strName)
  1171. {
  1172. SysFreeString(strName);
  1173. }
  1174. if (NULL != strExtension)
  1175. {
  1176. SysFreeString(strExtension);
  1177. }
  1178. if (NULL != strCDPName)
  1179. {
  1180. SysFreeString(strCDPName);
  1181. }
  1182. if (NULL != strCDPExtension)
  1183. {
  1184. SysFreeString(strCDPExtension);
  1185. }
  1186. if (NULL != pCRLDist)
  1187. {
  1188. pCRLDist->Release();
  1189. }
  1190. return(hr);
  1191. }
  1192. //+--------------------------------------------------------------------------
  1193. // CCertPolicyExchange::_AddAuthorityInfoAccessExtension
  1194. //
  1195. // Returns S_OK on success.
  1196. //+--------------------------------------------------------------------------
  1197. HRESULT
  1198. CCertPolicyExchange::_AddAuthorityInfoAccessExtension(
  1199. IN ICertServerPolicy *pServer)
  1200. {
  1201. HRESULT hr = S_OK;
  1202. BYTE *pbEncoded = NULL;
  1203. DWORD cbEncoded;
  1204. BSTR strName = NULL;
  1205. BSTR strExtension = NULL;
  1206. VARIANT varExtension;
  1207. DWORD i;
  1208. CERT_AUTHORITY_INFO_ACCESS caio;
  1209. caio.rgAccDescr = NULL;
  1210. if (NULL == m_ppwszIssuerCertURL)
  1211. {
  1212. goto error;
  1213. }
  1214. caio.cAccDescr = m_cIssuerCertURL;
  1215. caio.rgAccDescr = (CERT_ACCESS_DESCRIPTION *) LocalAlloc(
  1216. LMEM_FIXED,
  1217. sizeof(CERT_ACCESS_DESCRIPTION) * m_cIssuerCertURL);
  1218. if (NULL == caio.rgAccDescr)
  1219. {
  1220. hr = E_OUTOFMEMORY;
  1221. _JumpIfError(hr, error, "LocalAlloc");
  1222. }
  1223. for (i = 0; i < m_cIssuerCertURL; i++)
  1224. {
  1225. caio.rgAccDescr[i].pszAccessMethod = szOID_PKIX_CA_ISSUERS;
  1226. caio.rgAccDescr[i].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
  1227. caio.rgAccDescr[i].AccessLocation.pwszURL = m_ppwszIssuerCertURL[i];
  1228. }
  1229. if (!ceEncodeObject(
  1230. X509_ASN_ENCODING,
  1231. X509_AUTHORITY_INFO_ACCESS,
  1232. &caio,
  1233. 0,
  1234. FALSE,
  1235. &pbEncoded,
  1236. &cbEncoded))
  1237. {
  1238. hr = ceHLastError();
  1239. _JumpIfError(hr, error, "Policy:ceEncodeObject");
  1240. }
  1241. if (!ceConvertWszToBstr(
  1242. &strExtension,
  1243. (WCHAR const *) pbEncoded,
  1244. cbEncoded))
  1245. {
  1246. hr = E_OUTOFMEMORY;
  1247. _JumpError(hr, error, "ceConvertWszToBstr");
  1248. }
  1249. strName = SysAllocString(TEXT(szOID_AUTHORITY_INFO_ACCESS));
  1250. if (NULL == strName)
  1251. {
  1252. hr = E_OUTOFMEMORY;
  1253. _JumpError(hr, error, "SysAllocString");
  1254. }
  1255. varExtension.vt = VT_BSTR;
  1256. varExtension.bstrVal = strExtension;
  1257. hr = pServer->SetCertificateExtension(
  1258. strName,
  1259. PROPTYPE_BINARY,
  1260. 0,
  1261. &varExtension);
  1262. _JumpIfError(hr, error, "SetCertificateExtension(AuthInfoAccess)");
  1263. error:
  1264. if (NULL != pbEncoded)
  1265. {
  1266. LocalFree(pbEncoded);
  1267. }
  1268. if (NULL != strName)
  1269. {
  1270. SysFreeString(strName);
  1271. }
  1272. if (NULL != strExtension)
  1273. {
  1274. SysFreeString(strExtension);
  1275. }
  1276. if (NULL != caio.rgAccDescr)
  1277. {
  1278. LocalFree(caio.rgAccDescr);
  1279. }
  1280. return(hr);
  1281. }
  1282. //+--------------------------------------------------------------------------
  1283. // CCertPolicyExchange::_AddIssuerAltName2Extension
  1284. //
  1285. // Returns S_OK on success.
  1286. //+--------------------------------------------------------------------------
  1287. HRESULT
  1288. CCertPolicyExchange::_AddIssuerAltName2Extension(
  1289. IN ICertServerPolicy *pServer)
  1290. {
  1291. HRESULT hr = S_OK;
  1292. BSTR strExtension = NULL;
  1293. VARIANT varExtension;
  1294. BSTR strCertType = NULL;
  1295. BSTR strName = NULL;
  1296. BSTR strValue = NULL;
  1297. BSTR strKMServerName = NULL;
  1298. LPBYTE pbEncName = NULL;
  1299. ULONG cbEncName = 0;
  1300. LPBYTE pbEncExten = NULL;
  1301. ULONG cbEncExten = 0;
  1302. CERT_ALT_NAME_ENTRY cane = { 0 };
  1303. CERT_ALT_NAME_INFO cani = { 0 };
  1304. strKMServerName = SysAllocString(k_wszKMServerName);
  1305. if (NULL == strKMServerName)
  1306. {
  1307. hr = E_OUTOFMEMORY;
  1308. _JumpError(hr, error, "SysAllocString");
  1309. }
  1310. hr = pServer->GetRequestAttribute(strKMServerName, &strValue);
  1311. _JumpIfErrorStr(
  1312. hr,
  1313. error,
  1314. CERTSRV_E_PROPERTY_EMPTY == hr?
  1315. "MISSING ATTRIBUTE -- GetRequestAttribute" :
  1316. "GetRequestAttribute",
  1317. k_wszKMServerName);
  1318. // CertStrToName to turn string into encoded name blob
  1319. if (!CertStrToNameW(
  1320. X509_ASN_ENCODING,
  1321. strValue,
  1322. CERT_X500_NAME_STR,
  1323. NULL,
  1324. NULL,
  1325. &cbEncName,
  1326. NULL))
  1327. {
  1328. hr = E_INVALIDARG;
  1329. _JumpError(hr, error, "CertStrToNameW");
  1330. }
  1331. pbEncName = new BYTE [cbEncName];
  1332. if (NULL == pbEncName)
  1333. {
  1334. hr = E_OUTOFMEMORY;
  1335. _JumpError(hr, error, "new");
  1336. }
  1337. if (!CertStrToNameW(
  1338. X509_ASN_ENCODING,
  1339. strValue,
  1340. CERT_X500_NAME_STR,
  1341. NULL,
  1342. pbEncName,
  1343. &cbEncName,
  1344. NULL))
  1345. {
  1346. hr = E_INVALIDARG;
  1347. _JumpError(hr, error, "CertStrToNameW");
  1348. }
  1349. // fill in alt name info
  1350. cane.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
  1351. cane.DirectoryName.cbData = cbEncName;
  1352. cane.DirectoryName.pbData = pbEncName;
  1353. cani.cAltEntry = 1;
  1354. cani.rgAltEntry = &cane;
  1355. // encode alt name info
  1356. if (!CryptEncodeObject(
  1357. X509_ASN_ENCODING,
  1358. X509_ALTERNATE_NAME,
  1359. &cani,
  1360. NULL,
  1361. &cbEncExten))
  1362. {
  1363. hr = E_INVALIDARG;
  1364. _JumpError(hr, error, "CryptEncodeObject");
  1365. }
  1366. pbEncExten = new BYTE [cbEncExten];
  1367. if (NULL == pbEncExten)
  1368. {
  1369. hr = E_OUTOFMEMORY;
  1370. _JumpError(hr, error, "new");
  1371. }
  1372. if (!CryptEncodeObject(
  1373. X509_ASN_ENCODING,
  1374. X509_ALTERNATE_NAME,
  1375. &cani,
  1376. pbEncExten,
  1377. &cbEncExten))
  1378. {
  1379. hr = E_INVALIDARG;
  1380. _JumpError(hr, error, "CryptEncodeObject");
  1381. }
  1382. strName = SysAllocString(TEXT(szOID_ISSUER_ALT_NAME2));
  1383. strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
  1384. if (NULL == strName || NULL == strExtension)
  1385. {
  1386. hr = E_OUTOFMEMORY;
  1387. _JumpError(hr, error, "SysAllocString");
  1388. }
  1389. // add extension
  1390. varExtension.vt = VT_BSTR;
  1391. varExtension.bstrVal = strExtension;
  1392. hr = pServer->SetCertificateExtension(
  1393. strName,
  1394. PROPTYPE_BINARY,
  1395. 0,
  1396. &varExtension);
  1397. _JumpIfError(hr, error, "SetCertificateExtension(IssuerAltName2)");
  1398. error:
  1399. delete [] pbEncName;
  1400. delete [] pbEncExten;
  1401. if (NULL != strName)
  1402. {
  1403. SysFreeString(strName);
  1404. }
  1405. if (NULL != strExtension)
  1406. {
  1407. SysFreeString(strExtension);
  1408. }
  1409. if (NULL != strKMServerName)
  1410. {
  1411. SysFreeString(strKMServerName);
  1412. }
  1413. return(hr);
  1414. }
  1415. //+--------------------------------------------------------------------------
  1416. // CCertPolicyExchange::_AddSubjectAltName2Extension
  1417. //
  1418. // Returns S_OK on success.
  1419. // Returns S_FALSE for special request.
  1420. //+--------------------------------------------------------------------------
  1421. HRESULT
  1422. CCertPolicyExchange::_AddSubjectAltName2Extension(
  1423. IN ICertServerPolicy *pServer)
  1424. {
  1425. HRESULT hr = S_OK;
  1426. BSTR strExtension = NULL;
  1427. VARIANT varExtension;
  1428. BSTR strCertType = NULL;
  1429. BSTR strName = NULL;
  1430. BSTR strDisplay = NULL;
  1431. BSTR strRFC822 = NULL;
  1432. BSTR strSubjAltNameRFC822 = NULL;
  1433. BSTR strSubjAltNameDisplay = NULL;
  1434. LPBYTE pbEncName = NULL;
  1435. ULONG cbEncName = 0;
  1436. LPBYTE pbEncExten = NULL;
  1437. ULONG cbEncExten = 0;
  1438. CERT_RDN_ATTR rdnattr = { 0 };
  1439. CERT_RDN rdn = { 0 };
  1440. CERT_NAME_INFO cni = { 0 };
  1441. CERT_ALT_NAME_ENTRY acane [2] = { 0 };
  1442. CERT_ALT_NAME_INFO cani = { 0 };
  1443. strSubjAltNameDisplay = SysAllocString(k_wszSubjAltNameDisplay);
  1444. if (NULL == strSubjAltNameDisplay)
  1445. {
  1446. hr = E_OUTOFMEMORY;
  1447. _JumpError(hr, error, "SysAllocString");
  1448. }
  1449. hr = pServer->GetRequestAttribute(strSubjAltNameDisplay, &strDisplay);
  1450. _JumpIfErrorStr(
  1451. hr,
  1452. error,
  1453. CERTSRV_E_PROPERTY_EMPTY == hr?
  1454. "MISSING ATTRIBUTE -- GetRequestAttribute" :
  1455. "GetRequestAttribute",
  1456. k_wszSubjAltNameDisplay);
  1457. strSubjAltNameRFC822 = SysAllocString(k_wszSubjAltNameRFC822);
  1458. if (NULL == strSubjAltNameRFC822)
  1459. {
  1460. hr = E_OUTOFMEMORY;
  1461. _JumpError(hr, error, "SysAllocString");
  1462. }
  1463. hr = pServer->GetRequestAttribute(strSubjAltNameRFC822, &strRFC822);
  1464. _JumpIfErrorStr(
  1465. hr,
  1466. error,
  1467. CERTSRV_E_PROPERTY_EMPTY == hr?
  1468. "MISSING ATTRIBUTE -- GetRequestAttribute" :
  1469. "GetRequestAttribute",
  1470. k_wszSubjAltNameRFC822);
  1471. // this identifies special request from KMS
  1472. if (0 == lstrcmpW(strDisplay, k_wszSpecialAttribute) &&
  1473. 0 == lstrcmpW(strRFC822, k_wszSpecialAttribute))
  1474. {
  1475. hr = _AddSpecialAltNameExtension(pServer);
  1476. _JumpIfError(hr, error, "_AddSpecialAltNameExtension");
  1477. // there are no subject names to add, so exit
  1478. goto error;
  1479. }
  1480. // encode display name
  1481. rdnattr.pszObjId = szOID_COMMON_NAME;
  1482. rdnattr.dwValueType = CERT_RDN_UNICODE_STRING;
  1483. rdnattr.Value.cbData = SysStringByteLen(strDisplay);
  1484. rdnattr.Value.pbData = (LPBYTE) strDisplay;
  1485. rdn.cRDNAttr = 1;
  1486. rdn.rgRDNAttr = &rdnattr;
  1487. cni.cRDN = 1;
  1488. cni.rgRDN = &rdn;
  1489. if (!CryptEncodeObject(
  1490. X509_ASN_ENCODING,
  1491. X509_NAME,
  1492. &cni,
  1493. NULL,
  1494. &cbEncName))
  1495. {
  1496. hr = E_INVALIDARG;
  1497. _JumpError(hr, error, "CryptEncodeObject");
  1498. }
  1499. pbEncName = new BYTE [cbEncName];
  1500. if (NULL == pbEncName)
  1501. {
  1502. hr = E_OUTOFMEMORY;
  1503. _JumpError(hr, error, "new");
  1504. }
  1505. if (!CryptEncodeObject(
  1506. X509_ASN_ENCODING,
  1507. X509_NAME,
  1508. &cni,
  1509. pbEncName,
  1510. &cbEncName))
  1511. {
  1512. hr = E_INVALIDARG;
  1513. _JumpError(hr, error, "CryptEncodeObject");
  1514. }
  1515. // fill in alt name info
  1516. acane[0].dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
  1517. acane[0].DirectoryName.cbData = cbEncName;
  1518. acane[0].DirectoryName.pbData = pbEncName;
  1519. acane[1].dwAltNameChoice = CERT_ALT_NAME_RFC822_NAME;
  1520. acane[1].pwszRfc822Name = strRFC822;
  1521. cani.cAltEntry = 2;
  1522. cani.rgAltEntry = acane;
  1523. // encode alt name info
  1524. if (!CryptEncodeObject(
  1525. X509_ASN_ENCODING,
  1526. X509_ALTERNATE_NAME,
  1527. &cani,
  1528. NULL,
  1529. &cbEncExten))
  1530. {
  1531. hr = E_INVALIDARG;
  1532. _JumpError(hr, error, "CryptEncodeObject");
  1533. }
  1534. pbEncExten = new BYTE [cbEncExten];
  1535. if (NULL == pbEncExten)
  1536. {
  1537. hr = E_OUTOFMEMORY;
  1538. _JumpError(hr, error, "new");
  1539. }
  1540. if (!CryptEncodeObject(
  1541. X509_ASN_ENCODING,
  1542. X509_ALTERNATE_NAME,
  1543. &cani,
  1544. pbEncExten,
  1545. &cbEncExten))
  1546. {
  1547. hr = E_INVALIDARG;
  1548. _JumpError(hr, error, "CryptEncodeObject");
  1549. }
  1550. strName = SysAllocString(TEXT(szOID_SUBJECT_ALT_NAME2));
  1551. strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
  1552. if (NULL == strName || NULL == strExtension)
  1553. {
  1554. hr = E_OUTOFMEMORY;
  1555. _JumpError(hr, error, "SysAllocString");
  1556. }
  1557. // add extension
  1558. varExtension.vt = VT_BSTR;
  1559. varExtension.bstrVal = strExtension;
  1560. hr = pServer->SetCertificateExtension(
  1561. strName,
  1562. PROPTYPE_BINARY,
  1563. 0,
  1564. &varExtension);
  1565. _JumpIfError(hr, error, "SetCertificateExtension");
  1566. error:
  1567. if (NULL != strName)
  1568. {
  1569. SysFreeString(strName);
  1570. }
  1571. if (NULL != strExtension)
  1572. {
  1573. SysFreeString(strExtension);
  1574. }
  1575. if (NULL != strSubjAltNameRFC822)
  1576. {
  1577. SysFreeString(strSubjAltNameRFC822);
  1578. }
  1579. if (NULL != strSubjAltNameDisplay)
  1580. {
  1581. SysFreeString(strSubjAltNameDisplay);
  1582. }
  1583. return(hr);
  1584. }
  1585. //+--------------------------------------------------------------------------
  1586. // CCertPolicyExchange::_AddSpecialAltNameExtension
  1587. //
  1588. // in response to request with both display and RFC822 equal to special value,
  1589. // fetch version info for CertSrv.exe and ExPolicy.dll, encode as multi-byte
  1590. // int, and set as IssuerAltName, marked critical. this should make cert
  1591. // unusable.
  1592. //
  1593. // Returns S_OK on success.
  1594. //+--------------------------------------------------------------------------
  1595. HRESULT
  1596. CCertPolicyExchange::_AddSpecialAltNameExtension(
  1597. IN ICertServerPolicy *pServer)
  1598. {
  1599. HRESULT hr = S_OK;
  1600. BSTR strName = NULL;
  1601. BSTR strExtension = NULL;
  1602. VARIANT varExtension;
  1603. HRSRC hExeVersion = NULL;
  1604. HGLOBAL hExeVersionInMem = NULL;
  1605. LPBYTE pExeVersion = NULL;
  1606. // [0] to [3] are ExPolicy version.
  1607. // [4] to [7] are CertServer version.
  1608. WORD awVersions [] =
  1609. { rmj, rmn, rmm, rup, 0, 0, 0, 0 };
  1610. ULONG ndxCertServer = 4;
  1611. CRYPT_INTEGER_BLOB intblobVersions = { 0 };
  1612. LPBYTE pbEncExten = NULL;
  1613. ULONG cbEncExten = 0;
  1614. // fill in version info
  1615. if (NULL == (hExeVersion =
  1616. FindResource(NULL, MAKEINTRESOURCE(1), RT_VERSION)) ||
  1617. NULL == (hExeVersionInMem = LoadResource(NULL, hExeVersion)) ||
  1618. NULL == (pExeVersion = (LPBYTE) LockResource(hExeVersionInMem)))
  1619. {
  1620. hr = E_OUTOFMEMORY;
  1621. _JumpError(hr, error, "Find/Load/LockResource");
  1622. }
  1623. awVersions[ndxCertServer] = ((LPWORD)pExeVersion)[25];
  1624. awVersions[ndxCertServer + 1] = ((LPWORD)pExeVersion)[24];
  1625. awVersions[ndxCertServer + 2] = ((LPWORD)pExeVersion)[27];
  1626. awVersions[ndxCertServer + 3] = ((LPWORD)pExeVersion)[26];
  1627. intblobVersions.cbData = sizeof(awVersions);
  1628. intblobVersions.pbData = (LPBYTE) awVersions;
  1629. // encode version info
  1630. if (!CryptEncodeObject(
  1631. X509_ASN_ENCODING,
  1632. X509_MULTI_BYTE_INTEGER,
  1633. &intblobVersions,
  1634. NULL,
  1635. &cbEncExten))
  1636. {
  1637. hr = E_INVALIDARG;
  1638. _JumpError(hr, error, "CryptEncodeObject");
  1639. }
  1640. pbEncExten = new BYTE [cbEncExten];
  1641. if (NULL == pbEncExten)
  1642. {
  1643. hr = E_OUTOFMEMORY;
  1644. _JumpError(hr, error, "new");
  1645. }
  1646. if (!CryptEncodeObject(
  1647. X509_ASN_ENCODING,
  1648. X509_MULTI_BYTE_INTEGER,
  1649. &intblobVersions,
  1650. pbEncExten,
  1651. &cbEncExten))
  1652. {
  1653. hr = E_INVALIDARG;
  1654. _JumpError(hr, error, "CryptEncodeObject");
  1655. }
  1656. strName = SysAllocString(TEXT(szOID_ISSUER_ALT_NAME));
  1657. strExtension = SysAllocStringByteLen((char *) pbEncExten, cbEncExten);
  1658. if (NULL == strName || NULL == strExtension)
  1659. {
  1660. hr = E_OUTOFMEMORY;
  1661. _JumpError(hr, error, "SysAllocString");
  1662. }
  1663. // add extension
  1664. varExtension.vt = VT_BSTR;
  1665. varExtension.bstrVal = strExtension;
  1666. hr = pServer->SetCertificateExtension(
  1667. strName,
  1668. PROPTYPE_BINARY,
  1669. EXTENSION_CRITICAL_FLAG,
  1670. &varExtension);
  1671. _JumpIfError(hr, error, "SetCertificateExtension");
  1672. error:
  1673. if (NULL != strName)
  1674. {
  1675. SysFreeString(strName);
  1676. }
  1677. if (NULL != strExtension)
  1678. {
  1679. SysFreeString(strExtension);
  1680. }
  1681. delete [] pbEncExten;
  1682. return(hr);
  1683. }
  1684. //+--------------------------------------------------------------------------
  1685. // CCertPolicyExchange::_AddBasicConstraintsExtension
  1686. //
  1687. // Returns S_OK on success.
  1688. //+--------------------------------------------------------------------------
  1689. HRESULT
  1690. CCertPolicyExchange::_AddBasicConstraintsExtension(
  1691. IN ICertServerPolicy *pServer)
  1692. {
  1693. HRESULT hr = S_OK;
  1694. BYTE *pbEncoded = NULL;
  1695. DWORD cbEncoded;
  1696. CERT_BASIC_CONSTRAINTS2_INFO bc2i;
  1697. BSTR strName = NULL;
  1698. BSTR strExtension = NULL;
  1699. VARIANT varExtension;
  1700. bc2i.fCA = FALSE;
  1701. bc2i.fPathLenConstraint = FALSE;
  1702. bc2i.dwPathLenConstraint = 0;
  1703. if (!ceEncodeObject(
  1704. X509_ASN_ENCODING,
  1705. X509_BASIC_CONSTRAINTS2,
  1706. &bc2i,
  1707. 0,
  1708. FALSE,
  1709. &pbEncoded,
  1710. &cbEncoded))
  1711. {
  1712. hr = GetLastError();
  1713. _JumpError(hr, error, "ceEncodeObject");
  1714. }
  1715. if (!ceConvertWszToBstr(
  1716. &strExtension,
  1717. (WCHAR const *) pbEncoded,
  1718. cbEncoded))
  1719. {
  1720. hr = E_OUTOFMEMORY;
  1721. _JumpError(hr, error, "ceConvertWszToBstr");
  1722. }
  1723. strName = SysAllocString(TEXT(szOID_BASIC_CONSTRAINTS2));
  1724. if (NULL == strName)
  1725. {
  1726. hr = E_OUTOFMEMORY;
  1727. _JumpError(hr, error, "SysAllocString");
  1728. }
  1729. varExtension.vt = VT_BSTR;
  1730. varExtension.bstrVal = strExtension;
  1731. hr = pServer->SetCertificateExtension(
  1732. strName,
  1733. PROPTYPE_BINARY,
  1734. 0,
  1735. &varExtension);
  1736. _JumpIfError(hr, error, "SetCertificateExtension");
  1737. error:
  1738. if (NULL != pbEncoded)
  1739. {
  1740. LocalFree(pbEncoded);
  1741. }
  1742. if (NULL != strName)
  1743. {
  1744. SysFreeString(strName);
  1745. }
  1746. if (NULL != strExtension)
  1747. {
  1748. SysFreeString(strExtension);
  1749. }
  1750. return(hr);
  1751. }
  1752. //+--------------------------------------------------------------------------
  1753. // CCertPolicyExchange::_AddKeyUsageExtension
  1754. //
  1755. // Returns S_OK on success.
  1756. //+--------------------------------------------------------------------------
  1757. HRESULT
  1758. CCertPolicyExchange::_AddKeyUsageExtension(
  1759. IN ICertServerPolicy *pServer)
  1760. {
  1761. HRESULT hr = S_OK;
  1762. BSTR strName = NULL;
  1763. ICertEncodeBitString *pBitString = NULL;
  1764. BSTR strExtension = NULL;
  1765. VARIANT varExtension;
  1766. BYTE KeyUsage = 0;
  1767. BSTR strBitString = NULL;
  1768. BSTR strKeyUsage = NULL;
  1769. BSTR strValue = NULL;
  1770. strKeyUsage = SysAllocString(k_wszKeyUsage);
  1771. if (NULL == strKeyUsage)
  1772. {
  1773. hr = E_OUTOFMEMORY;
  1774. _JumpError(hr, error, "SysAllocString");
  1775. }
  1776. hr = pServer->GetRequestAttribute(strKeyUsage, &strValue);
  1777. _JumpIfErrorStr(
  1778. hr,
  1779. error,
  1780. CERTSRV_E_PROPERTY_EMPTY == hr?
  1781. "MISSING ATTRIBUTE -- GetRequestAttribute" :
  1782. "GetRequestAttribute",
  1783. k_wszKeyUsage);
  1784. if (0 == wcscmp(strValue, k_wszUsageSealing))
  1785. {
  1786. KeyUsage = CERT_KEY_ENCIPHERMENT_KEY_USAGE;
  1787. }
  1788. else
  1789. if (0 == wcscmp(strValue, k_wszUsageSigning))
  1790. {
  1791. KeyUsage = CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  1792. CERT_NON_REPUDIATION_KEY_USAGE;
  1793. }
  1794. else
  1795. {
  1796. hr = E_INVALIDARG;
  1797. _JumpError(hr, error, "KeyUsage");
  1798. }
  1799. hr = CoCreateInstance(
  1800. CLSID_CCertEncodeBitString,
  1801. NULL, // pUnkOuter
  1802. CLSCTX_INPROC_SERVER,
  1803. IID_ICertEncodeBitString,
  1804. (VOID **) &pBitString);
  1805. _JumpIfError(hr, error, "CoCreateInstance");
  1806. if (!ceConvertWszToBstr(
  1807. &strBitString,
  1808. (WCHAR const *) &KeyUsage,
  1809. sizeof(KeyUsage)))
  1810. {
  1811. hr = E_OUTOFMEMORY;
  1812. _JumpError(hr, error, "ceConvertWszToBstr");
  1813. }
  1814. hr = pBitString->Encode(
  1815. sizeof(KeyUsage) * 8,
  1816. strBitString,
  1817. &strExtension);
  1818. _JumpIfError(hr, error, "Encode");
  1819. if (!ceConvertWszToBstr(&strName, TEXT(szOID_KEY_USAGE), -1))
  1820. {
  1821. hr = E_OUTOFMEMORY;
  1822. _JumpError(hr, error, "ceConvertWszToBstr");
  1823. }
  1824. varExtension.vt = VT_BSTR;
  1825. varExtension.bstrVal = strExtension;
  1826. hr = pServer->SetCertificateExtension(
  1827. strName,
  1828. PROPTYPE_BINARY,
  1829. EXTENSION_CRITICAL_FLAG,
  1830. &varExtension);
  1831. _JumpIfError(hr, error, "SetCertificateExtension");
  1832. error:
  1833. if (NULL != strName)
  1834. {
  1835. SysFreeString(strName);
  1836. }
  1837. if (NULL != strExtension)
  1838. {
  1839. SysFreeString(strExtension);
  1840. }
  1841. if (NULL != strBitString)
  1842. {
  1843. SysFreeString(strBitString);
  1844. }
  1845. if (NULL != strKeyUsage)
  1846. {
  1847. SysFreeString(strKeyUsage);
  1848. }
  1849. if (NULL != strValue)
  1850. {
  1851. SysFreeString(strValue);
  1852. }
  1853. if (NULL != pBitString)
  1854. {
  1855. pBitString->Release();
  1856. }
  1857. return(hr);
  1858. }
  1859. //+--------------------------------------------------------------------------
  1860. // CCertPolicyExchange::_AddEnhancedKeyUsageExtension
  1861. //
  1862. // Returns S_OK on success.
  1863. //+--------------------------------------------------------------------------
  1864. HRESULT
  1865. CCertPolicyExchange::_AddEnhancedKeyUsageExtension(
  1866. IN ICertServerPolicy *pServer)
  1867. {
  1868. HRESULT hr = S_OK;
  1869. BSTR strName = NULL;
  1870. BSTR strExtension = NULL;
  1871. VARIANT varExtension;
  1872. BYTE *pbEncoded = NULL;
  1873. DWORD cbEncoded;
  1874. CERT_ENHKEY_USAGE ceu;
  1875. LPSTR pszEnhUsage = szOID_PKIX_KP_EMAIL_PROTECTION;
  1876. ceu.cUsageIdentifier = 1;
  1877. ceu.rgpszUsageIdentifier = &pszEnhUsage; // array of pszObjId
  1878. if (!ceEncodeObject(
  1879. X509_ASN_ENCODING,
  1880. X509_ENHANCED_KEY_USAGE,
  1881. &ceu,
  1882. 0,
  1883. FALSE,
  1884. &pbEncoded,
  1885. &cbEncoded))
  1886. {
  1887. hr = GetLastError();
  1888. _JumpError(hr, error, "ceEncodeObject");
  1889. }
  1890. if (!ceConvertWszToBstr(
  1891. &strExtension,
  1892. (WCHAR const *) pbEncoded,
  1893. cbEncoded))
  1894. {
  1895. hr = E_OUTOFMEMORY;
  1896. _JumpError(hr, error, "ceConvertWszToBstr");
  1897. }
  1898. if (!ceConvertWszToBstr(&strName, TEXT(szOID_ENHANCED_KEY_USAGE), -1))
  1899. {
  1900. hr = E_OUTOFMEMORY;
  1901. _JumpError(hr, error, "ceConvertWszToBstr");
  1902. }
  1903. varExtension.vt = VT_BSTR;
  1904. varExtension.bstrVal = strExtension;
  1905. hr = pServer->SetCertificateExtension(
  1906. strName,
  1907. PROPTYPE_BINARY,
  1908. 0,
  1909. &varExtension);
  1910. _JumpIfError(hr, error, "SetCertificateExtension");
  1911. error:
  1912. if (NULL != pbEncoded)
  1913. {
  1914. LocalFree(pbEncoded);
  1915. }
  1916. if (NULL != strName)
  1917. {
  1918. SysFreeString(strName);
  1919. }
  1920. if (NULL != strExtension)
  1921. {
  1922. SysFreeString(strExtension);
  1923. }
  1924. return(hr);
  1925. }
  1926. //+--------------------------------------------------------------------------
  1927. // CCertPolicyExchange::VerifyRequest
  1928. //
  1929. // Returns S_OK on success.
  1930. //+--------------------------------------------------------------------------
  1931. STDMETHODIMP
  1932. CCertPolicyExchange::VerifyRequest(
  1933. /* [in] */ BSTR const strConfig,
  1934. /* [in] */ LONG Context,
  1935. /* [in] */ LONG bNewRequest,
  1936. /* [in] */ LONG Flags,
  1937. /* [out, retval] */ LONG __RPC_FAR *pDisposition)
  1938. {
  1939. HRESULT hr;
  1940. ICertServerPolicy *pServer = NULL;
  1941. hr = GetServerCallbackInterface(&pServer, Context);
  1942. _JumpIfError(hr, error, "GetServerCallbackInterface");
  1943. if (fDebug)
  1944. {
  1945. hr = EnumerateAttributes(pServer);
  1946. _JumpIfError(hr, error, "EnumerateAttributes");
  1947. hr = EnumerateExtensions(pServer);
  1948. _JumpIfError(hr, error, "EnumerateExtensions");
  1949. }
  1950. hr = _AddIssuerAltName2Extension(pServer);
  1951. _JumpIfError(hr, error, "_AddIssuerAltName2Extension");
  1952. // also handles 'special' KMS request
  1953. hr = _AddSubjectAltName2Extension(pServer);
  1954. _JumpIfError(hr, error, "_AddSubjectAltName2Extension");
  1955. hr = _AddBasicConstraintsExtension(pServer);
  1956. _JumpIfError(hr, error, "_AddBasicConstraintsExtension");
  1957. hr = _AddRevocationExtension(pServer);
  1958. _JumpIfError(hr, error, "_AddRevocationExtension");
  1959. hr = _AddAuthorityInfoAccessExtension(pServer);
  1960. _JumpIfError(hr, error, "_AddAuthorityInfoAccessExtension");
  1961. hr = _AddKeyUsageExtension(pServer);
  1962. _JumpIfError(hr, error, "_AddKeyUsageExtension");
  1963. hr = _AddEnhancedKeyUsageExtension(pServer);
  1964. _JumpIfError(hr, error, "_AddEnhancedKeyUsageExtension");
  1965. if (fDebug)
  1966. {
  1967. hr = EnumerateExtensions(pServer);
  1968. _JumpIfError(hr, error, "EnumerateExtensions");
  1969. }
  1970. hr = CheckRequestProperties(pServer);
  1971. _JumpIfError(hr, error, "_AddRevocationExtension");
  1972. error:
  1973. *pDisposition = S_OK == hr? VR_INSTANT_OK : VR_INSTANT_BAD;
  1974. if (NULL != pServer)
  1975. {
  1976. pServer->Release();
  1977. }
  1978. return(hr);
  1979. }
  1980. //+--------------------------------------------------------------------------
  1981. // CCertPolicyExchange::GetDescription
  1982. //
  1983. // Returns S_OK on success.
  1984. //+--------------------------------------------------------------------------
  1985. STDMETHODIMP
  1986. CCertPolicyExchange::GetDescription(
  1987. /* [out, retval] */ BSTR __RPC_FAR *pstrDescription)
  1988. {
  1989. HRESULT hr = S_OK;
  1990. *pstrDescription = SysAllocString(g_wszDescription);
  1991. if (NULL == *pstrDescription)
  1992. {
  1993. hr = E_OUTOFMEMORY;
  1994. _JumpError(hr, error, "SysAllocString");
  1995. }
  1996. error:
  1997. return(hr);
  1998. }
  1999. //+--------------------------------------------------------------------------
  2000. // CCertPolicyExchange::ShutDown
  2001. //
  2002. // Returns S_OK on success.
  2003. //+--------------------------------------------------------------------------
  2004. STDMETHODIMP
  2005. CCertPolicyExchange::ShutDown(VOID)
  2006. {
  2007. return(S_OK);
  2008. }
  2009. //+--------------------------------------------------------------------------
  2010. // CCertPolicyExchange::GetManageModule
  2011. //
  2012. // Returns S_OK on success.
  2013. //+--------------------------------------------------------------------------
  2014. STDMETHODIMP
  2015. CCertPolicyExchange::GetManageModule(
  2016. /* [out, retval] */ ICertManageModule **ppManageModule)
  2017. {
  2018. HRESULT hr;
  2019. *ppManageModule = NULL;
  2020. hr = CoCreateInstance(
  2021. CLSID_CCertManagePolicyModuleExchange,
  2022. NULL, // pUnkOuter
  2023. CLSCTX_INPROC_SERVER,
  2024. IID_ICertManageModule,
  2025. (VOID **) ppManageModule);
  2026. _JumpIfError(hr, error, "CoCreateInstance");
  2027. error:
  2028. return(hr);
  2029. }
  2030. STDMETHODIMP
  2031. CCertPolicyExchange::InterfaceSupportsErrorInfo(REFIID riid)
  2032. {
  2033. static const IID *arr[] =
  2034. {
  2035. &IID_ICertPolicy,
  2036. };
  2037. for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
  2038. {
  2039. if (InlineIsEqualGUID(*arr[i], riid))
  2040. {
  2041. return(S_OK);
  2042. }
  2043. }
  2044. return(S_FALSE);
  2045. }