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.

3339 lines
83 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000
  5. //
  6. // File: template.cpp
  7. //
  8. // Contents: Cert Server Policy Module implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <ntdsapi.h>
  14. #include <lm.h>
  15. #include <winldap.h>
  16. #include <security.h>
  17. #include <ntdsapi.h>
  18. #include "cspelog.h"
  19. #include "pollog.h"
  20. #include "csprop.h"
  21. #include "csldap.h"
  22. #include "csdisp.h"
  23. #include "csber.h"
  24. #include "policy.h"
  25. #include "cainfop.h"
  26. #define __dwFILE__ __dwFILE_POLICY_DEFAULT_TEMPLATE_CPP__
  27. // Versions of NT earlier than this build have an auto-enrollment loop problem
  28. // with not having the basic constraints extension, so we must put one in certs
  29. // for these builds. This build marks when certcli started return no BC
  30. // extension for templates that were not CA's.
  31. #define VERSION_AUTOENROLLMENT_BC_AWARE 2036
  32. // Versions of NT earlier than this build have an auto-enrollment loop problem
  33. // with having the UPN anywhere but the CN. Certs for these builds must have
  34. // the UPN in the common name.
  35. #define VERSION_AUTOENROLLMENT_UPN_AWARE 2090
  36. #define VERSION_WIN2K_XENROLL_CLIENT (2195 + 1)
  37. // All of the "known" Key Usage bits currently defined:
  38. #define dwKNOWN_KEY_USAGE_BITS \
  39. (CERT_DIGITAL_SIGNATURE_KEY_USAGE | \
  40. CERT_NON_REPUDIATION_KEY_USAGE | \
  41. CERT_KEY_ENCIPHERMENT_KEY_USAGE | \
  42. CERT_DATA_ENCIPHERMENT_KEY_USAGE | \
  43. CERT_KEY_AGREEMENT_KEY_USAGE | \
  44. CERT_KEY_CERT_SIGN_KEY_USAGE | \
  45. CERT_OFFLINE_CRL_SIGN_KEY_USAGE | \
  46. CERT_CRL_SIGN_KEY_USAGE | \
  47. CERT_ENCIPHER_ONLY_KEY_USAGE | \
  48. (CERT_DECIPHER_ONLY_KEY_USAGE << 8))
  49. // Mask to turn off all the "known" Key Usage bits that aren't expclitly valid:
  50. #define dwKUMASK(dwValid) ((DWORD) ((dwValid) | ~dwKNOWN_KEY_USAGE_BITS))
  51. typedef struct _KEYUSAGEMASK {
  52. WCHAR const * const *apwszAlg;
  53. DWORD dwMask1; // 1: CA mask (2: if any of these bits are set)
  54. DWORD dwMask2; // 1: EE mask (2: clear these bits)
  55. } KEYUSAGEMASK;
  56. WCHAR const * const s_apwszRSA[] = // RSA public key
  57. {
  58. TEXT(szOID_RSA_RSA),
  59. TEXT(szOID_OIWSEC_rsaXchg),
  60. NULL
  61. };
  62. WCHAR const * const s_apwszDSA[] = // DSA public key
  63. {
  64. TEXT(szOID_X957_DSA),
  65. TEXT(szOID_OIWSEC_dsa),
  66. TEXT(szOID_INFOSEC_mosaicKMandUpdSig),
  67. NULL
  68. };
  69. WCHAR const * const s_apwszDH[] = // DH public key
  70. {
  71. TEXT(szOID_ANSI_X942_DH),
  72. TEXT(szOID_RSA_DH),
  73. NULL
  74. };
  75. KEYUSAGEMASK g_aKeyUsageMask1[] =
  76. {
  77. {
  78. s_apwszRSA,
  79. // Valid CA cert Key Usage bits -> mask = 0xffff7ff6
  80. dwKUMASK(
  81. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  82. CERT_NON_REPUDIATION_KEY_USAGE |
  83. CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  84. CERT_DATA_ENCIPHERMENT_KEY_USAGE |
  85. CERT_KEY_CERT_SIGN_KEY_USAGE |
  86. CERT_CRL_SIGN_KEY_USAGE), // same as CERT_OFFLINE_CRL_SIGN_KEY_USAGE
  87. // Valid EE cert Key Usage bits -> mask = 0xffff7ff0
  88. dwKUMASK(
  89. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  90. CERT_NON_REPUDIATION_KEY_USAGE |
  91. CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  92. CERT_DATA_ENCIPHERMENT_KEY_USAGE),
  93. },
  94. {
  95. s_apwszDSA,
  96. // Valid CA cert Key Usage bits -> mask = 0xffff7fc6
  97. dwKUMASK(
  98. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  99. CERT_NON_REPUDIATION_KEY_USAGE |
  100. CERT_KEY_CERT_SIGN_KEY_USAGE |
  101. CERT_CRL_SIGN_KEY_USAGE), // same as CERT_OFFLINE_CRL_SIGN_KEY_USAGE
  102. // Valid EE cert Key Usage bits -> mask = 0xffff7fc0
  103. dwKUMASK(
  104. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  105. CERT_NON_REPUDIATION_KEY_USAGE),
  106. },
  107. {
  108. s_apwszDH,
  109. // Valid CA cert Key Usage bits -> mask = 0xffff7f09
  110. dwKUMASK(
  111. CERT_KEY_AGREEMENT_KEY_USAGE |
  112. CERT_ENCIPHER_ONLY_KEY_USAGE),
  113. // Valid EE cert Key Usage bits -> mask = 0xffff7f09
  114. dwKUMASK(
  115. CERT_KEY_AGREEMENT_KEY_USAGE |
  116. CERT_ENCIPHER_ONLY_KEY_USAGE),
  117. },
  118. };
  119. KEYUSAGEMASK g_aKeyUsageMask2[] =
  120. {
  121. {
  122. s_apwszRSA,
  123. // CERT_KEY_ENCIPHERMENT_KEY_USAGE(SHOULD not be set w/Cert,CRL sign)
  124. // CERT_DATA_ENCIPHERMENT_KEY_USAGE (SHOULD not be set w/Cert,CRL sign)
  125. CERT_KEY_CERT_SIGN_KEY_USAGE |
  126. CERT_CRL_SIGN_KEY_USAGE, // same as CERT_OFFLINE_CRL_SIGN_KEY_USAGE
  127. CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  128. CERT_DATA_ENCIPHERMENT_KEY_USAGE,
  129. },
  130. };
  131. CRITICAL_SECTION g_DSCacheCriticalSection;
  132. BOOL g_fDSCacheCriticalSection = FALSE;
  133. HRESULT
  134. TPInitialize(
  135. IN ICertServerPolicy *) // pServer
  136. {
  137. return(S_OK);
  138. }
  139. VOID
  140. TPCleanup()
  141. {
  142. }
  143. HRESULT
  144. tpCAGetCertTypeProperty(
  145. IN HCERTTYPE hCertType,
  146. IN WCHAR const *pwszPropName,
  147. WCHAR ***papwszValues)
  148. {
  149. HRESULT hr;
  150. *papwszValues = NULL;
  151. hr = CAGetCertTypeProperty(hCertType, pwszPropName, papwszValues);
  152. _PrintIfErrorStr2(
  153. hr,
  154. "Policy:CAGetCertTypeProperty",
  155. pwszPropName,
  156. HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
  157. if (S_OK != hr)
  158. {
  159. *papwszValues = NULL;
  160. if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
  161. {
  162. goto error;
  163. }
  164. hr = S_OK;
  165. }
  166. error:
  167. return(hr);
  168. }
  169. HRESULT
  170. tpCAGetCertTypeStringProperty(
  171. IN HCERTTYPE hCertType,
  172. IN WCHAR const *pwszPropName,
  173. OUT WCHAR **ppwszValue)
  174. {
  175. HRESULT hr;
  176. WCHAR **apwszValues = NULL;
  177. *ppwszValue = NULL;
  178. hr = CAGetCertTypeProperty(hCertType, pwszPropName, &apwszValues);
  179. if (S_OK != hr)
  180. {
  181. apwszValues = NULL;
  182. _JumpErrorStr(hr, error, "CAGetCertTypeProperty", pwszPropName);
  183. }
  184. if (NULL == apwszValues || NULL == apwszValues[0])
  185. {
  186. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  187. _JumpErrorStr(hr, error, "CAGetCertTypeProperty", pwszPropName);
  188. }
  189. hr = myDupString(apwszValues[0], ppwszValue);
  190. _JumpIfError(hr, error, "myDupString");
  191. error:
  192. if (NULL != apwszValues)
  193. {
  194. CAFreeCertTypeProperty(hCertType, apwszValues);
  195. }
  196. return(hr);
  197. }
  198. HRESULT
  199. tpCAGetCertTypeObjectIdList(
  200. IN HCERTTYPE hCertType,
  201. IN WCHAR const *pwszPropName,
  202. OUT OBJECTIDLIST *prgPolicies)
  203. {
  204. HRESULT hr;
  205. WCHAR **apwsz;
  206. prgPolicies->cObjId = 0;
  207. prgPolicies->rgpwszObjId = NULL;
  208. hr = tpCAGetCertTypeProperty(
  209. hCertType,
  210. pwszPropName,
  211. &prgPolicies->rgpwszObjId);
  212. _JumpIfErrorStr(
  213. hr,
  214. error,
  215. "CTemplatePolicy:tpCAGetCertTypeProperty",
  216. pwszPropName);
  217. apwsz = prgPolicies->rgpwszObjId;
  218. if (NULL != apwsz)
  219. {
  220. while (NULL != *apwsz++)
  221. {
  222. prgPolicies->cObjId++;
  223. }
  224. }
  225. hr = S_OK;
  226. error:
  227. return(hr);
  228. }
  229. CTemplatePolicy::CTemplatePolicy()
  230. {
  231. m_hCertType = NULL;
  232. ZeroMemory(&m_tp, sizeof(m_tp));
  233. m_pwszTemplateName = NULL;
  234. m_pwszTemplateObjId = NULL;
  235. m_pExtensions = NULL;
  236. ZeroMemory(&m_CriticalExtensions, sizeof(m_CriticalExtensions));
  237. ZeroMemory(&m_PoliciesIssuance, sizeof(m_PoliciesIssuance));
  238. ZeroMemory(&m_PoliciesApplication, sizeof(m_PoliciesApplication));
  239. m_pPolicy = NULL;
  240. }
  241. CTemplatePolicy::~CTemplatePolicy()
  242. {
  243. _Cleanup();
  244. }
  245. VOID
  246. CTemplatePolicy::_Cleanup()
  247. {
  248. ZeroMemory(&m_tp, sizeof(m_tp));
  249. if (NULL != m_hCertType)
  250. {
  251. CACloseCertType(m_hCertType);
  252. m_hCertType = NULL;
  253. }
  254. if (NULL != m_pwszTemplateName)
  255. {
  256. LocalFree(m_pwszTemplateName);
  257. m_pwszTemplateName = NULL;
  258. }
  259. if (NULL != m_pwszTemplateObjId)
  260. {
  261. LocalFree(m_pwszTemplateObjId);
  262. m_pwszTemplateObjId = NULL;
  263. }
  264. if (NULL != m_pExtensions)
  265. {
  266. LocalFree(m_pExtensions);
  267. m_pExtensions = NULL;
  268. }
  269. if (NULL != m_CriticalExtensions.rgpwszObjId)
  270. {
  271. LocalFree(m_CriticalExtensions.rgpwszObjId);
  272. }
  273. ZeroMemory(&m_CriticalExtensions, sizeof(m_CriticalExtensions));
  274. if (NULL != m_PoliciesIssuance.rgpwszObjId)
  275. {
  276. LocalFree(m_PoliciesIssuance.rgpwszObjId);
  277. }
  278. ZeroMemory(&m_PoliciesIssuance, sizeof(m_PoliciesIssuance));
  279. if (NULL != m_PoliciesApplication.rgpwszObjId)
  280. {
  281. LocalFree(m_PoliciesApplication.rgpwszObjId);
  282. }
  283. ZeroMemory(&m_PoliciesApplication, sizeof(m_PoliciesApplication));
  284. m_pPolicy = NULL;
  285. }
  286. HRESULT
  287. CTemplatePolicy::_LogLoadResult(
  288. IN CCertPolicyEnterprise *pPolicy,
  289. IN ICertServerPolicy *pServer,
  290. IN HRESULT hrLoad)
  291. {
  292. HRESULT hr;
  293. WCHAR const *pwszError = NULL;
  294. WCHAR const *apwsz[2];
  295. DWORD level;
  296. DWORD MsgId;
  297. WCHAR const *pwszLogProp;
  298. WCHAR *pwszNameAndVersion = NULL;
  299. #define wszFORMATVERSION L"(v%u.%u): V%u"
  300. WCHAR wszVersion[ARRAYSIZE(wszFORMATVERSION) + 3 * cwcDWORDSPRINTF];
  301. WCHAR const *pwszTemplate;
  302. if (S_OK != hrLoad)
  303. {
  304. pwszError = myGetErrorMessageText(hrLoad, TRUE);
  305. level = CERTLOG_WARNING;
  306. MsgId = MSG_LOAD_TEMPLATE;
  307. pwszLogProp = wszPROPEVENTLOGWARNING;
  308. }
  309. else
  310. {
  311. level = CERTLOG_VERBOSE;
  312. MsgId = MSG_LOAD_TEMPLATE_SUCCEEDED;
  313. pwszLogProp = wszPROPEVENTLOGVERBOSE;
  314. }
  315. if (level > pPolicy->GetLogLevel())
  316. {
  317. hr = S_OK;
  318. goto error;
  319. }
  320. wsprintf(
  321. wszVersion,
  322. wszFORMATVERSION,
  323. m_tp.dwTemplateMajorVersion,
  324. m_tp.dwTemplateMinorVersion,
  325. m_tp.dwSchemaVersion);
  326. CSASSERT(wcslen(wszVersion) < ARRAYSIZE(wszVersion));
  327. pwszTemplate = m_pwszTemplateName;
  328. if (NULL == pwszTemplate)
  329. {
  330. pwszTemplate = L"???";
  331. }
  332. pwszNameAndVersion = (WCHAR *) LocalAlloc(
  333. LMEM_FIXED,
  334. (wcslen(pwszTemplate) + wcslen(wszVersion) + 1) *
  335. sizeof(WCHAR));
  336. if (NULL == pwszNameAndVersion)
  337. {
  338. hr = E_OUTOFMEMORY;
  339. _JumpError(hr, error, "Policy:LocalAlloc");
  340. }
  341. wcscpy(pwszNameAndVersion, pwszTemplate);
  342. wcscat(pwszNameAndVersion, wszVersion);
  343. apwsz[0] = pwszNameAndVersion;
  344. apwsz[1] = pwszError;
  345. hr = LogPolicyEvent(
  346. g_hInstance,
  347. S_OK,
  348. MsgId,
  349. pServer,
  350. pwszLogProp,
  351. apwsz);
  352. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:LogPolicyEvent");
  353. error:
  354. if (NULL != pwszNameAndVersion)
  355. {
  356. LocalFree(pwszNameAndVersion);
  357. }
  358. if (NULL != pwszError)
  359. {
  360. LocalFree(const_cast<WCHAR *>(pwszError));
  361. }
  362. return(hr);
  363. }
  364. HRESULT
  365. CTemplatePolicy::_CloneExtensions(
  366. IN CERT_EXTENSIONS const *pExtensionsIn,
  367. OUT CERT_EXTENSIONS **ppExtensionsOut)
  368. {
  369. HRESULT hr;
  370. DWORD cb;
  371. CERT_EXTENSION *pExt;
  372. CERT_EXTENSION *pExtEnd;
  373. CERT_EXTENSION *pExtOut;
  374. BYTE *pbOut;
  375. *ppExtensionsOut = NULL;
  376. cb = sizeof(CERT_EXTENSIONS) +
  377. pExtensionsIn->cExtension * sizeof(pExtensionsIn->rgExtension[0]);
  378. pExtEnd = &pExtensionsIn->rgExtension[pExtensionsIn->cExtension];
  379. for (pExt = pExtensionsIn->rgExtension; pExt < pExtEnd; pExt++)
  380. {
  381. cb += DWORDROUND(strlen(pExt->pszObjId) + 1);
  382. cb += DWORDROUND(pExt->Value.cbData);
  383. }
  384. *ppExtensionsOut = (CERT_EXTENSIONS *) LocalAlloc(LMEM_FIXED, cb);
  385. if (NULL == *ppExtensionsOut)
  386. {
  387. hr = E_OUTOFMEMORY;
  388. _JumpError(hr, error, "Policy:LocalAlloc");
  389. }
  390. (*ppExtensionsOut)->cExtension = pExtensionsIn->cExtension;
  391. pExtOut = (CERT_EXTENSION *) &(*ppExtensionsOut)[1];
  392. (*ppExtensionsOut)->rgExtension = pExtOut;
  393. pbOut = (BYTE *) &pExtOut[pExtensionsIn->cExtension];
  394. for (pExt = pExtensionsIn->rgExtension; pExt < pExtEnd; pExt++, pExtOut++)
  395. {
  396. pExtOut->pszObjId = (char *) pbOut;
  397. strcpy(pExtOut->pszObjId, pExt->pszObjId);
  398. pbOut += DWORDROUND(strlen(pExt->pszObjId) + 1);
  399. pExtOut->fCritical = pExt->fCritical;
  400. pExtOut->Value.cbData = pExt->Value.cbData;
  401. pExtOut->Value.pbData = pbOut;
  402. CopyMemory(
  403. pExtOut->Value.pbData,
  404. pExt->Value.pbData,
  405. pExt->Value.cbData);
  406. pbOut += DWORDROUND(pExt->Value.cbData);
  407. }
  408. CSASSERT(Add2Ptr(*ppExtensionsOut, cb) == pbOut);
  409. hr = S_OK;
  410. error:
  411. return(hr);
  412. }
  413. HRESULT
  414. CTemplatePolicy::_CloneObjectIdList(
  415. IN OBJECTIDLIST const *pObjectIdListIn,
  416. OUT OBJECTIDLIST *pObjectIdListOut)
  417. {
  418. HRESULT hr;
  419. ZeroMemory(pObjectIdListOut, sizeof(*pObjectIdListOut));
  420. pObjectIdListOut->cObjId = pObjectIdListIn->cObjId;
  421. if (0 != pObjectIdListIn->cObjId)
  422. {
  423. DWORD cb = (pObjectIdListIn->cObjId + 1) * sizeof(pObjectIdListIn->rgpwszObjId);
  424. WCHAR const * const *ppwsz;
  425. WCHAR const * const *ppwszEnd;
  426. WCHAR **ppwszOut;
  427. BYTE *pbOut;
  428. ppwszEnd = &pObjectIdListIn->rgpwszObjId[pObjectIdListIn->cObjId];
  429. for (ppwsz = pObjectIdListIn->rgpwszObjId; ppwsz < ppwszEnd; ppwsz++)
  430. {
  431. cb += DWORDROUND((wcslen(*ppwsz) + 1) * sizeof(WCHAR));
  432. }
  433. pObjectIdListOut->rgpwszObjId = (WCHAR **) LocalAlloc(LMEM_FIXED, cb);
  434. if (NULL == pObjectIdListOut->rgpwszObjId)
  435. {
  436. hr = E_OUTOFMEMORY;
  437. _JumpError(hr, error, "Policy:LocalAlloc");
  438. }
  439. ppwszOut = pObjectIdListOut->rgpwszObjId;
  440. pbOut = (BYTE *) &ppwszOut[pObjectIdListOut->cObjId + 1];
  441. for (
  442. ppwsz = pObjectIdListIn->rgpwszObjId;
  443. ppwsz < ppwszEnd;
  444. ppwsz++, ppwszOut++)
  445. {
  446. *ppwszOut = (WCHAR *) pbOut;
  447. wcscpy(*ppwszOut, *ppwsz);
  448. pbOut += DWORDROUND((wcslen(*ppwszOut) + 1) * sizeof(WCHAR));
  449. }
  450. }
  451. hr = S_OK;
  452. error:
  453. return(hr);
  454. }
  455. //+--------------------------------------------------------------------------
  456. // CTemplatePolicy::Initialize
  457. // Populate the CTemplatePolicy object from the registry
  458. // Returns S_OK on success.
  459. //+--------------------------------------------------------------------------
  460. HRESULT
  461. CTemplatePolicy::Initialize(
  462. IN HCERTTYPE hCertType,
  463. IN ICertServerPolicy *pServer,
  464. IN CCertPolicyEnterprise *pPolicy)
  465. {
  466. HRESULT hr;
  467. CERT_EXTENSIONS *pExtensions = NULL;
  468. OBJECTIDLIST CriticalExtensions;
  469. OBJECTIDLIST PoliciesIssuance;
  470. OBJECTIDLIST PoliciesApplication;
  471. ZeroMemory(&CriticalExtensions, sizeof(CriticalExtensions));
  472. ZeroMemory(&PoliciesIssuance, sizeof(PoliciesIssuance));
  473. ZeroMemory(&PoliciesApplication, sizeof(PoliciesApplication));
  474. _Cleanup();
  475. CSASSERT(0 == m_tp.dwTemplateMajorVersion);
  476. CSASSERT(0 == m_tp.dwTemplateMinorVersion);
  477. CSASSERT(0 == m_tp.dwSchemaVersion);
  478. CSASSERT(0 == m_tp.dwMinKeyLength);
  479. hr = tpCAGetCertTypeStringProperty(
  480. hCertType,
  481. CERTTYPE_PROP_DN,
  482. &m_pwszTemplateName);
  483. _JumpIfErrorStr(
  484. hr,
  485. error,
  486. "CTemplatePolicy:Initialize:tpCAGetCertTypeStringProperty",
  487. CERTTYPE_PROP_DN);
  488. hr = CAGetCertTypePropertyEx(
  489. hCertType,
  490. CERTTYPE_PROP_REVISION,
  491. &m_tp.dwTemplateMajorVersion);
  492. _JumpIfErrorStr(
  493. hr,
  494. error,
  495. "CTemplatePolicy:Initialize:CAGetCertTypePropertyEx",
  496. CERTTYPE_PROP_REVISION);
  497. hr = CAGetCertTypePropertyEx(
  498. hCertType,
  499. CERTTYPE_PROP_SCHEMA_VERSION,
  500. &m_tp.dwSchemaVersion);
  501. _JumpIfErrorStr(
  502. hr,
  503. error,
  504. "CTemplatePolicy:Initialize:CAGetCertTypePropertyEx",
  505. CERTTYPE_PROP_SCHEMA_VERSION);
  506. if (CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion)
  507. {
  508. hr = tpCAGetCertTypeStringProperty(
  509. hCertType,
  510. CERTTYPE_PROP_OID,
  511. &m_pwszTemplateObjId);
  512. _JumpIfErrorStr(
  513. hr,
  514. error,
  515. "CTemplatePolicy:Initialize:tpCAGetCertTypeStringProperty",
  516. CERTTYPE_PROP_OID);
  517. hr = CAGetCertTypePropertyEx(
  518. hCertType,
  519. CERTTYPE_PROP_MINOR_REVISION,
  520. &m_tp.dwTemplateMinorVersion);
  521. _JumpIfErrorStr(
  522. hr,
  523. error,
  524. "CTemplatePolicy:Initialize:CAGetCertTypePropertyEx",
  525. CERTTYPE_PROP_MINOR_REVISION);
  526. hr = CAGetCertTypePropertyEx(
  527. hCertType,
  528. CERTTYPE_PROP_MIN_KEY_SIZE,
  529. &m_tp.dwMinKeyLength);
  530. _JumpIfErrorStr(
  531. hr,
  532. error,
  533. "CTemplatePolicy:Initialize:CAGetCertTypePropertyEx",
  534. CERTTYPE_PROP_MIN_KEY_SIZE);
  535. }
  536. if (!FIsAdvancedServer() && CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion)
  537. {
  538. // V2 templates require Advanced Server
  539. hr = HRESULT_FROM_WIN32(ERROR_CALL_NOT_IMPLEMENTED);
  540. _JumpError(hr, error, "CTemplatePolicy:Initialize:m_tp.dwSchemaVersion");
  541. }
  542. m_pPolicy = pPolicy;
  543. hr = CAGetCertTypeFlagsEx(
  544. hCertType,
  545. CERTTYPE_ENROLLMENT_FLAG,
  546. &m_tp.dwEnrollmentFlags);
  547. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:CAGetCertTypeFlagsEx");
  548. hr = CAGetCertTypeFlagsEx(
  549. hCertType,
  550. CERTTYPE_SUBJECT_NAME_FLAG,
  551. &m_tp.dwSubjectNameFlags);
  552. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:CAGetCertTypeFlagsEx");
  553. hr = CAGetCertTypeFlagsEx(
  554. hCertType,
  555. CERTTYPE_PRIVATE_KEY_FLAG,
  556. &m_tp.dwPrivateKeyFlags);
  557. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:CAGetCertTypeFlagsEx");
  558. hr = CAGetCertTypeFlagsEx(
  559. hCertType,
  560. CERTTYPE_GENERAL_FLAG,
  561. &m_tp.dwGeneralFlags);
  562. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:CAGetCertTypeFlagsEx");
  563. hr = CAGetCertTypePropertyEx(
  564. hCertType,
  565. CERTTYPE_PROP_RA_SIGNATURE,
  566. &m_tp.dwcSignatureRequired);
  567. _PrintIfErrorStr2(
  568. hr,
  569. "CTemplatePolicy:Initialize:CAGetCertTypePropertyEx",
  570. CERTTYPE_PROP_RA_SIGNATURE,
  571. HRESULT_FROM_WIN32(ERROR_NOT_FOUND));
  572. if (S_OK != hr)
  573. {
  574. if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) != hr)
  575. {
  576. goto error;
  577. }
  578. m_tp.dwcSignatureRequired = 0;
  579. }
  580. hr = CAGetCertTypeExpiration(
  581. hCertType,
  582. &m_tp.llftExpirationPeriod.ft,
  583. &m_tp.llftOverlapPeriod.ft);
  584. _JumpIfError(hr, error, "Policy:CAGetCertTypeExpiration");
  585. hr = CAGetCertTypeExtensions(hCertType, &pExtensions);
  586. _JumpIfError(hr, error, "CTemplatePolicy:Initialize:CAGetCertTypeExtensions");
  587. hr = _CloneExtensions(pExtensions, &m_pExtensions);
  588. _JumpIfError(hr, error, "CTemplatePolicy:_CloneExtensions");
  589. hr = tpCAGetCertTypeObjectIdList(
  590. hCertType,
  591. CERTTYPE_PROP_CRITICAL_EXTENSIONS,
  592. &CriticalExtensions);
  593. _JumpIfErrorStr(
  594. hr,
  595. error,
  596. "CTemplatePolicy:tpCAGetCertTypePolicies",
  597. CERTTYPE_PROP_CRITICAL_EXTENSIONS);
  598. hr = _CloneObjectIdList(&CriticalExtensions, &m_CriticalExtensions);
  599. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  600. hr = tpCAGetCertTypeObjectIdList(
  601. hCertType,
  602. CERTTYPE_PROP_RA_POLICY,
  603. &PoliciesIssuance);
  604. _JumpIfErrorStr(
  605. hr,
  606. error,
  607. "CTemplatePolicy:tpCAGetCertTypePolicies",
  608. CERTTYPE_PROP_RA_POLICY);
  609. hr = _CloneObjectIdList(&PoliciesIssuance, &m_PoliciesIssuance);
  610. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  611. hr = tpCAGetCertTypeObjectIdList(
  612. hCertType,
  613. CERTTYPE_PROP_RA_APPLICATION_POLICY,
  614. &PoliciesApplication);
  615. _JumpIfErrorStr(
  616. hr,
  617. error,
  618. "CTemplatePolicy:tpCAGetCertTypePolicies",
  619. CERTTYPE_PROP_RA_APPLICATION_POLICY);
  620. hr = _CloneObjectIdList(&PoliciesApplication, &m_PoliciesApplication);
  621. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  622. m_hCertType = hCertType; // Transfer ownership only on success
  623. error:
  624. if (NULL != pExtensions)
  625. {
  626. CAFreeCertTypeExtensions(hCertType, pExtensions);
  627. }
  628. if (NULL != CriticalExtensions.rgpwszObjId)
  629. {
  630. CAFreeCertTypeProperty(hCertType, CriticalExtensions.rgpwszObjId);
  631. }
  632. if (NULL != PoliciesIssuance.rgpwszObjId)
  633. {
  634. CAFreeCertTypeProperty(hCertType, PoliciesIssuance.rgpwszObjId);
  635. }
  636. if (NULL != PoliciesApplication.rgpwszObjId)
  637. {
  638. CAFreeCertTypeProperty(hCertType, PoliciesApplication.rgpwszObjId);
  639. }
  640. DBGPRINT((
  641. DBG_SS_CERTPOL,
  642. "Policy:Template:Initialize(%ws, v%u.%u): V%u hr=%x\n",
  643. NULL != m_pwszTemplateName? m_pwszTemplateName : L"",
  644. m_tp.dwTemplateMajorVersion,
  645. m_tp.dwTemplateMinorVersion,
  646. m_tp.dwSchemaVersion,
  647. hr));
  648. _LogLoadResult(pPolicy, pServer, hr);
  649. return(hr);
  650. }
  651. //+--------------------------------------------------------------------------
  652. // CTemplatePolicy::Clone
  653. //
  654. // Returns S_OK on success.
  655. //+--------------------------------------------------------------------------
  656. HRESULT
  657. CTemplatePolicy::Clone(
  658. OUT CTemplatePolicy **ppTemplate)
  659. {
  660. HRESULT hr;
  661. CTemplatePolicy *pTemplateClone = NULL;
  662. *ppTemplate = NULL;
  663. pTemplateClone = new CTemplatePolicy;
  664. if (NULL == pTemplateClone)
  665. {
  666. hr = E_OUTOFMEMORY;
  667. _JumpError(hr, error, "Policy:Clone:new");
  668. }
  669. //pTemplateClone->m_hCertType = m_hCertType;
  670. pTemplateClone->m_tp = m_tp;
  671. if (NULL != m_pwszTemplateName)
  672. {
  673. hr = myDupString(
  674. m_pwszTemplateName,
  675. &pTemplateClone->m_pwszTemplateName);
  676. _JumpIfError(hr, error, "myDupString");
  677. }
  678. if (NULL != m_pwszTemplateObjId)
  679. {
  680. hr = myDupString(
  681. m_pwszTemplateObjId,
  682. &pTemplateClone->m_pwszTemplateObjId);
  683. _JumpIfError(hr, error, "myDupString");
  684. }
  685. hr = _CloneExtensions(m_pExtensions, &pTemplateClone->m_pExtensions);
  686. _JumpIfError(hr, error, "CTemplatePolicy:_CloneExtensions");
  687. hr = _CloneObjectIdList(
  688. &m_CriticalExtensions,
  689. &pTemplateClone->m_CriticalExtensions);
  690. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  691. hr = _CloneObjectIdList(
  692. &m_PoliciesIssuance,
  693. &pTemplateClone->m_PoliciesIssuance);
  694. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  695. hr = _CloneObjectIdList(
  696. &m_PoliciesApplication,
  697. &pTemplateClone->m_PoliciesApplication);
  698. _JumpIfError(hr, error, "CTemplatePolicy:_CloneObjectIdList");
  699. pTemplateClone->m_pPolicy = m_pPolicy;
  700. *ppTemplate = pTemplateClone;
  701. pTemplateClone = NULL;
  702. hr = S_OK;
  703. error:
  704. if (NULL != pTemplateClone)
  705. {
  706. delete pTemplateClone;
  707. }
  708. return(hr);
  709. }
  710. //+--------------------------------------------------------------------------
  711. // CTemplatePolicy::AccessCheck
  712. //
  713. // Returns S_OK on success.
  714. //+--------------------------------------------------------------------------
  715. HRESULT
  716. CTemplatePolicy::AccessCheck(
  717. IN HANDLE hToken)
  718. {
  719. HRESULT hr;
  720. hr = CACertTypeAccessCheck(m_hCertType, hToken);
  721. if (E_ACCESSDENIED == hr)
  722. {
  723. // map E_ACCESSDENIED to a more meaningful error
  724. hr = CERTSRV_E_TEMPLATE_DENIED;
  725. }
  726. _JumpIfError(hr, error, "Policy:CACertTypeAccessCheck");
  727. error:
  728. return(hr);
  729. }
  730. //+--------------------------------------------------------------------------
  731. // CTemplatePolicy::Apply
  732. //
  733. // Returns S_OK on success.
  734. //+--------------------------------------------------------------------------
  735. HRESULT
  736. CTemplatePolicy::Apply(
  737. IN ICertServerPolicy *pServer,
  738. IN CRequestInstance *pRequest,
  739. OUT BOOL *pfReenroll)
  740. {
  741. HRESULT hr;
  742. DWORD dwRequestTemplateMinimumMajorVersion;
  743. DWORD dwRequestTemplateMinimumMinorVersion;
  744. BOOL fEnrollOnBehalfOf = FALSE;
  745. *pfReenroll = FALSE;
  746. pRequest->GetTemplateVersion(
  747. &dwRequestTemplateMinimumMajorVersion,
  748. &dwRequestTemplateMinimumMinorVersion);
  749. CONSOLEPRINT5((
  750. DBG_SS_CERTPOL,
  751. "Request cert type: %ws(v%u.%u/v%u.%u)\n",
  752. pRequest->GetTemplateName(),
  753. dwRequestTemplateMinimumMajorVersion,
  754. dwRequestTemplateMinimumMinorVersion,
  755. m_tp.dwTemplateMajorVersion,
  756. m_tp.dwTemplateMinorVersion));
  757. hr = _AddBasicConstraintsExtension(pRequest, pServer);
  758. _JumpIfError(hr, error, "Policy:_AddBasicConstraintsExtension");
  759. hr = _AddKeyUsageExtension(pServer, pRequest);
  760. _JumpIfError(hr, error, "Policy:_AddKeyUsageExtension");
  761. hr = _AddTemplateExtensionArray(pServer);
  762. _JumpIfError(hr, error, "Policy:_AddTemplateExtensionArray");
  763. if (0 == (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT & m_tp.dwSubjectNameFlags))
  764. {
  765. hr = pRequest->_LoadPrincipalObject(
  766. pServer,
  767. this,
  768. 0 != ((CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME |
  769. CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN |
  770. CT_FLAG_SUBJECT_ALT_REQUIRE_DNS) &
  771. m_tp.dwSubjectNameFlags));
  772. _JumpIfError(hr, error, "_LoadPrincipalObject");
  773. hr = _AddSubjectName(pServer, pRequest);
  774. _JumpIfError(hr, error, "Policy:_AddSubjectName");
  775. }
  776. hr = _AddAltSubjectName(pServer, pRequest);
  777. _JumpIfError(hr, error, "Policy:_AddAltSubjectName");
  778. pRequest->_ReleasePrincipalObject();
  779. hr = _ApplyExpirationTime(pServer, pRequest);
  780. _JumpIfError(hr, error, "Policy:_ApplyExpirationTime");
  781. hr = _EnforceKeySizePolicy(pServer);
  782. _JumpIfError(hr, error, "Policy:_EnforceKeySizePolicy");
  783. hr = _EnforceKeyArchivalPolicy(pServer);
  784. _JumpIfError(hr, error, "Policy:_EnforceKeyArchivalPolicy");
  785. hr = _EnforceSymmetricAlgorithms(pServer);
  786. _JumpIfError(hr, error, "Policy:_EnforceSymmetricAlgorithms");
  787. hr = _EnforceMinimumTemplateVersion(pRequest);
  788. _JumpIfError(hr, error, "Policy:_EnforceMinimumTemplateVersion");
  789. hr = _EnforceEnrollOnBehalfOfAllowed(pServer, &fEnrollOnBehalfOf);
  790. _JumpIfError(hr, error, "Policy:_EnforceEnrollOnBehalfOfAllowed");
  791. hr = S_FALSE;
  792. if (CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT & m_tp.dwEnrollmentFlags)
  793. {
  794. hr = _EnforceReenrollment(pServer, pRequest);
  795. _PrintIfError(hr, "Policy:_EnforceReenrollment");
  796. if (S_OK == hr)
  797. {
  798. *pfReenroll = TRUE;
  799. }
  800. }
  801. if (S_OK != hr)
  802. {
  803. hr = _EnforceSignaturePolicy(pServer, pRequest, fEnrollOnBehalfOf);
  804. _JumpIfError(hr, error, "Policy:_EnforceSignaturePolicy");
  805. }
  806. CSASSERT(S_OK == hr);
  807. error:
  808. pRequest->_ReleasePrincipalObject();
  809. return(hr);
  810. }
  811. //+--------------------------------------------------------------------------
  812. // CTemplatePolicy::_AddBasicConstraintsExtension
  813. //
  814. // Returns S_OK on success.
  815. //+--------------------------------------------------------------------------
  816. HRESULT
  817. CTemplatePolicy::_AddBasicConstraintsExtension(
  818. IN CRequestInstance *pRequest,
  819. IN ICertServerPolicy *pServer)
  820. {
  821. HRESULT hr;
  822. CERT_EXTENSION const *pExt;
  823. CERT_EXTENSION BasicConstraintsExtension;
  824. BasicConstraintsExtension.Value.pbData = NULL;
  825. pExt = CertFindExtension(
  826. szOID_BASIC_CONSTRAINTS2,
  827. m_pExtensions->cExtension,
  828. m_pExtensions->rgExtension);
  829. if (NULL == pExt)
  830. {
  831. if (pRequest->_IsNTClientOlder(
  832. 5,
  833. 0,
  834. VERSION_AUTOENROLLMENT_BC_AWARE,
  835. VER_PLATFORM_WIN32_NT))
  836. {
  837. CERT_BASIC_CONSTRAINTS2_INFO OldBasicConstraints =
  838. { FALSE, FALSE, 0};
  839. // Older autoenrollment clients don't know how to deal with
  840. // having no basic constraints extension, so they might loop.
  841. // For an old client, we must fabricate a basic constraints.
  842. if (!myEncodeObject(
  843. X509_ASN_ENCODING,
  844. szOID_BASIC_CONSTRAINTS2,
  845. &OldBasicConstraints,
  846. 0,
  847. CERTLIB_USE_LOCALALLOC,
  848. &BasicConstraintsExtension.Value.pbData,
  849. &BasicConstraintsExtension.Value.cbData))
  850. {
  851. hr = myHLastError();
  852. _JumpError(hr, error, "Policy:myEncodeObject");
  853. }
  854. BasicConstraintsExtension.fCritical = TRUE;
  855. BasicConstraintsExtension.pszObjId = szOID_BASIC_CONSTRAINTS2;
  856. pExt = &BasicConstraintsExtension;
  857. }
  858. }
  859. hr = m_pPolicy->AddBasicConstraintsCommon(
  860. pServer,
  861. pExt,
  862. FALSE, // fCA only enabled for standalone
  863. NULL != pExt);
  864. _JumpIfError(hr, error, "Policy:AddBasicConstraintsCommon");
  865. error:
  866. if (NULL != BasicConstraintsExtension.Value.pbData)
  867. {
  868. LocalFree(BasicConstraintsExtension.Value.pbData);
  869. }
  870. return(hr);
  871. }
  872. KEYUSAGEMASK const *
  873. FindKeyUsage(
  874. IN WCHAR const *pwszAlg,
  875. IN KEYUSAGEMASK const *pKeyUsageMask,
  876. IN DWORD cKeyUsageMask)
  877. {
  878. KEYUSAGEMASK const *pKeyUsageMaskRet = NULL;
  879. KEYUSAGEMASK const *pKeyUsageMaskEnd;
  880. for (
  881. pKeyUsageMaskEnd = &pKeyUsageMask[cKeyUsageMask];
  882. pKeyUsageMask < pKeyUsageMaskEnd;
  883. pKeyUsageMask++)
  884. {
  885. DWORD i;
  886. for (i = 0; NULL != pKeyUsageMask->apwszAlg[i]; i++)
  887. {
  888. if (0 == wcscmp(pwszAlg, pKeyUsageMask->apwszAlg[i]))
  889. {
  890. pKeyUsageMaskRet = pKeyUsageMask;
  891. break;
  892. }
  893. }
  894. if (NULL != pKeyUsageMaskRet)
  895. {
  896. break;
  897. }
  898. }
  899. return(pKeyUsageMaskRet);
  900. }
  901. //+--------------------------------------------------------------------------
  902. // CTemplatePolicy::_AddKeyUsageExtension
  903. //
  904. // Returns S_OK on success.
  905. //+--------------------------------------------------------------------------
  906. HRESULT
  907. CTemplatePolicy::_AddKeyUsageExtension(
  908. IN ICertServerPolicy *pServer,
  909. IN CRequestInstance *pRequest)
  910. {
  911. HRESULT hr = S_OK;
  912. BSTR strExtension = NULL;
  913. VARIANT varExtension;
  914. BSTR strAlg = NULL;
  915. CERT_EXTENSION const *pExt;
  916. CRYPT_BIT_BLOB *pKeyUsage = NULL;
  917. BYTE *pbKeyUsage = NULL;
  918. DWORD cbKeyUsage;
  919. DWORD dwKU;
  920. KEYUSAGEMASK const *pKeyUsageMask;
  921. VariantInit(&varExtension);
  922. pExt = CertFindExtension(
  923. szOID_KEY_USAGE,
  924. m_pExtensions->cExtension,
  925. m_pExtensions->rgExtension);
  926. if (NULL == pExt)
  927. {
  928. hr = S_OK;
  929. goto error;
  930. }
  931. if (!myDecodeObject(
  932. X509_ASN_ENCODING,
  933. X509_KEY_USAGE,
  934. pExt->Value.pbData,
  935. pExt->Value.cbData,
  936. CERTLIB_USE_LOCALALLOC,
  937. (VOID **) &pKeyUsage,
  938. &cbKeyUsage))
  939. {
  940. hr = myHLastError();
  941. _JumpError(hr, error, "Policy:myDecodeObject");
  942. }
  943. hr = polGetCertificateStringProperty(
  944. pServer,
  945. wszPROPCERTIFICATEPUBLICKEYALGORITHM,
  946. &strAlg);
  947. _JumpIfError(hr, error, "Policy:polGetCertificateStringProperty");
  948. // Mask out any illegal bits
  949. dwKU = 0;
  950. CopyMemory(&dwKU, pKeyUsage->pbData, min(sizeof(dwKU), pKeyUsage->cbData));
  951. pKeyUsageMask = FindKeyUsage(
  952. strAlg,
  953. g_aKeyUsageMask1,
  954. ARRAYSIZE(g_aKeyUsageMask1));
  955. if (NULL != pKeyUsageMask)
  956. {
  957. dwKU &= pRequest->IsCARequest()?
  958. pKeyUsageMask->dwMask1 : pKeyUsageMask->dwMask2;
  959. }
  960. pKeyUsageMask = FindKeyUsage(
  961. strAlg,
  962. g_aKeyUsageMask2,
  963. ARRAYSIZE(g_aKeyUsageMask2));
  964. if (NULL != pKeyUsageMask && (dwKU & pKeyUsageMask->dwMask1))
  965. {
  966. dwKU &= ~pKeyUsageMask->dwMask2;
  967. }
  968. CopyMemory(pKeyUsage->pbData, &dwKU, min(sizeof(dwKU), pKeyUsage->cbData));
  969. if (!myEncodeObject(
  970. X509_ASN_ENCODING,
  971. X509_KEY_USAGE,
  972. pKeyUsage,
  973. 0,
  974. CERTLIB_USE_LOCALALLOC,
  975. &pbKeyUsage,
  976. &cbKeyUsage))
  977. {
  978. hr = myHLastError();
  979. _JumpError(hr, error, "Policy:myEncodeObject");
  980. }
  981. if (!myConvertWszToBstr(
  982. &strExtension,
  983. (WCHAR const *) pbKeyUsage,
  984. cbKeyUsage))
  985. {
  986. hr = E_OUTOFMEMORY;
  987. _JumpError(hr, error, "Policy:myConvertWszToBstr");
  988. }
  989. varExtension.vt = VT_BSTR;
  990. varExtension.bstrVal = strExtension;
  991. strExtension = NULL;
  992. hr = polSetCertificateExtension(
  993. pServer,
  994. TEXT(szOID_KEY_USAGE),
  995. PROPTYPE_BINARY,
  996. pExt->fCritical? EXTENSION_CRITICAL_FLAG : 0,
  997. &varExtension);
  998. _JumpIfError(hr, error, "Policy:polSetCertificateExtension");
  999. error:
  1000. VariantClear(&varExtension);
  1001. if (NULL != strAlg)
  1002. {
  1003. SysFreeString(strAlg);
  1004. }
  1005. if (NULL != strExtension)
  1006. {
  1007. SysFreeString(strExtension);
  1008. }
  1009. if (NULL != pbKeyUsage)
  1010. {
  1011. LocalFree(pbKeyUsage);
  1012. }
  1013. if (NULL != pKeyUsage)
  1014. {
  1015. LocalFree(pKeyUsage);
  1016. }
  1017. return(hr);
  1018. }
  1019. //+--------------------------------------------------------------------------
  1020. // CTemplatePolicy::_AddTemplateExtensionArray
  1021. //
  1022. // Returns S_OK on success.
  1023. //+--------------------------------------------------------------------------
  1024. HRESULT
  1025. CTemplatePolicy::_AddTemplateExtensionArray(
  1026. IN ICertServerPolicy *pServer)
  1027. {
  1028. HRESULT hr;
  1029. DWORD i;
  1030. for (i = 0; i < m_pExtensions->cExtension; i++)
  1031. {
  1032. CERT_EXTENSION const *pExt = &m_pExtensions->rgExtension[i];
  1033. // Skip extensions that have special handling code.
  1034. if (0 == strcmp(szOID_BASIC_CONSTRAINTS2, pExt->pszObjId) ||
  1035. 0 == strcmp(szOID_KEY_USAGE, pExt->pszObjId))
  1036. {
  1037. continue;
  1038. }
  1039. hr = _AddTemplateExtension(pServer, pExt);
  1040. _JumpIfError(hr, error, "Policy:_AddTemplateExtension");
  1041. }
  1042. hr = S_OK;
  1043. error:
  1044. return(hr);
  1045. }
  1046. //+--------------------------------------------------------------------------
  1047. // CTemplatePolicy::_AddTemplateExtension
  1048. //
  1049. // Returns S_OK on success.
  1050. //+--------------------------------------------------------------------------
  1051. HRESULT
  1052. CTemplatePolicy::_AddTemplateExtension(
  1053. IN ICertServerPolicy *pServer,
  1054. IN CERT_EXTENSION const *pExt)
  1055. {
  1056. HRESULT hr = S_OK;
  1057. BSTR strExtension = NULL;
  1058. BSTR strObjId = NULL;
  1059. VARIANT varExtension;
  1060. if (!myConvertSzToBstr(&strObjId, pExt->pszObjId, -1))
  1061. {
  1062. hr = E_OUTOFMEMORY;
  1063. _JumpError(hr, error, "Policy:myConvertSzToBstr");
  1064. }
  1065. if (!myConvertWszToBstr(
  1066. &strExtension,
  1067. (WCHAR const *) pExt->Value.pbData,
  1068. pExt->Value.cbData))
  1069. {
  1070. hr = E_OUTOFMEMORY;
  1071. _JumpError(hr, error, "Policy:myConvertWszToBstr");
  1072. }
  1073. varExtension.vt = VT_BSTR;
  1074. varExtension.bstrVal = strExtension;
  1075. hr = pServer->SetCertificateExtension(
  1076. strObjId,
  1077. PROPTYPE_BINARY,
  1078. pExt->fCritical? EXTENSION_CRITICAL_FLAG : 0,
  1079. &varExtension);
  1080. _JumpIfErrorStr(hr, error, "Policy:polSetCertificateExtension", strObjId);
  1081. error:
  1082. if (NULL != strObjId)
  1083. {
  1084. SysFreeString(strObjId);
  1085. }
  1086. if (NULL != strExtension)
  1087. {
  1088. SysFreeString(strExtension);
  1089. }
  1090. return(hr);
  1091. }
  1092. //+--------------------------------------------------------------------------
  1093. // CTemplatePolicy::_AddSubjectName
  1094. //
  1095. // Build the subject name and add it to the cert, if required
  1096. //
  1097. // The subject name consists of:
  1098. // machine: the CN is set to the UPN (machineDNSName)
  1099. // old user: the CN is set to the UPN (Kerberos name)
  1100. // user: the CN is set to the DS_ATTR_COMMON_NAME
  1101. //
  1102. // both: E= indicates an e-mail name
  1103. //
  1104. // Returns S_OK on success.
  1105. //+--------------------------------------------------------------------------
  1106. HRESULT
  1107. CTemplatePolicy::_AddSubjectName(
  1108. IN ICertServerPolicy *pServer,
  1109. CRequestInstance *pRequest)
  1110. {
  1111. HRESULT hr;
  1112. BSTRC strCN = NULL;
  1113. BSTRC strEMail = NULL;
  1114. BSTR strPropEMail = NULL;
  1115. VARIANT varValue;
  1116. BSTR strSubjectDot = NULL;
  1117. BSTR strSubjectCommonName = NULL;
  1118. varValue.vt = VT_NULL;
  1119. strSubjectDot = SysAllocString(wszPROPSUBJECTDOT);
  1120. strSubjectCommonName = SysAllocString(wszPROPSUBJECTCOMMONNAME);
  1121. if (NULL == strSubjectDot || NULL == strSubjectCommonName)
  1122. {
  1123. hr = E_OUTOFMEMORY;
  1124. _JumpError(hr, error, "Policy:SysAllocString");
  1125. }
  1126. // Clear out any existing subject name info
  1127. hr = pServer->SetCertificateProperty(
  1128. strSubjectDot,
  1129. PROPTYPE_STRING,
  1130. &varValue);
  1131. _JumpIfError(hr, error, "Policy:SetCertificateProperty");
  1132. if (CT_FLAG_SUBJECT_REQUIRE_DIRECTORY_PATH & m_tp.dwSubjectNameFlags)
  1133. {
  1134. hr = _AddDSDistinguishedName(pServer, pRequest);
  1135. _JumpIfError(hr, error, "Policy:_AddDSDistinguishedName");
  1136. }
  1137. else
  1138. if ((CT_FLAG_SUBJECT_REQUIRE_COMMON_NAME |
  1139. CT_FLAG_SUBJECT_REQUIRE_DNS_AS_CN) & m_tp.dwSubjectNameFlags)
  1140. {
  1141. if (!pRequest->_IsUser() ||
  1142. (pRequest->_IsXenrollRequest() &&
  1143. pRequest->_IsNTClientOlder(
  1144. 5,
  1145. 0,
  1146. VERSION_AUTOENROLLMENT_UPN_AWARE,
  1147. VER_PLATFORM_WIN32_NT)))
  1148. {
  1149. // The UPN will be either a user UPN or the machine DNS name
  1150. if (NULL == pRequest->m_pwszUPN)
  1151. {
  1152. hr = E_POINTER; // We should never get this
  1153. _JumpError(hr, error, "Policy:NULL UPN");
  1154. }
  1155. strCN = SysAllocString(pRequest->m_pwszUPN);
  1156. if (NULL == strCN)
  1157. {
  1158. hr = E_OUTOFMEMORY;
  1159. _JumpError(hr, error, "Policy:SysAllocString");
  1160. }
  1161. }
  1162. else
  1163. {
  1164. // We are talking to an advanced client which can deal with a UPN
  1165. // in a SubjectAltName extension. Put the DS CN in the cert.
  1166. hr = pRequest->_GetValueString(DS_ATTR_COMMON_NAME, &strCN);
  1167. _JumpIfErrorStr(
  1168. hr,
  1169. error,
  1170. "Policy:_GetValueString",
  1171. DS_ATTR_COMMON_NAME);
  1172. }
  1173. CSASSERT(NULL != strCN);
  1174. varValue.vt = VT_BSTR;
  1175. varValue.bstrVal = const_cast<BSTR>(strCN);
  1176. hr = pServer->SetCertificateProperty(
  1177. strSubjectCommonName,
  1178. PROPTYPE_STRING,
  1179. &varValue);
  1180. _JumpIfError(hr, error, "Policy:SetCertificateProperty");
  1181. }
  1182. if (CT_FLAG_SUBJECT_REQUIRE_EMAIL & m_tp.dwSubjectNameFlags)
  1183. {
  1184. hr = pRequest->_GetValueString(DS_ATTR_EMAIL_ADDR, &strEMail);
  1185. if (S_OK != hr)
  1186. {
  1187. if (CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion &&
  1188. 0 == (EDITF_EMAILOPTIONAL & m_pPolicy->GetEditFlags()))
  1189. {
  1190. hr = CERTSRV_E_SUBJECT_EMAIL_REQUIRED;
  1191. _JumpError(hr, error, "Policy:_AddSubjectName:EMail");
  1192. }
  1193. pRequest->BuildErrorInfo(
  1194. hr,
  1195. MSG_NO_EMAIL_NAME,
  1196. &pRequest->m_strUserDN);
  1197. }
  1198. else
  1199. {
  1200. varValue.vt = VT_BSTR;
  1201. varValue.bstrVal = const_cast<BSTR>(strEMail);
  1202. strPropEMail = SysAllocString(wszPROPSUBJECTEMAIL);
  1203. if (NULL == strPropEMail)
  1204. {
  1205. hr = E_OUTOFMEMORY;
  1206. _JumpError(hr, error, "Policy:SysAllocStringLen");
  1207. }
  1208. hr = pServer->SetCertificateProperty(
  1209. strPropEMail,
  1210. PROPTYPE_STRING,
  1211. &varValue);
  1212. _JumpIfError(hr, error, "Policy:SetCertificateProperty");
  1213. }
  1214. }
  1215. hr = S_OK;
  1216. error:
  1217. if (NULL != strPropEMail)
  1218. {
  1219. SysFreeString(strPropEMail);
  1220. }
  1221. if (NULL != strCN)
  1222. {
  1223. SysFreeString(const_cast<BSTR>(strCN));
  1224. }
  1225. if (NULL != strEMail)
  1226. {
  1227. SysFreeString(const_cast<BSTR>(strEMail));
  1228. }
  1229. if (NULL != strSubjectDot)
  1230. {
  1231. SysFreeString(strSubjectDot);
  1232. }
  1233. if (NULL != strSubjectCommonName)
  1234. {
  1235. SysFreeString(strSubjectCommonName);
  1236. }
  1237. return(hr);
  1238. }
  1239. HRESULT
  1240. tpDsUnquoteRdnValue(
  1241. IN DWORD cwcVal,
  1242. IN WCHAR const *pwcVal,
  1243. OUT WCHAR **ppwszVal)
  1244. {
  1245. HRESULT hr;
  1246. DWORD cwc;
  1247. *ppwszVal = NULL;
  1248. cwc = 0;
  1249. while (TRUE)
  1250. {
  1251. hr = DsUnquoteRdnValue(cwcVal, pwcVal, &cwc, *ppwszVal);
  1252. if (S_OK != hr)
  1253. {
  1254. hr = myHError(hr);
  1255. if (NULL == *ppwszVal)
  1256. {
  1257. if (HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW) == hr)
  1258. {
  1259. hr = S_OK;
  1260. }
  1261. }
  1262. else
  1263. {
  1264. LocalFree(*ppwszVal);
  1265. *ppwszVal = NULL;
  1266. }
  1267. _JumpIfError(hr, error, "Policy:DsUnquoteRdnValue");
  1268. }
  1269. if (NULL != *ppwszVal)
  1270. {
  1271. (*ppwszVal)[cwc] = L'\0';
  1272. break;
  1273. }
  1274. *ppwszVal = (WCHAR *) LocalAlloc(LMEM_FIXED, sizeof(WCHAR) * (cwc + 1));
  1275. if (NULL == *ppwszVal)
  1276. {
  1277. hr = E_OUTOFMEMORY;
  1278. _JumpError(hr, error, "Policy:LocalAlloc");
  1279. }
  1280. }
  1281. hr = S_OK;
  1282. error:
  1283. return(hr);
  1284. }
  1285. HRESULT
  1286. tpSetRequestRDN(
  1287. IN ICertServerPolicy *pServer,
  1288. IN WCHAR const *pwcKey,
  1289. IN DWORD cwcKey,
  1290. IN WCHAR const *pwcVal,
  1291. IN DWORD cwcVal)
  1292. {
  1293. HRESULT hr;
  1294. WCHAR *pwszVal = NULL;
  1295. BSTR strRDNName = NULL;
  1296. BSTR strValueOld = NULL;
  1297. BSTR strValue = NULL;
  1298. VARIANT varNew;
  1299. hr = tpDsUnquoteRdnValue(cwcVal, pwcVal, &pwszVal);
  1300. _JumpIfError(hr, error, "Policy:tpDsUnquoteRdnValue");
  1301. strRDNName = SysAllocStringLen(
  1302. NULL,
  1303. WSZARRAYSIZE(wszPROPSUBJECTDOT) + cwcKey);
  1304. if (NULL == strRDNName)
  1305. {
  1306. hr = E_OUTOFMEMORY;
  1307. _JumpError(hr, error, "Policy:SysAllocStringLen");
  1308. }
  1309. wcscpy(strRDNName, wszPROPSUBJECTDOT);
  1310. CopyMemory(
  1311. &strRDNName[WSZARRAYSIZE(wszPROPSUBJECTDOT)],
  1312. pwcKey,
  1313. sizeof(WCHAR) * cwcKey);
  1314. strRDNName[WSZARRAYSIZE(wszPROPSUBJECTDOT) + cwcKey] = L'\0';
  1315. CSASSERT(SysStringByteLen(strRDNName) == wcslen(strRDNName) * sizeof(WCHAR));
  1316. hr = polGetCertificateStringProperty(pServer, strRDNName, &strValueOld);
  1317. if (S_OK == hr)
  1318. {
  1319. strValue = SysAllocStringLen(
  1320. NULL,
  1321. wcslen(pwszVal) +
  1322. WSZARRAYSIZE(wszNAMESEPARATORDEFAULT) +
  1323. wcslen(strValueOld));
  1324. if (NULL == strValue)
  1325. {
  1326. hr = E_OUTOFMEMORY;
  1327. _JumpError(hr, error, "Policy:SysAllocStringLen");
  1328. }
  1329. wcscpy(strValue, pwszVal);
  1330. wcscat(strValue, wszNAMESEPARATORDEFAULT);
  1331. wcscat(strValue, strValueOld);
  1332. }
  1333. else
  1334. {
  1335. strValue = SysAllocString(pwszVal);
  1336. if (NULL == strValue)
  1337. {
  1338. hr = E_OUTOFMEMORY;
  1339. _JumpError(hr, error, "Policy:SysAllocStringLen");
  1340. }
  1341. }
  1342. CSASSERT(SysStringByteLen(strValue) == wcslen(strValue) * sizeof(WCHAR));
  1343. varNew.vt = VT_BSTR;
  1344. varNew.bstrVal = strValue;
  1345. hr = pServer->SetCertificateProperty(strRDNName, PROPTYPE_STRING, &varNew);
  1346. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1347. {
  1348. hr = CERTSRV_E_BAD_REQUESTSUBJECT;
  1349. }
  1350. _JumpIfError(hr, error, "Policy:SetCertificateProperty");
  1351. error:
  1352. if (NULL != pwszVal)
  1353. {
  1354. LocalFree(pwszVal);
  1355. }
  1356. if (NULL != strRDNName)
  1357. {
  1358. SysFreeString(strRDNName);
  1359. }
  1360. if (NULL != strValueOld)
  1361. {
  1362. SysFreeString(strValueOld);
  1363. }
  1364. if (NULL != strValue)
  1365. {
  1366. SysFreeString(strValue);
  1367. }
  1368. return(hr);
  1369. }
  1370. DWORD
  1371. s_myDsGetRdnW(
  1372. IN OUT WCHAR const **ppwcDN,
  1373. IN OUT DWORD *pcwcDN,
  1374. OUT WCHAR const **ppwcKey,
  1375. OUT DWORD *pcwcKey,
  1376. OUT WCHAR const **ppwcVal,
  1377. OUT DWORD *pcwcVal)
  1378. {
  1379. HRESULT hr;
  1380. WCHAR const *pwc = *ppwcDN;
  1381. DWORD cwc = *pcwcDN;
  1382. if (0 < cwc && L',' == *pwc)
  1383. {
  1384. pwc++;
  1385. cwc--;
  1386. }
  1387. hr = ERROR_DS_NAME_UNPARSEABLE;
  1388. *ppwcKey = pwc;
  1389. while (TRUE)
  1390. {
  1391. if (0 == cwc)
  1392. {
  1393. _JumpError(hr, error, "no key");
  1394. }
  1395. if (L'=' == *pwc)
  1396. {
  1397. break;
  1398. }
  1399. pwc++;
  1400. cwc--;
  1401. }
  1402. *pcwcKey = SAFE_SUBTRACT_POINTERS(pwc, *ppwcKey);
  1403. pwc++;
  1404. cwc--;
  1405. *ppwcVal = pwc;
  1406. if (0 == cwc)
  1407. {
  1408. _JumpError(hr, error, "no value");
  1409. }
  1410. while (TRUE)
  1411. {
  1412. if (0 == cwc || L',' == *pwc)
  1413. {
  1414. break;
  1415. }
  1416. pwc++;
  1417. cwc--;
  1418. }
  1419. *pcwcVal = SAFE_SUBTRACT_POINTERS(pwc, *ppwcVal);
  1420. *ppwcDN = pwc;
  1421. *pcwcDN = cwc;
  1422. hr = S_OK;
  1423. error:
  1424. return(hr);
  1425. }
  1426. typedef DWORD (WINAPI FNDSGETRDNW)(
  1427. IN OUT LPCWCH *ppDN,
  1428. IN OUT DWORD *pcDN,
  1429. OUT LPCWCH *ppKey,
  1430. OUT DWORD *pcKey,
  1431. OUT LPCWCH *ppVal,
  1432. OUT DWORD *pcVal);
  1433. DWORD
  1434. myDsGetRdn(
  1435. IN OUT WCHAR const **ppwcDN,
  1436. IN OUT DWORD *pcwcDN,
  1437. OUT WCHAR const **ppwcKey,
  1438. OUT DWORD *pcwcKey,
  1439. OUT WCHAR const **ppwcVal,
  1440. OUT DWORD *pcwcVal)
  1441. {
  1442. HRESULT hr;
  1443. HMODULE hModule;
  1444. static FNDSGETRDNW *s_pfn = NULL;
  1445. if (NULL == s_pfn)
  1446. {
  1447. hModule = GetModuleHandle(TEXT("ntdsapi.dll"));
  1448. if (NULL == hModule)
  1449. {
  1450. hr = GetLastError();
  1451. goto error;
  1452. }
  1453. // load system function
  1454. s_pfn = (FNDSGETRDNW *) GetProcAddress(hModule, "DsGetRdnW");
  1455. if (NULL == s_pfn)
  1456. {
  1457. hr = GetLastError();
  1458. _PrintError(hr, "ntdsapi.dll!DsGetRdnW");
  1459. s_pfn = s_myDsGetRdnW;
  1460. }
  1461. }
  1462. hr = (*s_pfn)(ppwcDN, pcwcDN, ppwcKey, pcwcKey, ppwcVal, pcwcVal);
  1463. _JumpIfError(hr, error, "Policy:DsGetRdnW");
  1464. error:
  1465. return(hr);
  1466. }
  1467. HRESULT
  1468. CTemplatePolicy::_AddDSDistinguishedName(
  1469. IN ICertServerPolicy *pServer,
  1470. CRequestInstance *pRequest)
  1471. {
  1472. HRESULT hr;
  1473. WCHAR const *pwcDN;
  1474. DWORD cwcDN;
  1475. DWORD cRDN;
  1476. cRDN = 0;
  1477. pwcDN = pRequest->m_strUserDN;
  1478. if (NULL != pwcDN)
  1479. {
  1480. WCHAR const *pwcKey;
  1481. WCHAR const *pwcVal;
  1482. DWORD cwcKey;
  1483. DWORD cwcVal;
  1484. cwcDN = wcslen(pwcDN);
  1485. while (0 != cwcDN)
  1486. {
  1487. hr = myDsGetRdn(&pwcDN, &cwcDN, &pwcKey, &cwcKey, &pwcVal, &cwcVal);
  1488. if (S_OK != hr)
  1489. {
  1490. hr = myHError(hr);
  1491. _JumpError(hr, error, "Policy:myDsGetRdn");
  1492. }
  1493. if (0 != cwcKey && 0 != cwcVal)
  1494. {
  1495. hr = tpSetRequestRDN(
  1496. pServer,
  1497. pwcKey,
  1498. cwcKey,
  1499. pwcVal,
  1500. cwcVal);
  1501. _JumpIfError(hr, error, "Policy:tpSetRequestRDN");
  1502. cRDN++;
  1503. }
  1504. }
  1505. }
  1506. if (0 == cRDN)
  1507. {
  1508. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  1509. _JumpError(hr, error, "Policy:m_strUserDN");
  1510. }
  1511. hr = S_OK;
  1512. error:
  1513. return(hr);
  1514. }
  1515. //+--------------------------------------------------------------------------
  1516. // CCertPolicyEnterprise::_AddAltSubjectName
  1517. //
  1518. // Returns S_OK on success.
  1519. //+--------------------------------------------------------------------------
  1520. HRESULT
  1521. CTemplatePolicy::_AddAltSubjectName(
  1522. IN ICertServerPolicy *pServer,
  1523. IN OUT CRequestInstance *pRequest)
  1524. {
  1525. HRESULT hr = S_OK;
  1526. DWORD cbExtension;
  1527. VARIANT varExtension;
  1528. DWORD iNameEntry;
  1529. WCHAR **ppwszCurName;
  1530. CERT_OTHER_NAME objectGuidOtherName;
  1531. CERT_OTHER_NAME upnOtherName;
  1532. WCHAR **apwszMailNames = NULL;
  1533. WCHAR **apwszMachineNames = NULL;
  1534. BYTE *pbExtension= NULL;
  1535. BSTR strobjectGuid = NULL;
  1536. CERT_ALT_NAME_INFO AltName;
  1537. AltName.cAltEntry = 0;
  1538. AltName.rgAltEntry = NULL;
  1539. objectGuidOtherName.Value.pbData = NULL;
  1540. objectGuidOtherName.Value.cbData = 0;
  1541. upnOtherName.Value.pbData = NULL;
  1542. upnOtherName.Value.cbData = 0;
  1543. VariantInit(&varExtension);
  1544. // If this cert template doesn't set the alt-subject-name, then enable
  1545. // whatever alt subject name that was in the request.
  1546. if (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME & m_tp.dwSubjectNameFlags)
  1547. {
  1548. LONG ExtFlags;
  1549. hr = polGetCertificateExtension(
  1550. pServer,
  1551. TEXT(szOID_SUBJECT_ALT_NAME2),
  1552. PROPTYPE_BINARY,
  1553. &varExtension);
  1554. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  1555. {
  1556. hr = CERTSRV_E_SUBJECT_ALT_NAME_REQUIRED;
  1557. }
  1558. _JumpIfError(hr, error, "Policy:polGetCertificateExtension");
  1559. hr = pServer->GetCertificateExtensionFlags(&ExtFlags);
  1560. _JumpIfError(hr, error, "Policy:GetCertificateExtensionFlags");
  1561. if (EXTENSION_DISABLE_FLAG & ExtFlags)
  1562. {
  1563. ExtFlags &= ~EXTENSION_DISABLE_FLAG;
  1564. hr = polSetCertificateExtension(
  1565. pServer,
  1566. TEXT(szOID_SUBJECT_ALT_NAME2),
  1567. PROPTYPE_BINARY,
  1568. ExtFlags,
  1569. &varExtension);
  1570. _JumpIfError(hr, error, "Policy:polSetCertificateExtension");
  1571. }
  1572. CSASSERT(S_OK == hr);
  1573. goto error;
  1574. }
  1575. // We do alt name entries for
  1576. // UPN/SPN
  1577. // rfc822 (mail name)
  1578. // DNSname
  1579. // DS location
  1580. if ((CT_FLAG_SUBJECT_ALT_REQUIRE_UPN | CT_FLAG_SUBJECT_ALT_REQUIRE_SPN) &
  1581. m_tp.dwSubjectNameFlags)
  1582. {
  1583. // Add the UPN
  1584. if (NULL == pRequest->m_pwszUPN)
  1585. {
  1586. hr = CERTSRV_E_SUBJECT_UPN_REQUIRED;
  1587. _JumpError(hr, error, "Policy:_AddAltSubjectName:UPN");
  1588. }
  1589. AltName.cAltEntry++;
  1590. }
  1591. if (CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL & m_tp.dwSubjectNameFlags)
  1592. {
  1593. hr = pRequest->_GetValues(DS_ATTR_EMAIL_ADDR, &apwszMailNames);
  1594. if (S_OK != hr || NULL == apwszMailNames || NULL == apwszMailNames[0])
  1595. {
  1596. _PrintIfError(hr, "_GetValues(email)");
  1597. if (CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion &&
  1598. 0 == (EDITF_EMAILOPTIONAL & m_pPolicy->GetEditFlags()))
  1599. {
  1600. hr = CERTSRV_E_SUBJECT_EMAIL_REQUIRED;
  1601. _JumpError(hr, error, "Policy:_AddAltSubjectName:EMail");
  1602. }
  1603. pRequest->BuildErrorInfo(
  1604. hr,
  1605. MSG_NO_EMAIL_NAME,
  1606. &pRequest->m_strUserDN);
  1607. }
  1608. else
  1609. {
  1610. ppwszCurName = apwszMailNames;
  1611. while (NULL != *ppwszCurName)
  1612. {
  1613. AltName.cAltEntry++;
  1614. ppwszCurName++;
  1615. }
  1616. }
  1617. }
  1618. if (CT_FLAG_SUBJECT_ALT_REQUIRE_DIRECTORY_GUID & m_tp.dwSubjectNameFlags)
  1619. {
  1620. hr = pRequest->_GetObjectGUID(&strobjectGuid);
  1621. if (S_OK != hr || NULL == strobjectGuid)
  1622. {
  1623. _PrintIfError(hr, "_GetObjectGUID");
  1624. hr = CERTSRV_E_SUBJECT_DIRECTORY_GUID_REQUIRED;
  1625. _JumpError(hr, error, "Policy:_AddAltSubjectName:GUID");
  1626. }
  1627. AltName.cAltEntry++;
  1628. }
  1629. if (CT_FLAG_SUBJECT_ALT_REQUIRE_DNS & m_tp.dwSubjectNameFlags)
  1630. {
  1631. hr = pRequest->_GetValues(DS_ATTR_DNS_NAME, &apwszMachineNames);
  1632. if (S_OK != hr || NULL == apwszMachineNames || NULL == apwszMachineNames[0])
  1633. {
  1634. _PrintIfError(hr, "_GetValues(dns)");
  1635. hr = CERTSRV_E_SUBJECT_DNS_REQUIRED;
  1636. _JumpError(hr, error, "Policy:_AddAltSubjectName:DNS");
  1637. }
  1638. ppwszCurName = apwszMachineNames;
  1639. while (NULL != *ppwszCurName)
  1640. {
  1641. AltName.cAltEntry++;
  1642. ppwszCurName++;
  1643. }
  1644. }
  1645. if (AltName.cAltEntry == 0)
  1646. {
  1647. hr = S_OK;
  1648. goto error;
  1649. }
  1650. AltName.rgAltEntry = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  1651. LMEM_FIXED,
  1652. sizeof(CERT_ALT_NAME_ENTRY) * AltName.cAltEntry);
  1653. if (NULL == AltName.rgAltEntry)
  1654. {
  1655. hr = E_OUTOFMEMORY;
  1656. _JumpError(hr, error, "Policy:LocalAlloc");
  1657. }
  1658. iNameEntry = 0;
  1659. if ((CT_FLAG_SUBJECT_ALT_REQUIRE_UPN | CT_FLAG_SUBJECT_ALT_REQUIRE_SPN) &
  1660. m_tp.dwSubjectNameFlags)
  1661. {
  1662. // Add the UPN
  1663. CERT_NAME_VALUE nameUpn;
  1664. nameUpn.dwValueType = CERT_RDN_UTF8_STRING;
  1665. nameUpn.Value.pbData = (BYTE *) pRequest->m_pwszUPN;
  1666. nameUpn.Value.cbData = wcslen(pRequest->m_pwszUPN) * sizeof(WCHAR);
  1667. if (!myEncodeObject(
  1668. X509_ASN_ENCODING,
  1669. X509_UNICODE_ANY_STRING,
  1670. &nameUpn,
  1671. 0,
  1672. CERTLIB_USE_LOCALALLOC,
  1673. &upnOtherName.Value.pbData,
  1674. &upnOtherName.Value.cbData))
  1675. {
  1676. hr = myHLastError();
  1677. _JumpError(hr, error, "Policy:myEncodeObject");
  1678. }
  1679. upnOtherName.pszObjId = szOID_NT_PRINCIPAL_NAME;
  1680. AltName.rgAltEntry[iNameEntry].dwAltNameChoice= CERT_ALT_NAME_OTHER_NAME;
  1681. AltName.rgAltEntry[iNameEntry++].pOtherName = &upnOtherName;
  1682. }
  1683. // Now do strobjectGuid
  1684. if (CT_FLAG_SUBJECT_ALT_REQUIRE_DIRECTORY_GUID & m_tp.dwSubjectNameFlags)
  1685. {
  1686. CRYPT_DATA_BLOB blobGuid;
  1687. CSASSERT(NULL != strobjectGuid);
  1688. blobGuid.pbData = (BYTE *) strobjectGuid;
  1689. blobGuid.cbData = SysStringByteLen(strobjectGuid);
  1690. objectGuidOtherName.pszObjId = szOID_NTDS_REPLICATION;
  1691. if (!myEncodeObject(
  1692. X509_ASN_ENCODING,
  1693. X509_OCTET_STRING,
  1694. &blobGuid,
  1695. 0,
  1696. CERTLIB_USE_LOCALALLOC,
  1697. &objectGuidOtherName.Value.pbData,
  1698. &objectGuidOtherName.Value.cbData))
  1699. {
  1700. hr = myHLastError();
  1701. _JumpError(hr, error, "Policy:myEncodeObject");
  1702. }
  1703. AltName.rgAltEntry[iNameEntry].dwAltNameChoice= CERT_ALT_NAME_OTHER_NAME;
  1704. AltName.rgAltEntry[iNameEntry++].pOtherName = &objectGuidOtherName;
  1705. }
  1706. // Now do rfc822
  1707. if (CT_FLAG_SUBJECT_ALT_REQUIRE_EMAIL & m_tp.dwSubjectNameFlags)
  1708. {
  1709. ppwszCurName = apwszMailNames;
  1710. if (NULL != ppwszCurName)
  1711. {
  1712. while (NULL != *ppwszCurName)
  1713. {
  1714. AltName.rgAltEntry[iNameEntry].dwAltNameChoice= CERT_ALT_NAME_RFC822_NAME;
  1715. AltName.rgAltEntry[iNameEntry++].pwszRfc822Name = *ppwszCurName;
  1716. ppwszCurName++;
  1717. }
  1718. }
  1719. }
  1720. // Now do DNS
  1721. if (CT_FLAG_SUBJECT_ALT_REQUIRE_DNS & m_tp.dwSubjectNameFlags)
  1722. {
  1723. ppwszCurName = apwszMachineNames;
  1724. if (NULL != ppwszCurName)
  1725. {
  1726. while (NULL != *ppwszCurName)
  1727. {
  1728. AltName.rgAltEntry[iNameEntry].dwAltNameChoice= CERT_ALT_NAME_DNS_NAME;
  1729. AltName.rgAltEntry[iNameEntry++].pwszRfc822Name = *ppwszCurName;
  1730. ppwszCurName++;
  1731. }
  1732. }
  1733. }
  1734. if (!myEncodeObject(
  1735. X509_ASN_ENCODING,
  1736. X509_ALTERNATE_NAME,
  1737. &AltName,
  1738. 0,
  1739. CERTLIB_USE_LOCALALLOC,
  1740. &pbExtension,
  1741. &cbExtension))
  1742. {
  1743. hr = myHLastError();
  1744. _JumpError(hr, error, "Policy:myEncodeObject");
  1745. }
  1746. varExtension.vt = VT_BSTR;
  1747. varExtension.bstrVal = SysAllocStringByteLen(
  1748. (char const *) pbExtension,
  1749. cbExtension);
  1750. if (NULL == varExtension.bstrVal)
  1751. {
  1752. hr = E_OUTOFMEMORY;
  1753. _JumpError(hr, error, "Policy:SysAllocStringByteLen");
  1754. }
  1755. hr = polSetCertificateExtension(
  1756. pServer,
  1757. TEXT(szOID_SUBJECT_ALT_NAME2),
  1758. PROPTYPE_BINARY,
  1759. 0,
  1760. &varExtension);
  1761. _JumpIfError(hr, error, "Policy:polSetCertificateExtension");
  1762. error:
  1763. if (NULL != pbExtension)
  1764. {
  1765. LocalFree(pbExtension);
  1766. }
  1767. if (NULL != strobjectGuid)
  1768. {
  1769. SysFreeString(strobjectGuid);
  1770. }
  1771. if (NULL != AltName.rgAltEntry)
  1772. {
  1773. // clean each entry in array
  1774. for (DWORD i = 0; i < AltName.cAltEntry; i++)
  1775. {
  1776. switch (AltName.rgAltEntry[i].dwAltNameChoice)
  1777. {
  1778. case CERT_ALT_NAME_DIRECTORY_NAME:
  1779. {
  1780. if (NULL != AltName.rgAltEntry[i].DirectoryName.pbData)
  1781. {
  1782. LocalFree(AltName.rgAltEntry[i].DirectoryName.pbData);
  1783. AltName.rgAltEntry[i].DirectoryName.pbData = NULL;
  1784. }
  1785. break;
  1786. }
  1787. case CERT_ALT_NAME_OTHER_NAME:
  1788. // points to objectGuidOtherName or bstrUpn, which are
  1789. // freed separately
  1790. break;
  1791. case CERT_ALT_NAME_RFC822_NAME:
  1792. // points to apwszMailNames, freed later
  1793. break;
  1794. case CERT_ALT_NAME_DNS_NAME:
  1795. // points to apwszMachineNames, freed later
  1796. break;
  1797. }
  1798. }
  1799. // free array
  1800. LocalFree(AltName.rgAltEntry);
  1801. }
  1802. if (NULL != objectGuidOtherName.Value.pbData)
  1803. {
  1804. LocalFree(objectGuidOtherName.Value.pbData);
  1805. }
  1806. if (NULL != upnOtherName.Value.pbData)
  1807. {
  1808. LocalFree(upnOtherName.Value.pbData);
  1809. }
  1810. if (NULL != pRequest)
  1811. {
  1812. if (NULL != apwszMailNames)
  1813. {
  1814. pRequest->_FreeValues(apwszMailNames);
  1815. }
  1816. if (NULL != apwszMachineNames)
  1817. {
  1818. pRequest->_FreeValues(apwszMachineNames);
  1819. }
  1820. }
  1821. VariantClear(&varExtension);
  1822. return(hr);
  1823. }
  1824. #ifdef DBG_CERTSRV_DEBUG_PRINT
  1825. # define DBGPRINTTIMEORPERIOD(pszDesc, pft) \
  1826. policyDbgPrintTimeOrPeriod((pszDesc), (pft))
  1827. VOID
  1828. policyDbgPrintTimeOrPeriod(
  1829. IN char const *pszDesc,
  1830. IN FILETIME const *pft)
  1831. {
  1832. HRESULT hr;
  1833. WCHAR *pwszTime = NULL;
  1834. WCHAR awc[1];
  1835. if (0 <= (LONG) pft->dwHighDateTime)
  1836. {
  1837. hr = myGMTFileTimeToWszLocalTime(pft, TRUE, &pwszTime);
  1838. _PrintIfError(hr, "myGMTFileTimeToWszLocalTime");
  1839. }
  1840. else
  1841. {
  1842. hr = myFileTimePeriodToWszTimePeriod(pft, TRUE, &pwszTime);
  1843. _PrintIfError(hr, "myFileTimePeriodToWszTimePeriod");
  1844. }
  1845. if (S_OK != hr)
  1846. {
  1847. awc[0] = L'\0';
  1848. pwszTime = awc;
  1849. }
  1850. DBGPRINT((DBG_SS_CERTPOL, "%hs: %ws\n", pszDesc, pwszTime));
  1851. //error:
  1852. if (NULL != pwszTime && awc != pwszTime)
  1853. {
  1854. LocalFree(pwszTime);
  1855. }
  1856. }
  1857. #else // DBG_CERTSRV_DEBUG_PRINT
  1858. # define DBGPRINTTIMEORPERIOD(pszDesc, pft)
  1859. #endif // DBG_CERTSRV_DEBUG_PRINT
  1860. //+--------------------------------------------------------------------------
  1861. // CCertPolicyEnterprise::_ApplyExpirationTime
  1862. //
  1863. // Returns S_OK on success.
  1864. //+--------------------------------------------------------------------------
  1865. HRESULT
  1866. CTemplatePolicy::_ApplyExpirationTime(
  1867. IN ICertServerPolicy *pServer,
  1868. IN OUT CRequestInstance *pRequest)
  1869. {
  1870. HRESULT hr = S_OK;
  1871. VARIANT varValue;
  1872. BSTR strNameNotBefore = NULL;
  1873. BSTR strNameNotAfter = NULL;
  1874. SYSTEMTIME SystemTime;
  1875. LLFILETIME llftNotAfter;
  1876. LLFILETIME llftNotAfterCalc;
  1877. LLFILETIME llftNotBefore;
  1878. LLFILETIME llftNotAfterOverlap;
  1879. WCHAR const *pwszTemplate;
  1880. VariantInit(&varValue);
  1881. pwszTemplate = m_pwszTemplateName;
  1882. if (NULL == pwszTemplate)
  1883. {
  1884. pwszTemplate = m_pwszTemplateObjId;
  1885. }
  1886. strNameNotBefore = SysAllocString(wszPROPCERTIFICATENOTBEFOREDATE);
  1887. if (NULL == strNameNotBefore)
  1888. {
  1889. hr = E_OUTOFMEMORY;
  1890. _JumpError(hr, error, "Policy:SysAllocString");
  1891. }
  1892. hr = pServer->GetCertificateProperty(
  1893. strNameNotBefore,
  1894. PROPTYPE_DATE,
  1895. &varValue);
  1896. _JumpIfError(hr, error, "Policy:GetCertificateProperty");
  1897. if (VT_DATE != varValue.vt)
  1898. {
  1899. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1900. _JumpError(hr, error, "Policy:varValue.vt");
  1901. }
  1902. if (!VariantTimeToSystemTime(varValue.date, &SystemTime))
  1903. {
  1904. hr = myHLastError();
  1905. _JumpError(hr, error, "Policy:VariantTimeToSystemTime");
  1906. }
  1907. if (!SystemTimeToFileTime(&SystemTime, &llftNotBefore.ft))
  1908. {
  1909. hr = myHLastError();
  1910. _JumpError(hr, error, "Policy:SystemTimeToFileTime");
  1911. }
  1912. strNameNotAfter = SysAllocString(wszPROPCERTIFICATENOTAFTERDATE);
  1913. if (NULL == strNameNotAfter)
  1914. {
  1915. hr = E_OUTOFMEMORY;
  1916. _JumpError(hr, error, "Policy:SysAllocString");
  1917. }
  1918. VariantClear(&varValue);
  1919. hr = pServer->GetCertificateProperty(
  1920. strNameNotAfter,
  1921. PROPTYPE_DATE,
  1922. &varValue);
  1923. _JumpIfError(hr, error, "Policy:GetCertificateProperty");
  1924. if (VT_DATE != varValue.vt)
  1925. {
  1926. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1927. _JumpError(hr, error, "Policy:varValue.vt");
  1928. }
  1929. if (!VariantTimeToSystemTime(varValue.date, &SystemTime))
  1930. {
  1931. hr = myHLastError();
  1932. _JumpError(hr, error, "Policy:VariantTimeToSystemTime");
  1933. }
  1934. if (!SystemTimeToFileTime(&SystemTime, &llftNotAfter.ft))
  1935. {
  1936. hr = myHLastError();
  1937. _JumpError(hr, error, "Policy:SystemTimeToFileTime");
  1938. }
  1939. if (0 > m_tp.llftExpirationPeriod.ll)
  1940. {
  1941. llftNotAfterCalc.ll = llftNotBefore.ll - m_tp.llftExpirationPeriod.ll;
  1942. }
  1943. else
  1944. {
  1945. llftNotAfterCalc.ll = m_tp.llftExpirationPeriod.ll;
  1946. }
  1947. if (llftNotAfterCalc.ll > llftNotAfter.ll)
  1948. {
  1949. // truncated!
  1950. llftNotAfterCalc.ll = llftNotAfter.ll;
  1951. pRequest->BuildErrorInfo(
  1952. S_OK,
  1953. MSG_TEMPLATE_VALIDITY_TOO_LONG,
  1954. &pwszTemplate);
  1955. }
  1956. if (!FileTimeToSystemTime(&llftNotAfterCalc.ft, &SystemTime))
  1957. {
  1958. hr = myHLastError();
  1959. _JumpError(hr, error, "Policy:FileTimeToSystemTime");
  1960. }
  1961. if (!SystemTimeToVariantTime(&SystemTime, &varValue.date))
  1962. {
  1963. hr = myHLastError();
  1964. _JumpError(hr, error, "Policy:SystemTimeToVariantTime");
  1965. }
  1966. hr = pServer->SetCertificateProperty(
  1967. strNameNotAfter,
  1968. PROPTYPE_DATE,
  1969. &varValue);
  1970. if (S_OK != hr)
  1971. {
  1972. DBGPRINTTIMEORPERIOD(" Old NotBefore", &llftNotBefore.ft);
  1973. DBGPRINTTIMEORPERIOD(" Old NotAfter", &llftNotAfter.ft);
  1974. DBGPRINTTIMEORPERIOD("Template Period", &m_tp.llftExpirationPeriod.ft);
  1975. DBGPRINTTIMEORPERIOD(" New NotAfter", &llftNotAfterCalc.ft);
  1976. }
  1977. _JumpIfError(hr, error, "Policy:SetCertificateProperty");
  1978. // Verify new cert will be valid for at least as long as the overlap period
  1979. if (0 > m_tp.llftOverlapPeriod.ll)
  1980. {
  1981. llftNotAfterOverlap.ll = llftNotBefore.ll - m_tp.llftOverlapPeriod.ll;
  1982. }
  1983. else
  1984. {
  1985. llftNotAfterOverlap.ll = m_tp.llftOverlapPeriod.ll;
  1986. }
  1987. if (llftNotAfterOverlap.ll > llftNotAfter.ll)
  1988. {
  1989. LONG RequestFlags;
  1990. hr = polGetRequestLongProperty(
  1991. pServer,
  1992. wszPROPREQUESTFLAGS,
  1993. &RequestFlags);
  1994. _JumpIfErrorStr(
  1995. hr,
  1996. error,
  1997. "Policy:polGetRequestLongProperty",
  1998. wszPROPREQUESTFLAGS);
  1999. if (CR_FLG_RENEWAL & RequestFlags)
  2000. {
  2001. // too little life left, log and fail!
  2002. pRequest->BuildErrorInfo(
  2003. S_OK,
  2004. MSG_TEMPLATE_OVERLAP_TOO_LONG,
  2005. &pwszTemplate);
  2006. hr = CERTSRV_E_CERT_TYPE_OVERLAP;
  2007. _JumpError(hr, error, "Overlap too long");
  2008. }
  2009. }
  2010. CSASSERT(S_OK == hr);
  2011. error:
  2012. VariantClear(&varValue);
  2013. if (NULL != strNameNotBefore)
  2014. {
  2015. SysFreeString(strNameNotBefore);
  2016. }
  2017. if (NULL != strNameNotAfter)
  2018. {
  2019. SysFreeString(strNameNotAfter);
  2020. }
  2021. return(hr);
  2022. }
  2023. //+--------------------------------------------------------------------------
  2024. // CCertPolicyEnterprise::_EnforceKeySizePolicy
  2025. //
  2026. // Returns S_OK on success.
  2027. //+--------------------------------------------------------------------------
  2028. HRESULT
  2029. CTemplatePolicy::_EnforceKeySizePolicy(
  2030. IN ICertServerPolicy *pServer)
  2031. {
  2032. HRESULT hr;
  2033. if (0 != m_tp.dwMinKeyLength)
  2034. {
  2035. LONG KeyLength;
  2036. hr = polGetCertificateLongProperty(
  2037. pServer,
  2038. wszPROPCERTIFICATEPUBLICKEYLENGTH,
  2039. &KeyLength);
  2040. _JumpIfErrorStr(
  2041. hr,
  2042. error,
  2043. "Policy:polGetCertificateLongProperty",
  2044. wszPROPCERTIFICATEPUBLICKEYLENGTH);
  2045. if (m_tp.dwMinKeyLength > (DWORD) KeyLength)
  2046. {
  2047. DBGPRINT((
  2048. DBG_SS_ERROR,
  2049. "Key Length %u, expected minimum %u\n",
  2050. KeyLength,
  2051. m_tp.dwMinKeyLength));
  2052. hr = CERTSRV_E_KEY_LENGTH;
  2053. _JumpError(hr, error, "Key too small");
  2054. }
  2055. }
  2056. hr = S_OK;
  2057. error:
  2058. return(hr);
  2059. }
  2060. //+--------------------------------------------------------------------------
  2061. // CCertPolicyEnterprise::_EnforceKeyArchivalPolicy
  2062. //
  2063. // Returns S_OK on success.
  2064. //+--------------------------------------------------------------------------
  2065. HRESULT
  2066. CTemplatePolicy::_EnforceKeyArchivalPolicy(
  2067. IN ICertServerPolicy *pServer)
  2068. {
  2069. HRESULT hr;
  2070. LONG fKeyArchived;
  2071. hr = polGetCertificateLongProperty(
  2072. pServer,
  2073. wszPROPKEYARCHIVED,
  2074. &fKeyArchived);
  2075. _JumpIfErrorStr(
  2076. hr,
  2077. error,
  2078. "Policy:polGetCertificateLongProperty",
  2079. wszPROPKEYARCHIVED);
  2080. if (CT_FLAG_REQUIRE_PRIVATE_KEY_ARCHIVAL & m_tp.dwPrivateKeyFlags)
  2081. {
  2082. if (!fKeyArchived)
  2083. {
  2084. hr = CERTSRV_E_ARCHIVED_KEY_REQUIRED;
  2085. _JumpError(hr, error, "missing archived key");
  2086. }
  2087. }
  2088. else
  2089. {
  2090. if (fKeyArchived)
  2091. {
  2092. hr = CERTSRV_E_ARCHIVED_KEY_UNEXPECTED;
  2093. _JumpError(hr, error, "unexpected archived key");
  2094. }
  2095. }
  2096. hr = S_OK;
  2097. error:
  2098. return(hr);
  2099. }
  2100. //+--------------------------------------------------------------------------
  2101. // CCertPolicyEnterprise::_EnforceSymmetricAlgorithms
  2102. //
  2103. // Returns S_OK on success.
  2104. //+--------------------------------------------------------------------------
  2105. HRESULT
  2106. CTemplatePolicy::_EnforceSymmetricAlgorithms(
  2107. IN ICertServerPolicy *pServer)
  2108. {
  2109. HRESULT hr;
  2110. VARIANT varExtension;
  2111. BOOL fSetNeeded = FALSE;
  2112. LONG ExtFlags = 0;
  2113. BSTR strCSPProvider = NULL;
  2114. VariantInit(&varExtension);
  2115. if (CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS & m_tp.dwEnrollmentFlags)
  2116. {
  2117. hr = polGetCertificateExtension(
  2118. pServer,
  2119. TEXT(szOID_RSA_SMIMECapabilities),
  2120. PROPTYPE_BINARY,
  2121. &varExtension);
  2122. if (CERTSRV_E_PROPERTY_EMPTY != hr)
  2123. {
  2124. _JumpIfError(hr, error, "Policy:GetCertificateExtension");
  2125. hr = pServer->GetCertificateExtensionFlags(&ExtFlags);
  2126. _JumpIfError(hr, error, "Policy:GetCertificateExtensionFlags");
  2127. if (EXTENSION_DISABLE_FLAG & ExtFlags)
  2128. {
  2129. ExtFlags &= ~EXTENSION_DISABLE_FLAG;
  2130. fSetNeeded = TRUE;
  2131. }
  2132. }
  2133. else
  2134. {
  2135. BYTE const *pbSMIME;
  2136. DWORD cbSMIME;
  2137. pbSMIME = m_pPolicy->GetSMIME(&cbSMIME);
  2138. if (0 == (EDITF_ENABLEDEFAULTSMIME & m_pPolicy->GetEditFlags()) ||
  2139. NULL == pbSMIME)
  2140. {
  2141. hr = CERTSRV_E_SMIME_REQUIRED;
  2142. _JumpError(hr, error, "Policy:GetCertificateExtension");
  2143. }
  2144. varExtension.bstrVal = NULL;
  2145. if (!myConvertWszToBstr(
  2146. &varExtension.bstrVal,
  2147. (WCHAR const *) pbSMIME,
  2148. cbSMIME))
  2149. {
  2150. hr = E_OUTOFMEMORY;
  2151. _JumpError(hr, error, "Policy:myConvertWszToBstr");
  2152. }
  2153. varExtension.vt = VT_BSTR;
  2154. fSetNeeded = TRUE;
  2155. }
  2156. }
  2157. if (fSetNeeded)
  2158. {
  2159. hr = polSetCertificateExtension(
  2160. pServer,
  2161. TEXT(szOID_RSA_SMIMECapabilities),
  2162. PROPTYPE_BINARY,
  2163. ExtFlags,
  2164. &varExtension);
  2165. _JumpIfError(hr, error, "Policy:SetCertificateExtension");
  2166. }
  2167. hr = S_OK;
  2168. error:
  2169. if (NULL != strCSPProvider)
  2170. {
  2171. SysFreeString(strCSPProvider);
  2172. }
  2173. VariantClear(&varExtension);
  2174. return(hr);
  2175. }
  2176. #ifdef CERTSRV_EOBO_DCR_APPROVED
  2177. // Fail the request if:
  2178. // the request is for a V2 template
  2179. // AND
  2180. // RequesterName is not the same as the CallerName (enroll-on-behalf-of)
  2181. // AND
  2182. // CT_FLAG_ALLOW_ENROLL_ON_BEHALF_OF is not set in the template flags
  2183. // OR
  2184. // RequesterName *is* the same as the CallerName (not enroll-on-behalf-of)
  2185. // AND
  2186. // CT_FLAG_ALLOW_ENROLL_ON_BEHALF_OF *is* set in the template flags
  2187. #else
  2188. // Fail the request if all of the following are true:
  2189. // 1: the request is for a V2 template
  2190. // 2: no signatures are required by the template
  2191. // 3: the RequesterName is not the same as the CallerName (enroll-on-behalf-of)
  2192. #endif
  2193. HRESULT
  2194. CTemplatePolicy::_EnforceEnrollOnBehalfOfAllowed(
  2195. IN ICertServerPolicy *pServer,
  2196. OUT BOOL *pfEnrollOnBehalfOf)
  2197. {
  2198. HRESULT hr;
  2199. BSTR strRequester = NULL;
  2200. BSTR strCaller = NULL;
  2201. *pfEnrollOnBehalfOf = FALSE;
  2202. hr = polGetRequestStringProperty(
  2203. pServer,
  2204. wszPROPREQUESTERNAME,
  2205. &strRequester);
  2206. _JumpIfErrorStr(
  2207. hr,
  2208. error,
  2209. "Policy:polGetRequestStringProperty",
  2210. wszPROPREQUESTERNAME);
  2211. hr = polGetRequestStringProperty(
  2212. pServer,
  2213. wszPROPCALLERNAME,
  2214. &strCaller);
  2215. _JumpIfErrorStr(
  2216. hr,
  2217. error,
  2218. "Policy:polGetRequestStringProperty",
  2219. wszPROPCALLERNAME);
  2220. *pfEnrollOnBehalfOf = 0 != mylstrcmpiL(strRequester, strCaller);
  2221. if (CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion
  2222. #ifdef CERTSRV_EOBO_DCR_APPROVED
  2223. #else
  2224. && 0 == m_tp.dwcSignatureRequired
  2225. #endif
  2226. )
  2227. {
  2228. #ifdef CERTSRV_EOBO_DCR_APPROVED
  2229. if (!*pfEnrollOnBehalfOf ^
  2230. (0 != (CT_FLAG_ALLOW_ENROLL_ON_BEHALF_OF & m_tp.dwEnrollmentFlags)))
  2231. #else
  2232. if (*pfEnrollOnBehalfOf)
  2233. #endif
  2234. {
  2235. hr = CERTSRV_E_BAD_RENEWAL_SUBJECT;
  2236. _JumpError(hr, error, "EnrollOnBehalfOf allowed/disallowed");
  2237. }
  2238. }
  2239. hr = S_OK; // caller matches requester
  2240. error:
  2241. if (NULL != strRequester)
  2242. {
  2243. SysFreeString(strRequester);
  2244. }
  2245. if (NULL != strCaller)
  2246. {
  2247. SysFreeString(strCaller);
  2248. }
  2249. return(hr);
  2250. }
  2251. HRESULT
  2252. CTemplatePolicy::_EnforceMinimumTemplateVersion(
  2253. IN CRequestInstance *pRequest)
  2254. {
  2255. HRESULT hr;
  2256. DWORD dwRequestTemplateMinimumMajorVersion;
  2257. DWORD dwRequestTemplateMinimumMinorVersion;
  2258. pRequest->GetTemplateVersion(
  2259. &dwRequestTemplateMinimumMajorVersion,
  2260. &dwRequestTemplateMinimumMinorVersion);
  2261. if (m_tp.dwTemplateMajorVersion < dwRequestTemplateMinimumMajorVersion ||
  2262. (m_tp.dwTemplateMajorVersion == dwRequestTemplateMinimumMajorVersion &&
  2263. m_tp.dwTemplateMinorVersion < dwRequestTemplateMinimumMinorVersion))
  2264. {
  2265. DBGPRINT((
  2266. DBG_SS_ERROR,
  2267. "Requested template version %u.%u, Loaded version %u.%u\n",
  2268. dwRequestTemplateMinimumMajorVersion,
  2269. dwRequestTemplateMinimumMinorVersion,
  2270. m_tp.dwTemplateMajorVersion,
  2271. m_tp.dwTemplateMinorVersion));
  2272. hr = CERTSRV_E_BAD_TEMPLATE_VERSION;
  2273. _JumpError(hr, error, "Policy:_EnforceMinimumTemplateVersion");
  2274. }
  2275. hr = S_OK;
  2276. error:
  2277. return(hr);
  2278. }
  2279. HRESULT
  2280. tpSplitPolicies(
  2281. IN BSTR strPolicies,
  2282. OUT DWORD *pcPolicies,
  2283. OUT OBJECTIDLIST **pprgPolicies)
  2284. {
  2285. HRESULT hr;
  2286. WCHAR const *pwszT;
  2287. WCHAR *pwszOut;
  2288. DWORD cPolicies;
  2289. OBJECTIDLIST *prgPolicies;
  2290. DWORD cObjId;
  2291. WCHAR **rgpwszObjId;
  2292. BOOL fNew;
  2293. *pprgPolicies = NULL;
  2294. pwszT = strPolicies;
  2295. cPolicies = 1; // plus one per newline separator
  2296. cObjId = 0;
  2297. while (L'\0' != *pwszT)
  2298. {
  2299. int ichar = wcscspn(pwszT, L",\n");
  2300. if (ichar == 0) // neither of these, look for end-of-string
  2301. ichar = wcslen(pwszT);
  2302. pwszT += ichar;
  2303. switch (*pwszT)
  2304. {
  2305. case L'\n':
  2306. cPolicies++; // plus one per newline separator
  2307. pwszT++; // step over the newline
  2308. break;
  2309. case L',':
  2310. cObjId++; // plus one per comma separator
  2311. pwszT++; // step over the comma
  2312. break;
  2313. case L'\0':
  2314. default:
  2315. CSASSERT(L'\0' == *pwszT);
  2316. break;
  2317. }
  2318. }
  2319. cObjId += cPolicies; // plus one per signature
  2320. prgPolicies = (OBJECTIDLIST *) LocalAlloc(
  2321. LMEM_FIXED,
  2322. cPolicies * sizeof(prgPolicies[0]) +
  2323. cObjId * sizeof(WCHAR *) +
  2324. (wcslen(strPolicies) + 1) * sizeof(WCHAR));
  2325. if (NULL == prgPolicies)
  2326. {
  2327. hr = E_OUTOFMEMORY;
  2328. _JumpError(hr, error, "Policy:SysAllocString");
  2329. }
  2330. *pprgPolicies = prgPolicies;
  2331. *pcPolicies = cPolicies;
  2332. rgpwszObjId = (WCHAR **) &prgPolicies[cPolicies];
  2333. pwszOut = (WCHAR *) &rgpwszObjId[cObjId];
  2334. wcscpy(pwszOut, strPolicies);
  2335. fNew = TRUE;
  2336. while (L'\0' != *pwszOut)
  2337. {
  2338. if (fNew)
  2339. {
  2340. prgPolicies->cObjId = 0;
  2341. prgPolicies->rgpwszObjId = rgpwszObjId;
  2342. }
  2343. prgPolicies->cObjId++;
  2344. *rgpwszObjId = pwszOut;
  2345. rgpwszObjId++; // next array entry
  2346. fNew = FALSE;
  2347. int ichar = wcscspn(pwszOut , L",\n");
  2348. if (ichar == 0) // neither of these, look for end-of-string
  2349. ichar = wcslen(pwszOut);
  2350. pwszOut += ichar;
  2351. switch (*pwszOut)
  2352. {
  2353. case L'\n':
  2354. prgPolicies++;
  2355. fNew = TRUE;
  2356. // FALLTHROUGH
  2357. case L',':
  2358. *pwszOut++ = L'\0';
  2359. break;
  2360. case L'\0':
  2361. default:
  2362. CSASSERT(L'\0' == *pwszOut);
  2363. break;
  2364. }
  2365. }
  2366. hr = S_OK;
  2367. error:
  2368. return(hr);
  2369. }
  2370. HRESULT
  2371. CTemplatePolicy::_LoadSignaturePolicies(
  2372. IN ICertServerPolicy *pServer,
  2373. IN WCHAR const *pwszPropNameRequest,
  2374. OUT DWORD *pcSignaturePolicies,
  2375. OUT OBJECTIDLIST **pprgSignaturePolicies) // from the signing cert(s)
  2376. {
  2377. HRESULT hr;
  2378. BSTR strSignaturePolicies = NULL;
  2379. *pcSignaturePolicies = 0;
  2380. *pprgSignaturePolicies = NULL;
  2381. hr = polGetRequestStringProperty(
  2382. pServer,
  2383. pwszPropNameRequest,
  2384. &strSignaturePolicies);
  2385. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  2386. {
  2387. hr = CERTSRV_E_SIGNATURE_POLICY_REQUIRED;
  2388. }
  2389. _JumpIfErrorStr(
  2390. hr,
  2391. error,
  2392. "Policy:polGetRequestStringProperty",
  2393. pwszPropNameRequest);
  2394. hr = tpSplitPolicies(
  2395. strSignaturePolicies,
  2396. pcSignaturePolicies,
  2397. pprgSignaturePolicies);
  2398. _JumpIfError(hr, error, "Policy:tpSplitPolicies");
  2399. error:
  2400. if (NULL != strSignaturePolicies)
  2401. {
  2402. SysFreeString(strSignaturePolicies);
  2403. }
  2404. return(hr);
  2405. }
  2406. HRESULT
  2407. CTemplatePolicy::_EnforceReenrollment(
  2408. IN ICertServerPolicy *pServer,
  2409. IN CRequestInstance *pRequest)
  2410. {
  2411. HRESULT hr;
  2412. VARIANT var;
  2413. CERT_CONTEXT const *pOldCert = NULL;
  2414. CERT_EXTENSION const *pExt;
  2415. CERT_TEMPLATE_EXT *pTemplateExt = NULL;
  2416. WCHAR *pwszObjId = NULL;
  2417. CERT_ALT_NAME_INFO *pAltName = NULL;
  2418. CERT_NAME_VALUE *pName = NULL;
  2419. DWORD cb;
  2420. DWORD i;
  2421. VariantInit(&var);
  2422. if (NULL == m_pwszTemplateObjId)
  2423. {
  2424. hr = CERTSRV_E_UNSUPPORTED_CERT_TYPE;
  2425. _JumpError(hr, error, "Policy:No template ObjId");
  2426. }
  2427. hr = polGetProperty(
  2428. pServer,
  2429. TRUE, // fRequest
  2430. wszPROPREQUESTRAWOLDCERTIFICATE,
  2431. PROPTYPE_BINARY,
  2432. &var);
  2433. _JumpIfError(hr, error, "Policy:polGetProperty");
  2434. if (VT_BSTR != var.vt || NULL == var.bstrVal)
  2435. {
  2436. hr = CERTSRV_E_PROPERTY_EMPTY;
  2437. _JumpError(hr, error, "Policy:polGetProperty");
  2438. }
  2439. var.bstrVal;
  2440. pOldCert = CertCreateCertificateContext(
  2441. X509_ASN_ENCODING,
  2442. (BYTE *) var.bstrVal,
  2443. SysStringByteLen(var.bstrVal));
  2444. if (NULL == pOldCert)
  2445. {
  2446. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2447. _JumpError(hr, error, "CertCreateCertificateContext");
  2448. }
  2449. pExt = CertFindExtension(
  2450. szOID_CERTIFICATE_TEMPLATE,
  2451. pOldCert->pCertInfo->cExtension,
  2452. pOldCert->pCertInfo->rgExtension);
  2453. if (NULL == pExt)
  2454. {
  2455. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  2456. _JumpError(hr, error, "CertFindExtension(Template)");
  2457. }
  2458. if (!myDecodeObject(
  2459. X509_ASN_ENCODING,
  2460. X509_CERTIFICATE_TEMPLATE,
  2461. pExt->Value.pbData,
  2462. pExt->Value.cbData,
  2463. CERTLIB_USE_LOCALALLOC,
  2464. (VOID **) &pTemplateExt,
  2465. &cb))
  2466. {
  2467. hr = myHLastError();
  2468. _JumpError(hr, error, "Policy:myDecodeObject");
  2469. }
  2470. if (!myConvertSzToWsz(&pwszObjId, pTemplateExt->pszObjId, MAXDWORD))
  2471. {
  2472. hr = E_OUTOFMEMORY;
  2473. _JumpError(hr, error, "Policy:myConvertSzToWsz");
  2474. }
  2475. if (0 != lstrcmp(pwszObjId, m_pwszTemplateObjId))
  2476. {
  2477. hr = CERTSRV_E_UNSUPPORTED_CERT_TYPE;
  2478. _JumpError(hr, error, "Policy:different cert type");
  2479. }
  2480. if (NULL == pRequest->m_pwszUPN)
  2481. {
  2482. hr = E_POINTER; // We should never get this
  2483. _JumpError(hr, error, "Policy:NULL UPN");
  2484. }
  2485. pExt = CertFindExtension(
  2486. szOID_SUBJECT_ALT_NAME2,
  2487. pOldCert->pCertInfo->cExtension,
  2488. pOldCert->pCertInfo->rgExtension);
  2489. if (NULL == pExt)
  2490. {
  2491. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  2492. _JumpError(hr, error, "CertFindExtension(SubjectAltName)");
  2493. }
  2494. if (!myDecodeObject(
  2495. X509_ASN_ENCODING,
  2496. X509_ALTERNATE_NAME,
  2497. pExt->Value.pbData,
  2498. pExt->Value.cbData,
  2499. CERTLIB_USE_LOCALALLOC,
  2500. (VOID **) &pAltName,
  2501. &cb))
  2502. {
  2503. hr = myHLastError();
  2504. _JumpError(hr, error, "Policy:myDecodeObject");
  2505. }
  2506. for (i = 0; i < pAltName->cAltEntry; i++)
  2507. {
  2508. CERT_ALT_NAME_ENTRY *pAltEntry = &pAltName->rgAltEntry[i];
  2509. if (CERT_ALT_NAME_OTHER_NAME != pAltEntry->dwAltNameChoice)
  2510. {
  2511. continue;
  2512. }
  2513. if (0 != strcmp(
  2514. pAltEntry->pOtherName->pszObjId,
  2515. szOID_NT_PRINCIPAL_NAME))
  2516. {
  2517. continue;
  2518. }
  2519. if (!myDecodeObject(
  2520. X509_ASN_ENCODING,
  2521. X509_UNICODE_ANY_STRING,
  2522. pAltEntry->pOtherName->Value.pbData,
  2523. pAltEntry->pOtherName->Value.cbData,
  2524. CERTLIB_USE_LOCALALLOC,
  2525. (VOID **) &pName,
  2526. &cb))
  2527. {
  2528. hr = myHLastError();
  2529. _JumpError(hr, error, "Policy:myDecodeObject");
  2530. }
  2531. if (CERT_RDN_UTF8_STRING != pName->dwValueType ||
  2532. 0 != mylstrcmpiL(
  2533. pRequest->m_pwszUPN,
  2534. (WCHAR const *) pName->Value.pbData))
  2535. {
  2536. hr = CERTSRV_E_BAD_REQUESTSUBJECT;
  2537. _JumpError(hr, error, "UPN doesn't match renewal UPN");
  2538. }
  2539. }
  2540. if (NULL == pName)
  2541. {
  2542. hr = CERTSRV_E_BAD_REQUESTSUBJECT;
  2543. _JumpError(hr, error, "missing renewal UPN");
  2544. }
  2545. hr = S_OK;
  2546. error:
  2547. if (NULL != pName)
  2548. {
  2549. LocalFree(pName);
  2550. }
  2551. if (NULL != pAltName)
  2552. {
  2553. LocalFree(pAltName);
  2554. }
  2555. if (NULL != pwszObjId)
  2556. {
  2557. LocalFree(pwszObjId);
  2558. }
  2559. if (NULL != pTemplateExt)
  2560. {
  2561. LocalFree(pTemplateExt);
  2562. }
  2563. if (NULL != pOldCert)
  2564. {
  2565. CertFreeCertificateContext(pOldCert);
  2566. }
  2567. VariantClear(&var);
  2568. return(hr);
  2569. }
  2570. //+--------------------------------------------------------------------------
  2571. // CCertPolicyEnterprise::_EnforceSignaturePolicy
  2572. //
  2573. // Fetch required lists of Issuance and Application ObjIds from the template.
  2574. // Fetch signing certificates' lists of Issuance and Application ObjIds from
  2575. // the cert server.
  2576. //
  2577. // Reject signatures that don't include all of the required Application ObjIds.
  2578. // Reject signatures that don't include at least one of the required Issuance
  2579. // ObjIds.
  2580. //
  2581. // The count of accepted signatures must be equal to or greater than the
  2582. // template-specified required signature count.
  2583. //
  2584. // Returns S_OK on success.
  2585. //+--------------------------------------------------------------------------
  2586. HRESULT
  2587. CTemplatePolicy::_EnforceSignaturePolicy(
  2588. IN ICertServerPolicy *pServer,
  2589. IN CRequestInstance *pRequest,
  2590. IN BOOL fEnrollOnBehalfOf)
  2591. {
  2592. HRESULT hr;
  2593. DWORD cSignatureAccepted;
  2594. DWORD cSignatureRejected;
  2595. DWORD *prgdwRefCount = NULL;
  2596. DWORD i;
  2597. WCHAR const *awszStrings[3];
  2598. WCHAR wszCountAccepted[50];
  2599. WCHAR wszCountRequired[50];
  2600. WCHAR *pwszMissing = NULL;
  2601. OBJECTIDLIST *pPoliciesApplication;
  2602. DWORD cSignatureIssuance;
  2603. OBJECTIDLIST *prgSignatureIssuance = NULL;
  2604. DWORD cSignatureApplication;
  2605. OBJECTIDLIST *prgSignatureApplication = NULL;
  2606. static WCHAR *s_pwszObjIdEA = TEXT(szOID_ENROLLMENT_AGENT);
  2607. static OBJECTIDLIST s_PoliciesApplicationEA = { 1, &s_pwszObjIdEA };
  2608. pPoliciesApplication = &m_PoliciesApplication;
  2609. if (0 == m_tp.dwcSignatureRequired)
  2610. {
  2611. if (!fEnrollOnBehalfOf ||
  2612. CERTTYPE_SCHEMA_VERSION_2 <= m_tp.dwSchemaVersion)
  2613. {
  2614. hr = S_OK;
  2615. goto error;
  2616. }
  2617. // V1 template with fEnrollOnBehalfOf request.
  2618. // Enforce szOID_ENROLLMENT_AGENT
  2619. pPoliciesApplication = &s_PoliciesApplicationEA;
  2620. }
  2621. hr = _LoadSignaturePolicies(
  2622. pServer,
  2623. wszPROPSIGNERPOLICIES,
  2624. &cSignatureIssuance, // from the signing cert(s)
  2625. &prgSignatureIssuance);
  2626. _JumpIfErrorStr(
  2627. hr,
  2628. error,
  2629. "CTemplatePolicy:_LoadSignaturePolicies",
  2630. CERTTYPE_PROP_RA_POLICY);
  2631. hr = _LoadSignaturePolicies(
  2632. pServer,
  2633. wszPROPSIGNERAPPLICATIONPOLICIES,
  2634. &cSignatureApplication, // from the signing cert(s)
  2635. &prgSignatureApplication);
  2636. _JumpIfErrorStr(
  2637. hr,
  2638. error,
  2639. "CTemplatePolicy:_LoadSignaturePolicies",
  2640. CERTTYPE_PROP_RA_APPLICATION_POLICY);
  2641. if (0 == m_PoliciesIssuance.cObjId && 0 == pPoliciesApplication->cObjId)
  2642. {
  2643. hr = CERTSRV_E_TEMPLATE_POLICY_REQUIRED;
  2644. _JumpIfError(hr, error, "no template policies");
  2645. }
  2646. if (cSignatureIssuance != cSignatureApplication)
  2647. {
  2648. hr = NTE_BAD_SIGNATURE; // must be an internal server problem
  2649. _JumpError(hr, error, "Policy:bad request policies counts");
  2650. }
  2651. if (0 != m_PoliciesIssuance.cObjId)
  2652. {
  2653. prgdwRefCount = (DWORD *) LocalAlloc(
  2654. LMEM_FIXED | LMEM_ZEROINIT,
  2655. m_PoliciesIssuance.cObjId * sizeof(DWORD));
  2656. if (NULL == prgdwRefCount)
  2657. {
  2658. hr = E_OUTOFMEMORY;
  2659. _JumpError(hr, error, "Policy:LocalAlloc");
  2660. }
  2661. }
  2662. // Loop through each signature's Application and Issuance Policy OIDs
  2663. cSignatureAccepted = 0;
  2664. cSignatureRejected = 0;
  2665. for (i = 0; i < cSignatureIssuance; i++)
  2666. {
  2667. BOOL fReject = FALSE;
  2668. WCHAR **rgpwszObjId;
  2669. DWORD cObjId;
  2670. DWORD j;
  2671. DWORD idx;
  2672. // This signature must include ALL required Application Policy OIDs
  2673. // If no Application Policy OIDs are required, all signatures are OK.
  2674. rgpwszObjId = prgSignatureApplication[i].rgpwszObjId;
  2675. cObjId = prgSignatureApplication[i].cObjId;
  2676. for (j = 0; j < pPoliciesApplication->cObjId; j++)
  2677. {
  2678. idx = polFindObjIdInList(
  2679. pPoliciesApplication->rgpwszObjId[j],
  2680. cObjId,
  2681. rgpwszObjId);
  2682. if (MAXDWORD == idx)
  2683. {
  2684. fReject = TRUE;
  2685. _PrintErrorStr(
  2686. S_OK,
  2687. "Policy:missing Application Policy",
  2688. pPoliciesApplication->rgpwszObjId[j]);
  2689. }
  2690. }
  2691. if (!fReject)
  2692. {
  2693. DWORD cFound = 0;
  2694. // For each Issuance Policy OID in this signature that also exists
  2695. // in the required Issuance Policy OIDs, increment the ref count to
  2696. // show the OID was referenced by an accepted signature.
  2697. // Reject the signature if it doesn't reference any required OID.
  2698. rgpwszObjId = prgSignatureIssuance[i].rgpwszObjId;
  2699. cObjId = prgSignatureIssuance[i].cObjId;
  2700. for (j = 0; j < cObjId; j++)
  2701. {
  2702. // "*" means the signing cert is good for *all* policies.
  2703. if (0 == wcscmp(L"*", rgpwszObjId[j]))
  2704. {
  2705. for (idx = 0; idx < m_PoliciesIssuance.cObjId; idx++)
  2706. {
  2707. prgdwRefCount[idx]++;
  2708. cFound++;
  2709. }
  2710. }
  2711. else
  2712. {
  2713. idx = polFindObjIdInList(
  2714. rgpwszObjId[j],
  2715. m_PoliciesIssuance.cObjId,
  2716. m_PoliciesIssuance.rgpwszObjId);
  2717. if (MAXDWORD != idx)
  2718. {
  2719. prgdwRefCount[idx]++;
  2720. cFound++;
  2721. }
  2722. }
  2723. }
  2724. // If no Issuance Policy OIDs are required, all signatures are OK.
  2725. if (0 != m_PoliciesIssuance.cObjId && 0 == cFound)
  2726. {
  2727. fReject = TRUE;
  2728. }
  2729. }
  2730. if (fReject)
  2731. {
  2732. cSignatureRejected++;
  2733. }
  2734. else
  2735. {
  2736. cSignatureAccepted++;
  2737. }
  2738. DBGPRINT((
  2739. DBG_SS_CERTPOL,
  2740. "Sig[%u]: %ws\n",
  2741. i,
  2742. fReject? L"Rejected" : L"Accepted"));
  2743. }
  2744. awszStrings[0] = m_pwszTemplateName;
  2745. if (NULL == awszStrings[0])
  2746. {
  2747. awszStrings[0] = m_pwszTemplateObjId;
  2748. }
  2749. hr = S_OK;
  2750. if (cSignatureAccepted < m_tp.dwcSignatureRequired)
  2751. {
  2752. hr = CERTSRV_E_SIGNATURE_COUNT;
  2753. if (0 != cSignatureRejected)
  2754. {
  2755. hr = CERTSRV_E_SIGNATURE_REJECTED;
  2756. }
  2757. _PrintError(hr, "Policy:not enough signatures");
  2758. // The %1 Certificate Template requires %2 signatures,
  2759. // but only %3 were accepted.
  2760. wsprintf(wszCountRequired, L"%u", m_tp.dwcSignatureRequired);
  2761. awszStrings[1] = wszCountRequired;
  2762. wsprintf(wszCountAccepted, L"%u", cSignatureAccepted);
  2763. awszStrings[2] = wszCountAccepted;
  2764. pRequest->BuildErrorInfo(hr, MSG_SIGNATURE_COUNT, awszStrings);
  2765. }
  2766. DBGPRINT((
  2767. S_OK != hr? DBG_SS_CERTPOLI : DBG_SS_CERTPOL,
  2768. "Signatures: %u needed, %u accepted\n",
  2769. m_tp.dwcSignatureRequired,
  2770. cSignatureAccepted));
  2771. for (i = 0; i < m_PoliciesIssuance.cObjId; i++)
  2772. {
  2773. if (0 == prgdwRefCount[i])
  2774. {
  2775. hr = CERTSRV_E_ISSUANCE_POLICY_REQUIRED;
  2776. _PrintErrorStr(
  2777. hr,
  2778. "Policy:missing Issuance Policy",
  2779. m_PoliciesIssuance.rgpwszObjId[i]);
  2780. myAppendString(
  2781. m_PoliciesIssuance.rgpwszObjId[i],
  2782. L", ",
  2783. &pwszMissing);
  2784. }
  2785. }
  2786. if (NULL != pwszMissing)
  2787. {
  2788. // The %1 Certificate Template requires the following issuance
  2789. // policies that signing certificates did not include: %2.
  2790. awszStrings[1] = pwszMissing;
  2791. pRequest->BuildErrorInfo(
  2792. hr,
  2793. MSG_SIGNATURE_ISSUANCE_POLICY,
  2794. awszStrings);
  2795. }
  2796. _JumpIfError(hr, error, "Policy:missing Policy/Signature");
  2797. error:
  2798. if (NULL != pwszMissing)
  2799. {
  2800. LocalFree(pwszMissing);
  2801. }
  2802. if (NULL != prgSignatureIssuance)
  2803. {
  2804. LocalFree(prgSignatureIssuance);
  2805. }
  2806. if (NULL != prgSignatureApplication)
  2807. {
  2808. LocalFree(prgSignatureApplication);
  2809. }
  2810. if (NULL != prgdwRefCount)
  2811. {
  2812. LocalFree(prgdwRefCount);
  2813. }
  2814. return(hr);
  2815. }
  2816. HRESULT
  2817. CTemplatePolicy::GetFlags(
  2818. IN DWORD dwOption,
  2819. OUT DWORD *pdwFlags)
  2820. {
  2821. HRESULT hr;
  2822. switch (dwOption)
  2823. {
  2824. case CERTTYPE_ENROLLMENT_FLAG:
  2825. *pdwFlags = m_tp.dwEnrollmentFlags;
  2826. break;
  2827. case CERTTYPE_SUBJECT_NAME_FLAG:
  2828. *pdwFlags = m_tp.dwSubjectNameFlags;
  2829. break;
  2830. case CERTTYPE_PRIVATE_KEY_FLAG:
  2831. *pdwFlags = m_tp.dwPrivateKeyFlags;
  2832. break;
  2833. case CERTTYPE_GENERAL_FLAG:
  2834. *pdwFlags = m_tp.dwGeneralFlags;
  2835. break;
  2836. default:
  2837. hr = E_INVALIDARG;
  2838. _JumpError(hr, error, "Policy:bad dwOption");
  2839. }
  2840. hr = S_OK;
  2841. error:
  2842. return(hr);
  2843. }
  2844. HRESULT
  2845. CTemplatePolicy::GetCriticalExtensions(
  2846. OUT DWORD *pcCriticalExtensions,
  2847. OUT WCHAR const * const **papwszCriticalExtensions)
  2848. {
  2849. HRESULT hr;
  2850. *pcCriticalExtensions = m_CriticalExtensions.cObjId;
  2851. *papwszCriticalExtensions = m_CriticalExtensions.rgpwszObjId;
  2852. hr = S_OK;
  2853. return(hr);
  2854. }
  2855. HRESULT
  2856. CTemplatePolicy::GetV1TemplateClass(
  2857. OUT WCHAR const **ppwszV1TemplateClass)
  2858. {
  2859. WCHAR const *pwsz = NULL;
  2860. *ppwszV1TemplateClass = NULL;
  2861. if (CERTTYPE_SCHEMA_VERSION_2 > m_tp.dwSchemaVersion)
  2862. {
  2863. pwsz = m_pwszTemplateName;
  2864. }
  2865. else if (CT_FLAG_IS_CROSS_CA & m_tp.dwGeneralFlags)
  2866. {
  2867. pwsz = wszCERTTYPE_CROSS_CA;
  2868. }
  2869. *ppwszV1TemplateClass = pwsz;
  2870. return(S_OK);
  2871. }
  2872. // IsRequestedTemplate - determine if the request specifies this template
  2873. BOOL
  2874. CTemplatePolicy::IsRequestedTemplate(
  2875. OPTIONAL IN WCHAR const *pwszTemplateName,
  2876. OPTIONAL IN WCHAR const *pwszTemplateObjId)
  2877. {
  2878. HRESULT hr = CERTSRV_E_UNSUPPORTED_CERT_TYPE;
  2879. if (NULL != pwszTemplateName)
  2880. {
  2881. if ((NULL != m_pwszTemplateName &&
  2882. 0 == mylstrcmpiL(m_pwszTemplateName, pwszTemplateName)) ||
  2883. (NULL != m_pwszTemplateObjId &&
  2884. 0 == lstrcmp(m_pwszTemplateObjId, pwszTemplateName)))
  2885. {
  2886. hr = S_OK;
  2887. }
  2888. }
  2889. if (S_OK != hr && NULL != pwszTemplateObjId)
  2890. {
  2891. if ((NULL != m_pwszTemplateName &&
  2892. 0 == mylstrcmpiL(m_pwszTemplateName, pwszTemplateObjId)) ||
  2893. (NULL != m_pwszTemplateObjId &&
  2894. 0 == lstrcmp(m_pwszTemplateObjId, pwszTemplateObjId)))
  2895. {
  2896. hr = S_OK;
  2897. }
  2898. }
  2899. _JumpIfErrorStr2(
  2900. hr,
  2901. error,
  2902. "Policy:wrong CertType",
  2903. m_pwszTemplateName,
  2904. hr);
  2905. error:
  2906. return(S_OK == hr);
  2907. }