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.

1475 lines
50 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 2000
  6. //
  7. // File: cautil.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "wzrdpvk.h"
  11. #include "certca.h"
  12. #include "cautil.h"
  13. #include "CertRequesterContext.h"
  14. #include "CertDSManager.h"
  15. #include "CertRequester.h"
  16. //------------------------------------------------------------
  17. //
  18. // Utility memory deallocate functions.
  19. //
  20. //------------------------------------------------------------
  21. void CAFreeCertTypeExtensionsArray
  22. (
  23. IN LPVOID pCertExtensionsArray,
  24. int dwArrayLen
  25. )
  26. {
  27. for (int i=0; i<dwArrayLen; i++)
  28. {
  29. // Ignore return value.
  30. CAFreeCertTypeExtensions(NULL, ((PCERT_EXTENSIONS *)pCertExtensionsArray)[i]);
  31. }
  32. }
  33. void WizardFreePDWORDArray
  34. (IN LPVOID pdwArray,
  35. int dwArrayLen
  36. )
  37. {
  38. for (int i=0; i<dwArrayLen; i++)
  39. {
  40. WizardFree(((DWORD **)pdwArray)[i]);
  41. }
  42. }
  43. void WizardFreeLPWSTRArray
  44. (IN LPVOID pwszArray,
  45. int dwArrayLen
  46. )
  47. {
  48. for (int i=0; i<dwArrayLen; i++)
  49. {
  50. WizardFree(((LPWSTR *)pwszArray)[i]);
  51. }
  52. }
  53. typedef void (* PDEALLOCATOR)(void *, int);
  54. //--------------------------------------------------------------------
  55. //
  56. // CAUtilGetCADisplayName
  57. //
  58. //--------------------------------------------------------------------
  59. BOOL CAUtilGetCADisplayName(IN DWORD dwCAFindFlags,
  60. IN LPWSTR pwszCAName,
  61. OUT LPWSTR *ppwszCADisplayName)
  62. {
  63. BOOL fResult = FALSE;
  64. HCAINFO hCAInfo = NULL;
  65. HRESULT hr = E_FAIL;
  66. LPWSTR *ppwszDisplayNameProp = NULL;
  67. // Input validation:
  68. _JumpCondition(NULL == pwszCAName || NULL == ppwszCADisplayName, CLEANUP);
  69. // Init:
  70. *ppwszCADisplayName = NULL;
  71. hr = CAFindByName
  72. (pwszCAName,
  73. NULL,
  74. dwCAFindFlags,
  75. &hCAInfo);
  76. _JumpCondition(NULL == hCAInfo || FAILED(hr), CLEANUP);
  77. hr=CAGetCAProperty
  78. (hCAInfo,
  79. CA_PROP_DISPLAY_NAME,
  80. &ppwszDisplayNameProp);
  81. _JumpCondition(NULL == ppwszDisplayNameProp || FAILED(hr), CLEANUP);
  82. *ppwszCADisplayName = WizardAllocAndCopyWStr(ppwszDisplayNameProp[0]);
  83. _JumpCondition(NULL == *ppwszCADisplayName, CLEANUP);
  84. fResult = TRUE;
  85. CLEANUP:
  86. if(NULL != ppwszDisplayNameProp) { CAFreeCAProperty(hCAInfo, ppwszDisplayNameProp); }
  87. if(NULL != hCAInfo) { CACloseCA(hCAInfo); }
  88. return fResult;
  89. }
  90. //--------------------------------------------------------------------
  91. //
  92. // CheckSubjectRequirement
  93. //
  94. //--------------------------------------------------------------------
  95. BOOL CheckSubjectRequirement(HCERTTYPE hCurCertType,
  96. LPWSTR pwszInputCertDNName)
  97. {
  98. DWORD dwFlags;
  99. //check the subject requirement of the cert type
  100. if (S_OK != (CAGetCertTypeFlagsEx
  101. (hCurCertType,
  102. CERTTYPE_SUBJECT_NAME_FLAG,
  103. &dwFlags)))
  104. return FALSE;
  105. // Supported if
  106. // 1) Subject name requirement is not set
  107. // 2) Cert DN Name is supplied.
  108. return
  109. (0 == (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT & dwFlags)) ||
  110. (NULL != pwszInputCertDNName);
  111. }
  112. //--------------------------------------------------------------------
  113. //
  114. // Make sure the CSP supported by the cert type is consistent
  115. // with user's requirement and the local machine's CSP list
  116. //
  117. //--------------------------------------------------------------------
  118. BOOL CheckCertTypeCSP(IN CERT_WIZARD_INFO *pCertWizardInfo,
  119. IN LPWSTR *ppwszCSPList)
  120. {
  121. DWORD dwCSPIndex = 0;
  122. DWORD dwGlobalIndex = 0;
  123. LPWSTR pwszCSP = NULL;
  124. //for UI case, there is no CSP checking
  125. if(0 == (CRYPTUI_WIZ_NO_UI & (pCertWizardInfo->dwFlags)))
  126. return TRUE;
  127. //if the csp list is specfied, we are OK
  128. if(pCertWizardInfo->pwszProvider)
  129. return TRUE;
  130. if(NULL==ppwszCSPList)
  131. return FALSE;
  132. for(dwGlobalIndex=0; dwGlobalIndex < pCertWizardInfo->dwCSPCount; dwGlobalIndex++)
  133. {
  134. // Loop over the NULL-terminated CSP array...
  135. for (pwszCSP = ppwszCSPList[dwCSPIndex = 0]; NULL != pwszCSP; pwszCSP = ppwszCSPList[++dwCSPIndex])
  136. {
  137. if(0==_wcsicmp(pCertWizardInfo->rgwszProvider[dwGlobalIndex], pwszCSP))
  138. {
  139. // A match!
  140. return TRUE;
  141. }
  142. }
  143. }
  144. // Didn't find a CSP match.
  145. return FALSE;
  146. }
  147. //--------------------------------------------------------------------
  148. //
  149. // CheckCSPRequirement
  150. //
  151. //--------------------------------------------------------------------
  152. BOOL CheckCSPRequirement(IN HCERTTYPE hCurCertType,
  153. IN CERT_WIZARD_INFO *pCertWizardInfo)
  154. {
  155. BOOL fSupported = FALSE;
  156. HRESULT hr;
  157. LPWSTR *ppwszCSPList = NULL;
  158. if (NULL == hCurCertType)
  159. return FALSE;
  160. //get the CSP list from the cert type
  161. hr = CAGetCertTypeProperty
  162. (hCurCertType,
  163. CERTTYPE_PROP_CSP_LIST,
  164. &ppwszCSPList);
  165. if (S_OK == hr)
  166. {
  167. if (NULL != ppwszCSPList)
  168. {
  169. // The template specifies a CSP list. See if we can support it.
  170. fSupported = CheckCertTypeCSP(pCertWizardInfo, ppwszCSPList);
  171. }
  172. else
  173. {
  174. // Any CSP is good. Just make sure we have one:
  175. fSupported = 0 != pCertWizardInfo->dwCSPCount;
  176. }
  177. }
  178. else
  179. {
  180. // Can't get the CSP list. For UI case, CSP is optional
  181. if(0 == (CRYPTUI_WIZ_NO_UI & (pCertWizardInfo->dwFlags)))
  182. fSupported = TRUE;
  183. else
  184. //for UILess case, if a CSP is selected, it is also OK
  185. fSupported = NULL != pCertWizardInfo->pwszProvider;
  186. }
  187. //free the properties
  188. if(NULL != ppwszCSPList) { CAFreeCertTypeProperty(hCurCertType, ppwszCSPList); }
  189. // All done.
  190. return fSupported;
  191. }
  192. //--------------------------------------------------------------------
  193. //
  194. // Make sure that the CA supports at least one valid cert type
  195. //
  196. //--------------------------------------------------------------------
  197. BOOL IsValidCA(IN CERT_WIZARD_INFO *pCertWizardInfo,
  198. IN PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  199. IN HCAINFO hCAInfo)
  200. {
  201. BOOL fSupported = FALSE;
  202. CertRequester *pCertRequester = NULL;
  203. CertDSManager *pDSManager = NULL;
  204. HCERTTYPE hCurCertType = NULL;
  205. HCERTTYPE hPreCertType = NULL;
  206. HRESULT hr = E_FAIL;
  207. __try {
  208. _JumpCondition(NULL == hCAInfo || NULL == pCertWizardInfo || NULL == pCertWizardInfo->hRequester, InvalidArgError);
  209. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  210. pDSManager = pCertRequester->GetDSManager();
  211. _JumpCondition(NULL == pDSManager, InvalidArgError);
  212. if (S_OK != (hr = pDSManager->EnumCertTypesForCA
  213. (hCAInfo,
  214. (pCertWizardInfo->fMachine ? CT_ENUM_MACHINE_TYPES | CT_FIND_LOCAL_SYSTEM : CT_ENUM_USER_TYPES),
  215. &hCurCertType)))
  216. goto CLEANUP;
  217. while (NULL != hCurCertType)
  218. {
  219. //make sure the principal making this call has access to request
  220. //this cert type, even if he's requesting on behalf of another.
  221. fSupported = CAUtilValidCertTypeNoDS
  222. (hCurCertType,
  223. pCertRequestInfo->pwszCertDNName,
  224. pCertWizardInfo);
  225. // We've found a cert type which we can use for enrollment -- this CA is valid.
  226. _JumpCondition(TRUE == fSupported, CLEANUP);
  227. //enum for the next cert types
  228. hPreCertType = hCurCertType;
  229. hr = pDSManager->EnumNextCertType
  230. (hPreCertType,
  231. &hCurCertType);
  232. _JumpCondition(S_OK != hr, CLEANUP);
  233. //free the old cert type
  234. pDSManager->CloseCertType(hPreCertType);
  235. hPreCertType = NULL;
  236. }
  237. ErrorReturn:
  238. CLEANUP:
  239. if(NULL != hCurCertType) { CACloseCertType(hCurCertType); }
  240. if(NULL != hPreCertType) { CACloseCertType(hPreCertType); }
  241. goto CommonReturn;
  242. SET_ERROR(InvalidArgError, E_INVALIDARG);
  243. CommonReturn:;
  244. } __except(EXCEPTION_EXECUTE_HANDLER) {
  245. SetLastError(GetExceptionCode());
  246. fSupported = FALSE;
  247. }
  248. return fSupported;
  249. }
  250. BOOL CAUtilGetCertTypeNameNoDS(IN HCERTTYPE hCertType,
  251. OUT LPWSTR *ppwszCTName)
  252. {
  253. BOOL fResult = FALSE;
  254. HRESULT hr;
  255. LPWSTR *ppwszNameProp = NULL;
  256. _JumpCondition(NULL == hCertType || NULL == ppwszCTName, InvalidArgErr);
  257. // Init input params:
  258. *ppwszCTName = NULL;
  259. //get the machine readable form
  260. hr = CAGetCertTypePropertyEx
  261. (hCertType,
  262. CERTTYPE_PROP_DN,
  263. &ppwszNameProp);
  264. _JumpCondition(S_OK != hr, CertCliErr);
  265. _JumpConditionWithExpr(NULL == ppwszNameProp, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  266. _JumpConditionWithExpr(NULL == ppwszNameProp[0], CertCliErr, hr = E_FAIL);
  267. *ppwszCTName = WizardAllocAndCopyWStr(ppwszNameProp[0]);
  268. _JumpCondition(NULL==(*ppwszCTName), MemoryErr);
  269. fResult = TRUE;
  270. CommonReturn:
  271. if(NULL != ppwszNameProp) { CAFreeCAProperty(hCertType, ppwszNameProp); }
  272. return fResult;
  273. ErrorReturn:
  274. if (NULL != ppwszCTName && NULL != *ppwszCTName) { WizardFree(*ppwszCTName); }
  275. goto CommonReturn;
  276. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  277. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  278. SET_ERROR_VAR(CertCliErr, hr);
  279. }
  280. //--------------------------------------------------------------------
  281. //
  282. //From the API's cert type name, get the real machine readable name
  283. //
  284. //---------------------------------------------------------------------
  285. BOOL CAUtilGetCertTypeName(CERT_WIZARD_INFO *pCertWizardInfo,
  286. LPWSTR pwszAPIName,
  287. LPWSTR *ppwszCTName)
  288. {
  289. BOOL fResult = FALSE;
  290. CertDSManager *pDSManager = NULL;
  291. CertRequester *pCertRequester = NULL;
  292. DWORD dwException = 0;
  293. HCERTTYPE hCertType = NULL;
  294. HRESULT hr = S_OK;
  295. _JumpCondition(NULL == pCertWizardInfo || NULL == pCertWizardInfo->hRequester, InvalidArgError);
  296. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  297. pDSManager = pCertRequester->GetDSManager();
  298. _JumpCondition(NULL == pDSManager, InvalidArgError);
  299. __try {
  300. //get the handle based on name
  301. hr= pDSManager->FindCertTypeByName
  302. (pwszAPIName,
  303. NULL,
  304. (pCertWizardInfo->fMachine?CT_ENUM_MACHINE_TYPES|CT_FIND_LOCAL_SYSTEM:CT_ENUM_USER_TYPES),
  305. &hCertType);
  306. _JumpCondition(S_OK != hr, CertCliErr);
  307. _JumpConditionWithExpr(NULL == hCertType, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  308. fResult = CAUtilGetCertTypeNameNoDS(hCertType, ppwszCTName);
  309. _JumpConditionWithExpr(FALSE == fResult, CertCliErr, hr = GetLastError());
  310. } __except(EXCEPTION_EXECUTE_HANDLER) {
  311. dwException = GetExceptionCode();
  312. goto ExceptionErr;
  313. }
  314. fResult = TRUE;
  315. CommonReturn:
  316. //free the memory
  317. __try{
  318. if(NULL != hCertType) { pDSManager->CloseCertType(hCertType); }
  319. } __except(EXCEPTION_EXECUTE_HANDLER) {
  320. SetLastError(GetExceptionCode());
  321. }
  322. return fResult;
  323. ErrorReturn:
  324. fResult = FALSE;
  325. goto CommonReturn;
  326. SET_ERROR_VAR(CertCliErr, hr);
  327. SET_ERROR_VAR(ExceptionErr, dwException);
  328. SET_ERROR_VAR(InvalidArgError, E_INVALIDARG);
  329. }
  330. BOOL CAUtilValidCertTypeNoDS(HCERTTYPE hCertType,
  331. LPWSTR pwszCertDNName,
  332. CERT_WIZARD_INFO *pCertWizardInfo)
  333. {
  334. BOOL fResult = FALSE;
  335. CertRequester *pCertRequester = NULL;
  336. CertRequesterContext *pCertRequesterContext = NULL;
  337. _JumpCondition(hCertType == NULL || pCertWizardInfo == NULL || NULL == pCertWizardInfo->hRequester, InvalidArgError);
  338. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  339. pCertRequesterContext = pCertRequester->GetContext();
  340. _JumpCondition(NULL == pCertRequesterContext, InvalidArgError);
  341. //check the subject requirements
  342. _JumpCondition(FALSE == CheckSubjectRequirement(hCertType, pwszCertDNName), InvalidArgError);
  343. //check for the permission of the cert type
  344. _JumpCondition(FALSE == pCertRequesterContext->CheckAccessPermission(hCertType), AccessDeniedError);
  345. //check for the CSP permission of the cert type
  346. _JumpCondition(FALSE == CheckCSPRequirement(hCertType, pCertWizardInfo), InvalidArgError);
  347. fResult = TRUE;
  348. CommonReturn:
  349. return fResult;
  350. ErrorReturn:
  351. fResult = FALSE;
  352. goto CommonReturn;
  353. SET_ERROR_VAR(AccessDeniedError, E_ACCESSDENIED);
  354. SET_ERROR_VAR(InvalidArgError, E_INVALIDARG);
  355. }
  356. //--------------------------------------------------------------------
  357. //
  358. // Verify that the user has the correct permision to
  359. // ask for the requested certificatd types
  360. //
  361. //--------------------------------------------------------------------
  362. BOOL CAUtilValidCertType(IN PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  363. IN CERT_WIZARD_INFO *pCertWizardInfo)
  364. {
  365. BOOL fResult = FALSE;
  366. CertDSManager *pDSManager = NULL;
  367. CertRequester *pCertRequester = NULL;
  368. DWORD dwException = 0;
  369. DWORD dwCertTypeIndex = 0;
  370. HCERTTYPE hCertType = NULL;
  371. HRESULT hr = S_OK;
  372. PCCRYPTUI_WIZ_CERT_TYPE pCertType = NULL;
  373. _JumpCondition(NULL == pCertWizardInfo || NULL == pCertWizardInfo->hRequester, InvalidArgError);
  374. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  375. pDSManager = pCertRequester->GetDSManager();
  376. _JumpCondition(NULL == pDSManager, InvalidArgError);
  377. __try {
  378. //enum all the cert types. For each of them,
  379. //1. Has the correct permission
  380. //2. Has the correct subject requirement
  381. if(NULL != pCertRequestInfo)
  382. {
  383. if(CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE == pCertRequestInfo->dwCertChoice)
  384. {
  385. pCertType = pCertRequestInfo->pCertType;
  386. for(dwCertTypeIndex=0; dwCertTypeIndex <pCertType->cCertType; dwCertTypeIndex++)
  387. {
  388. DWORD dwFlags = CT_FIND_BY_OID;
  389. dwFlags |= pCertWizardInfo->fMachine ? CT_ENUM_MACHINE_TYPES | CT_FIND_LOCAL_SYSTEM : CT_ENUM_USER_TYPES;
  390. //get the handle based on OID
  391. hr= pDSManager->FindCertTypeByName
  392. (pCertType->rgwszCertType[dwCertTypeIndex],
  393. NULL,
  394. dwFlags,
  395. &hCertType);
  396. if (S_OK != hr)
  397. {
  398. // get the handle based on name:
  399. dwFlags &= ~CT_FIND_BY_OID;
  400. hr = pDSManager->FindCertTypeByName
  401. (pCertType->rgwszCertType[dwCertTypeIndex],
  402. NULL,
  403. dwFlags,
  404. &hCertType);
  405. }
  406. _JumpCondition(S_OK != hr, CertCliErr);
  407. _JumpConditionWithExpr(NULL == hCertType, CertCliErr, hr == S_OK ? hr = E_FAIL : hr);
  408. if (!CAUtilValidCertTypeNoDS(hCertType, pCertRequestInfo->pwszCertDNName, pCertWizardInfo))
  409. {
  410. hr = GetLastError();
  411. goto CertCliErr;
  412. }
  413. //free the cert type
  414. if(NULL != hCertType)
  415. {
  416. pDSManager->CloseCertType(hCertType);
  417. hCertType = NULL;
  418. }
  419. }
  420. }
  421. }
  422. } __except(EXCEPTION_EXECUTE_HANDLER) {
  423. dwException = GetExceptionCode();
  424. goto ExceptionErr;
  425. }
  426. fResult = TRUE;
  427. CommonReturn:
  428. return fResult;
  429. ErrorReturn:
  430. __try {
  431. if(NULL != hCertType) { pDSManager->CloseCertType(hCertType); }
  432. } __except(EXCEPTION_EXECUTE_HANDLER) {
  433. SetLastError(GetExceptionCode());
  434. }
  435. fResult = FALSE;
  436. goto CommonReturn;
  437. SET_ERROR_VAR(CertCliErr, hr);
  438. SET_ERROR_VAR(ExceptionErr, dwException)
  439. SET_ERROR_VAR(InvalidArgError, E_INVALIDARG);
  440. }
  441. //--------------------------------------------------------------------
  442. //
  443. //Retrieve a list of CAs that supports at least one valid cert types
  444. //
  445. //---------------------------------------------------------------------
  446. BOOL CAUtilRetrieveCAFromCertType(
  447. CERT_WIZARD_INFO *pCertWizardInfo,
  448. PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  449. BOOL /*fMultipleCA*/, //only need one CA
  450. DWORD dwNameFlag,
  451. DWORD *pdwCACount,
  452. LPWSTR **ppwszCALocation,
  453. LPWSTR **ppwszCAName)
  454. {
  455. BOOL fResult=FALSE;
  456. CertDSManager *pDSManager=NULL;
  457. CertRequesterContext *pCertRequesterContext = NULL;
  458. DWORD dwCACount=0;
  459. DWORD dwValidCACount=0;
  460. DWORD dwCAIndex=0;
  461. HRESULT hr=E_FAIL;
  462. HCAINFO hCurCAInfo=NULL;
  463. HCAINFO hPreCAInfo=NULL;
  464. LPWSTR *ppwszNameProp=NULL;
  465. LPWSTR *ppwszLocationProp=NULL;
  466. LPWSTR pwszDNName=NULL;
  467. PCCERT_CONTEXT pCertContext=NULL;
  468. DWORD dwSize=0;
  469. DWORD dwException=0;
  470. //input param checking
  471. if(!pdwCACount || !ppwszCALocation || !ppwszCAName) {
  472. SetLastError(ERROR_INVALID_PARAMETER);
  473. return FALSE;
  474. }
  475. //init
  476. *pdwCACount=0;
  477. *ppwszCALocation=NULL;
  478. *ppwszCAName=NULL;
  479. __try {
  480. //get a CA from the DS
  481. if(NULL != pCertWizardInfo)
  482. {
  483. CertRequester * pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  484. _JumpCondition(NULL == pCertRequester, InvalidArgErr);
  485. pCertRequesterContext = pCertRequester->GetContext();
  486. _JumpCondition(NULL == pCertRequesterContext, InvalidArgErr);
  487. pDSManager = pCertRequester->GetDSManager();
  488. _JumpCondition(NULL == pDSManager, InvalidArgErr);
  489. hr=pDSManager->EnumFirstCA(
  490. NULL,
  491. (pCertWizardInfo->fMachine?CA_FIND_LOCAL_SYSTEM:0),
  492. &hCurCAInfo);
  493. _JumpCondition(S_OK != hr, CAEnumCAErr);
  494. _JumpCondition(NULL == hCurCAInfo, CAEnumCAErrNotFound);
  495. }
  496. else
  497. {
  498. //this is for SelCA API where pCertWizardInfo is NULL
  499. hr = CAEnumFirstCA
  500. (NULL,
  501. (CRYPTUI_DLG_SELECT_CA_LOCAL_MACHINE_ENUMERATION & dwNameFlag) ? CA_FIND_LOCAL_SYSTEM:0,
  502. &hCurCAInfo);
  503. _JumpCondition(S_OK != hr, CAEnumCAErr);
  504. _JumpCondition(NULL == hCurCAInfo, CAEnumCAErrNotFound);
  505. if (S_OK != CertRequesterContext::MakeDefaultCertRequesterContext(&pCertRequesterContext))
  506. goto UnexpectedErr;
  507. }
  508. //get the CA count
  509. dwCACount = CACountCAs(hCurCAInfo);
  510. _JumpConditionWithExpr(0 == dwCACount, CertCliErr, hr = E_FAIL);
  511. //memory allocation and memset
  512. *ppwszCALocation=(LPWSTR *)WizardAlloc(sizeof(LPWSTR) * dwCACount);
  513. _JumpCondition(NULL == *ppwszCALocation, MemoryErr);
  514. memset(*ppwszCALocation, 0, sizeof(LPWSTR) * dwCACount);
  515. *ppwszCAName=(LPWSTR *)WizardAlloc(sizeof(LPWSTR) * dwCACount);
  516. _JumpCondition(NULL == *ppwszCAName, MemoryErr);
  517. memset(*ppwszCAName, 0, sizeof(LPWSTR) * dwCACount);
  518. dwValidCACount = 0;
  519. //enum all the CAs available on the DS
  520. for(dwCAIndex = 0; dwCAIndex < dwCACount; dwCAIndex++)
  521. {
  522. //make sure the CA supports all the cert types
  523. if(NULL != pCertRequestInfo)
  524. {
  525. // Skip this CA if it is not valid.
  526. _JumpCondition(FALSE == IsValidCA(pCertWizardInfo, pCertRequestInfo, hCurCAInfo), next);
  527. }
  528. // Skip this CA if the user does not have access rights to it.
  529. _JumpCondition(FALSE == pCertRequesterContext->CheckCAPermission(hCurCAInfo), next);
  530. //copy the CA name and location
  531. //get the CA's CN or DN based on dwNameFlag
  532. if(CRYPTUI_DLG_SELECT_CA_USE_DN & dwNameFlag)
  533. {
  534. //get the CA's certificate
  535. hr = CAGetCACertificate(hCurCAInfo, &pCertContext);
  536. _JumpCondition(S_OK != hr, CertCliErr);
  537. _JumpConditionWithExpr(NULL==pCertContext, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  538. //get the DN name
  539. dwSize = CertNameToStrW(pCertContext->dwCertEncodingType,
  540. &(pCertContext->pCertInfo->Subject),
  541. CERT_X500_NAME_STR,
  542. NULL,
  543. 0);
  544. _JumpCondition(0 == dwSize, TraceErr);
  545. pwszDNName=(LPWSTR)WizardAlloc(dwSize * sizeof(WCHAR));
  546. _JumpCondition(NULL==pwszDNName, MemoryErr);
  547. dwSize = CertNameToStrW(pCertContext->dwCertEncodingType,
  548. &(pCertContext->pCertInfo->Subject),
  549. CERT_X500_NAME_STR,
  550. pwszDNName,
  551. dwSize);
  552. _JumpCondition(0==dwSize, TraceErr);
  553. //copy the name
  554. (*ppwszCAName)[dwValidCACount]=WizardAllocAndCopyWStr(pwszDNName);
  555. _JumpCondition(NULL==(*ppwszCAName)[dwValidCACount], TraceErr);
  556. WizardFree(pwszDNName);
  557. pwszDNName = NULL;
  558. CertFreeCertificateContext(pCertContext);
  559. pCertContext = NULL;
  560. }
  561. else
  562. {
  563. hr = CAGetCAProperty(
  564. hCurCAInfo,
  565. CA_PROP_NAME,
  566. &ppwszNameProp);
  567. _JumpCondition(S_OK != hr, CertCliErr);
  568. _JumpConditionWithExpr(NULL == ppwszNameProp, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  569. //copy the name
  570. (*ppwszCAName)[dwValidCACount] = WizardAllocAndCopyWStr(ppwszNameProp[0]);
  571. _JumpCondition(NULL == (*ppwszCAName)[dwValidCACount], TraceErr);
  572. //free the property
  573. CAFreeCAProperty(hCurCAInfo, ppwszNameProp);
  574. ppwszNameProp = NULL;
  575. }
  576. //get the location
  577. hr = CAGetCAProperty
  578. (hCurCAInfo,
  579. CA_PROP_DNSNAME,
  580. &ppwszLocationProp);
  581. _JumpCondition(S_OK != hr, CertCliErr);
  582. _JumpConditionWithExpr(NULL == ppwszLocationProp, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  583. //copy the name
  584. (*ppwszCALocation)[dwValidCACount]=WizardAllocAndCopyWStr(ppwszLocationProp[0]);
  585. _JumpCondition(NULL == (*ppwszCALocation)[dwValidCACount], TraceErr);
  586. //free the property
  587. CAFreeCAProperty(hCurCAInfo, ppwszLocationProp);
  588. ppwszLocationProp = NULL;
  589. //increment the count
  590. dwValidCACount++;
  591. next:
  592. //enum for the CA
  593. hPreCAInfo = hCurCAInfo;
  594. hr = CAEnumNextCA
  595. (hPreCAInfo,
  596. &hCurCAInfo);
  597. //free the old CA Info
  598. CACloseCA(hPreCAInfo);
  599. hPreCAInfo=NULL;
  600. if((S_OK != hr) || (NULL==hCurCAInfo))
  601. break;
  602. }
  603. *pdwCACount = dwValidCACount;
  604. _JumpConditionWithExpr(0 == (*pdwCACount), CertCliErr, hr = E_FAIL);
  605. } __except(EXCEPTION_EXECUTE_HANDLER) {
  606. dwException = GetExceptionCode();
  607. goto ExceptionErr;
  608. }
  609. fResult = TRUE;
  610. CommonReturn:
  611. //free memory
  612. __try {
  613. if(NULL != ppwszNameProp) { CAFreeCAProperty(hCurCAInfo, ppwszNameProp); }
  614. if(NULL != ppwszLocationProp) { CAFreeCAProperty(hCurCAInfo, ppwszLocationProp); }
  615. if(NULL != hPreCAInfo) { CACloseCA(hPreCAInfo); }
  616. if(NULL != hCurCAInfo) { CACloseCA(hCurCAInfo); }
  617. } __except(EXCEPTION_EXECUTE_HANDLER) {
  618. SetLastError(GetExceptionCode());
  619. }
  620. if(NULL != pwszDNName) { WizardFree(pwszDNName); }
  621. if(NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
  622. return fResult;
  623. ErrorReturn:
  624. //free the memory in failure case
  625. if(NULL != ppwszCALocation && NULL != *ppwszCALocation)
  626. {
  627. for(dwCAIndex=0; dwCAIndex < dwCACount; dwCAIndex++)
  628. {
  629. if(NULL != (*ppwszCALocation)[dwCAIndex]) { WizardFree((*ppwszCALocation)[dwCAIndex]); }
  630. }
  631. WizardFree(*ppwszCALocation);
  632. *ppwszCALocation = NULL;
  633. }
  634. if(NULL != ppwszCAName && NULL != *ppwszCAName)
  635. {
  636. for(dwCAIndex=0; dwCAIndex < dwCACount; dwCAIndex++)
  637. {
  638. if(NULL != (*ppwszCAName)[dwCAIndex]) { WizardFree((*ppwszCAName)[dwCAIndex]); }
  639. }
  640. WizardFree(*ppwszCAName);
  641. *ppwszCAName = NULL;
  642. }
  643. fResult = FALSE;
  644. goto CommonReturn;
  645. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  646. SET_ERROR_VAR(CertCliErr, hr);
  647. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  648. TRACE_ERROR(TraceErr);
  649. SET_ERROR_VAR(CAEnumCAErr, hr);
  650. SET_ERROR(CAEnumCAErrNotFound, ERROR_DS_OBJ_NOT_FOUND);
  651. SET_ERROR_VAR(ExceptionErr, dwException)
  652. SET_ERROR(UnexpectedErr, E_UNEXPECTED);
  653. }
  654. //--------------------------------------------------------------------
  655. //
  656. //Based on the CA name and CA location, get a list of certificate type
  657. //and their extensions
  658. //
  659. // 1. Check the permission of the cert types
  660. // 2. Check the subject requirement of the cert types
  661. //---------------------------------------------------------------------
  662. BOOL CAUtilGetCertTypeNameAndExtensionsNoDS
  663. (
  664. CERT_WIZARD_INFO *pCertWizardInfo,
  665. LPWSTR pwszCertDNName,
  666. HCERTTYPE hCertType,
  667. LPWSTR *ppwszCertType,
  668. LPWSTR *ppwszDisplayCertType,
  669. PCERT_EXTENSIONS *pCertExtensions,
  670. DWORD *pdwKeySpec,
  671. DWORD *pdwMinKeySize,
  672. DWORD *pdwCSPCount,
  673. DWORD **ppdwCSPList,
  674. DWORD *pdwRASignature,
  675. DWORD *pdwEnrollmentFlags,
  676. DWORD *pdwSubjectNameFlags,
  677. DWORD *pdwPrivateKeyFlags,
  678. DWORD *pdwGeneralFlags)
  679. {
  680. BOOL fResult = FALSE;
  681. CertRequester *pCertRequester = NULL;
  682. CertRequesterContext *pCertRequesterContext = NULL;
  683. DWORD dwGlobalIndex = 0;
  684. DWORD dwLastError = ERROR_SUCCESS;
  685. DWORD dwCSPIndex = 0;
  686. DWORD dwFlags = 0;
  687. DWORD dwKeySpec = 0;
  688. DWORD dwEnrollmentFlags;
  689. DWORD dwSubjectNameFlags;
  690. DWORD dwPrivateKeyFlags;
  691. DWORD dwGeneralFlags;
  692. DWORD dwSchemaVersion;
  693. HRESULT hr = S_OK;
  694. LPWSTR pwszCSP = NULL;
  695. LPWSTR *ppwszCSP = NULL;
  696. LPWSTR *ppwszDisplayCertTypeName = NULL;
  697. LPWSTR *ppwszCertTypeName = NULL;
  698. // Input validation:
  699. if (NULL == pCertWizardInfo || NULL == pCertWizardInfo->hRequester ||
  700. NULL == ppwszCertType || NULL == ppwszDisplayCertType ||
  701. NULL == pCertExtensions || NULL == pdwKeySpec ||
  702. NULL == pdwMinKeySize || NULL == pdwCSPCount ||
  703. NULL == ppdwCSPList || NULL == pdwRASignature ||
  704. NULL == pdwEnrollmentFlags || NULL == pdwSubjectNameFlags ||
  705. NULL == pdwPrivateKeyFlags || NULL == pdwGeneralFlags)
  706. {
  707. SetLastError(ERROR_INVALID_PARAMETER);
  708. return FALSE;
  709. }
  710. // Init:
  711. *ppwszDisplayCertType = NULL;
  712. *ppwszCertType = NULL;
  713. *pCertExtensions = NULL;
  714. *pdwKeySpec = NULL;
  715. *pdwMinKeySize = NULL;
  716. *pdwCSPCount = NULL;
  717. *ppdwCSPList = NULL;
  718. *pdwRASignature = NULL;
  719. *pdwEnrollmentFlags = NULL;
  720. *pdwSubjectNameFlags = NULL;
  721. *pdwPrivateKeyFlags = NULL;
  722. *pdwGeneralFlags = NULL;
  723. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  724. pCertRequesterContext = pCertRequester->GetContext();
  725. _JumpCondition(NULL == pCertRequesterContext, InvalidArgError);
  726. // check the subject requirement of the cert type
  727. _JumpCondition(!CheckSubjectRequirement(hCertType,pwszCertDNName), CommonReturn);
  728. //check for the key specification of the cert type
  729. //we do not care about the return value. Since it will be set to 0
  730. //if the function failed.
  731. CAGetCertTypeKeySpec(hCertType, &dwKeySpec);
  732. //check for the CSP requirement of the cert type
  733. if((S_OK ==(hr=CAGetCertTypeProperty(hCertType,
  734. CERTTYPE_PROP_CSP_LIST,
  735. &ppwszCSP)))&&
  736. (NULL!=ppwszCSP)
  737. )
  738. {
  739. _JumpCondition(!CheckCertTypeCSP(pCertWizardInfo, ppwszCSP), CommonReturn);
  740. }
  741. //check for the permission of the cert type
  742. _JumpCondition(FALSE == pCertRequesterContext->CheckAccessPermission(hCertType), CommonReturn);
  743. //now, we have found a valid cert type.
  744. //copy Display name, extension, key spec, dwCertTypeFlag,
  745. //the CSP list
  746. //
  747. // First, get all applicable cert type flags:
  748. //
  749. // Get enrollment flags:
  750. if (S_OK != (hr=CAGetCertTypeFlagsEx
  751. (hCertType,
  752. CERTTYPE_ENROLLMENT_FLAG,
  753. &dwEnrollmentFlags)))
  754. goto CertCliErr;
  755. // Get subject name flags:
  756. if (S_OK != (hr=CAGetCertTypeFlagsEx
  757. (hCertType,
  758. CERTTYPE_SUBJECT_NAME_FLAG,
  759. &dwSubjectNameFlags)))
  760. goto CertCliErr;
  761. // Get private key flags.
  762. if(S_OK != (hr = CAGetCertTypeFlagsEx
  763. (hCertType,
  764. CERTTYPE_PRIVATE_KEY_FLAG,
  765. &dwPrivateKeyFlags)))
  766. goto CertCliErr;
  767. // Get general flags:
  768. if (S_OK != (hr=CAGetCertTypeFlagsEx
  769. (hCertType,
  770. CERTTYPE_GENERAL_FLAG,
  771. &dwGeneralFlags)))
  772. goto CertCliErr;
  773. // Filter out CT where subject name or subject alt name must be supplied.
  774. if (dwSubjectNameFlags &
  775. (CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT |
  776. CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME
  777. ))
  778. goto BadTemplateError;
  779. *pdwEnrollmentFlags = dwEnrollmentFlags;
  780. *pdwSubjectNameFlags = dwSubjectNameFlags;
  781. *pdwPrivateKeyFlags = dwPrivateKeyFlags;
  782. *pdwGeneralFlags = dwGeneralFlags;
  783. //get the display name of the cert type
  784. hr = CAGetCertTypeProperty
  785. (hCertType,
  786. CERTTYPE_PROP_FRIENDLY_NAME,
  787. &ppwszDisplayCertTypeName);
  788. _JumpCondition(S_OK != hr, CertCliErr);
  789. _JumpConditionWithExpr(NULL == ppwszDisplayCertTypeName, CertCliErr, hr = E_FAIL);
  790. //copy the name
  791. *ppwszDisplayCertType = WizardAllocAndCopyWStr(ppwszDisplayCertTypeName[0]);
  792. _JumpCondition(NULL == *ppwszDisplayCertType, MemoryError);
  793. //get the machine readable name of the cert type
  794. hr=CAGetCertTypeProperty
  795. (hCertType,
  796. CERTTYPE_PROP_DN,
  797. &ppwszCertTypeName);
  798. _JumpCondition(S_OK != hr, CertCliErr);
  799. _JumpConditionWithExpr(NULL == ppwszCertTypeName, CertCliErr, hr = E_FAIL);
  800. //copy the name
  801. *ppwszCertType = WizardAllocAndCopyWStr(ppwszCertTypeName[0]);
  802. _JumpCondition(NULL == *ppwszCertType, TraceError);
  803. //copy the dwKeySpec
  804. *pdwKeySpec = dwKeySpec;
  805. //
  806. // Assign V2 Properties.
  807. // If the current cert type is a V1 cert type, use default values.
  808. // Otherwise, get the properties from the CA.
  809. //
  810. if (S_OK != (hr=CAGetCertTypePropertyEx
  811. (hCertType,
  812. CERTTYPE_PROP_SCHEMA_VERSION,
  813. &dwSchemaVersion)))
  814. goto CertCliErr;
  815. if (dwSchemaVersion == CERTTYPE_SCHEMA_VERSION_1)
  816. {
  817. // NULL out the left half-word. This indicates that the min
  818. // key size is not specified, and should be defaulted during
  819. // enrollment.
  820. *pdwMinKeySize = 0;
  821. // Set requird number of required RA signatures to 0 (default).
  822. *pdwRASignature = 0;
  823. }
  824. else if (dwSchemaVersion == CERTTYPE_SCHEMA_VERSION_2)
  825. {
  826. // Get the minimum key size from the CA
  827. if (S_OK != (hr=CAGetCertTypePropertyEx
  828. (hCertType,
  829. CERTTYPE_PROP_MIN_KEY_SIZE,
  830. &dwFlags)))
  831. goto CertCliErr;
  832. // Copy the minimum key size. The minimum key size is stored in the
  833. // top half-word of the type flags.
  834. *pdwMinKeySize |= dwFlags;
  835. // Get the number of required RA signatures from the CA
  836. if (S_OK != (hr=CAGetCertTypePropertyEx
  837. (hCertType,
  838. CERTTYPE_PROP_RA_SIGNATURE,
  839. pdwRASignature)))
  840. goto CertCliErr;
  841. }
  842. // Filter out CTs which require RA signatures.
  843. if (*pdwRASignature > 0)
  844. {
  845. if (0 != (CRYPTUI_WIZ_NO_UI & pCertWizardInfo->dwFlags))
  846. {
  847. // In the no-UI case, we assume that the caller knows what they
  848. // are doing.
  849. }
  850. else
  851. {
  852. if ((0 != (CRYPTUI_WIZ_CERT_RENEW & pCertWizardInfo->dwPurpose)) &&
  853. (0 != (CT_FLAG_PREVIOUS_APPROVAL_VALIDATE_REENROLLMENT & dwEnrollmentFlags)))
  854. {
  855. // Special case: we're doing a renew, and the previous approval for this cert
  856. // validates future re-enrollments. We don't _really_ need RA sigs.
  857. }
  858. else
  859. {
  860. // This CT requires RA signatures. Filter it out:
  861. goto BadTemplateError;
  862. }
  863. }
  864. }
  865. // copy the necessary extensions
  866. if (S_OK != (hr = CAGetCertTypeExtensionsEx
  867. (hCertType,
  868. CT_EXTENSION_TEMPLATE,
  869. NULL,
  870. &(*pCertExtensions))))
  871. goto CertCliErr;
  872. //set up the CSP list. It will be a DWORD array index to the
  873. //global CSP list
  874. *ppdwCSPList = (DWORD *)WizardAlloc(sizeof(DWORD) * (pCertWizardInfo->dwCSPCount));
  875. _JumpCondition(NULL == (*ppdwCSPList), MemoryError);
  876. memset((*ppdwCSPList), 0 ,sizeof(DWORD) * (pCertWizardInfo->dwCSPCount));
  877. if (NULL == ppwszCSP || NULL == ppwszCSP[0])
  878. {
  879. // no specified CSPs on the templates means that all are allowed:
  880. for(dwGlobalIndex=0; dwGlobalIndex < pCertWizardInfo->dwCSPCount; dwGlobalIndex++)
  881. {
  882. (*ppdwCSPList)[(*pdwCSPCount)]=dwGlobalIndex;
  883. (*pdwCSPCount)++;
  884. }
  885. }
  886. else
  887. {
  888. //loop through the CSP list and build the index array
  889. //we should have at least on item in the index array since
  890. //we have checked the certtype before
  891. for (pwszCSP = ppwszCSP[dwCSPIndex = 0]; NULL != pwszCSP; pwszCSP = ppwszCSP[++dwCSPIndex])
  892. {
  893. for(dwGlobalIndex=0; dwGlobalIndex < pCertWizardInfo->dwCSPCount; dwGlobalIndex++)
  894. {
  895. if(0==_wcsicmp(pCertWizardInfo->rgwszProvider[dwGlobalIndex], pwszCSP))
  896. {
  897. (*ppdwCSPList)[(*pdwCSPCount)]=dwGlobalIndex;
  898. (*pdwCSPCount)++;
  899. }
  900. }
  901. }
  902. }
  903. fResult = TRUE;
  904. CommonReturn:
  905. SetLastError(dwLastError);
  906. if (NULL != ppwszCSP) { CAFreeCertTypeProperty(hCertType, ppwszCSP); }
  907. if (NULL != ppwszDisplayCertTypeName) { CAFreeCertTypeProperty(hCertType, ppwszDisplayCertTypeName); }
  908. if (NULL != ppwszCertTypeName) { CAFreeCertTypeProperty(hCertType, ppwszCertTypeName); }
  909. return fResult;
  910. ErrorReturn:
  911. if (NULL != ppwszDisplayCertType && NULL != *ppwszDisplayCertType) {
  912. WizardFree(*ppwszDisplayCertType);
  913. *ppwszDisplayCertType = NULL;
  914. }
  915. if (NULL != ppwszCertType && NULL != *ppwszCertType) {
  916. WizardFree(*ppwszCertType);
  917. *ppwszCertType = NULL;
  918. }
  919. if (NULL != ppdwCSPList && NULL != *ppdwCSPList) {
  920. WizardFree(*ppdwCSPList);
  921. *ppdwCSPList = NULL;
  922. }
  923. dwLastError = hr;
  924. goto CommonReturn;
  925. SET_HRESULT(BadTemplateError, E_INVALIDARG); // approximate error
  926. SET_HRESULT(InvalidArgError, E_INVALIDARG);
  927. SET_HRESULT(MemoryError, E_OUTOFMEMORY);
  928. TRACE_ERROR(CertCliErr);
  929. TRACE_ERROR(TraceError);
  930. }
  931. BOOL CAUtilGetCertTypeNameAndExtensions(
  932. CERT_WIZARD_INFO *pCertWizardInfo,
  933. PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  934. LPWSTR pwszCALocation,
  935. LPWSTR pwszCAName,
  936. DWORD *pdwCertType,
  937. LPWSTR **ppwszCertType,
  938. LPWSTR **ppwszDisplayCertType,
  939. PCERT_EXTENSIONS **ppCertExtensions,
  940. DWORD **ppdwKeySpec,
  941. DWORD **ppdwMinKeySize,
  942. DWORD **ppdwCSPCount,
  943. DWORD ***ppdwCSPList,
  944. DWORD **ppdwRASignature,
  945. DWORD **ppdwEnrollmentFlags,
  946. DWORD **ppdwSubjectNameFlags,
  947. DWORD **ppdwPrivateKeyFlags,
  948. DWORD **ppdwGeneralFlags)
  949. {
  950. BOOL fResult = FALSE;
  951. CertDSManager *pDSManager = NULL;
  952. CertRequester *pCertRequester = NULL;
  953. DWORD dwCertTypeCount = 0;
  954. DWORD dwException = 0;
  955. DWORD dwIndex = 0;
  956. DWORD dwValidCertType = 0;
  957. HCAINFO hCAInfo = NULL;
  958. HCERTTYPE hCurCertType = NULL;
  959. HCERTTYPE hPreCertType = NULL;
  960. HRESULT hr = S_OK;
  961. LPWSTR *ppwszCertTypeName = NULL;
  962. LPWSTR *ppwszDisplayCertTypeName = NULL;
  963. //
  964. // Construct tables to hold arrays we'll be manipulating.
  965. // These tables are used to allocate the arrays, deallocate the arrays, and dealloate
  966. // the array elements (if necessary).
  967. //
  968. typedef struct _CAUTIL_CERTTYPE_ELEM_ARRAY {
  969. LPVOID *lpvArray;
  970. DWORD dwElemSize;
  971. PDEALLOCATOR pElemDeallocator;
  972. } CAUTIL_CERTTYPE_ELEM_ARRAY;
  973. CAUTIL_CERTTYPE_ELEM_ARRAY certTypeElemArrays[] = {
  974. { (LPVOID *)ppwszDisplayCertType, sizeof (LPWSTR), WizardFreeLPWSTRArray },
  975. { (LPVOID *)ppwszCertType, sizeof (LPWSTR), WizardFreeLPWSTRArray },
  976. { (LPVOID *)ppCertExtensions, sizeof (PCERT_EXTENSIONS), CAFreeCertTypeExtensionsArray },
  977. { (LPVOID *)ppdwKeySpec, sizeof (DWORD), NULL },
  978. { (LPVOID *)ppdwMinKeySize, sizeof (DWORD), NULL },
  979. { (LPVOID *)ppdwCSPCount, sizeof (DWORD), NULL },
  980. { (LPVOID *)ppdwCSPList, sizeof (DWORD *), WizardFreePDWORDArray },
  981. { (LPVOID *)ppdwRASignature, sizeof (DWORD), NULL },
  982. { (LPVOID *)ppdwEnrollmentFlags, sizeof (DWORD), NULL },
  983. { (LPVOID *)ppdwSubjectNameFlags, sizeof (DWORD), NULL },
  984. { (LPVOID *)ppdwPrivateKeyFlags, sizeof (DWORD), NULL },
  985. { (LPVOID *)ppdwGeneralFlags, sizeof (DWORD), NULL }
  986. };
  987. DWORD const dwNumCTElemArrays = sizeof(certTypeElemArrays) / sizeof(certTypeElemArrays[0]);
  988. if (NULL == pCertWizardInfo || NULL == pCertRequestInfo ||
  989. NULL == pwszCALocation || NULL == pwszCAName ||
  990. NULL == pdwCertType)
  991. {
  992. SetLastError(ERROR_INVALID_PARAMETER);
  993. return FALSE;
  994. }
  995. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  996. if (NULL == pCertRequester)
  997. {
  998. SetLastError(ERROR_INVALID_PARAMETER);
  999. return FALSE;
  1000. }
  1001. pDSManager = pCertRequester->GetDSManager();
  1002. if (NULL == pDSManager)
  1003. {
  1004. SetLastError(ERROR_INVALID_PARAMETER);
  1005. return FALSE;
  1006. }
  1007. *pdwCertType = 0;
  1008. // Check and initialize the input parameters
  1009. for (dwIndex = 0; dwIndex < dwNumCTElemArrays; dwIndex++)
  1010. {
  1011. if (NULL == certTypeElemArrays[dwIndex].lpvArray)
  1012. {
  1013. SetLastError(ERROR_INVALID_PARAMETER);
  1014. return FALSE;
  1015. }
  1016. *(certTypeElemArrays[dwIndex].lpvArray) = NULL;
  1017. }
  1018. __try {
  1019. //get the CA Info handler
  1020. hr= pDSManager->FindCAByName
  1021. (pwszCAName,
  1022. NULL,
  1023. (pCertWizardInfo->fMachine?CA_FIND_LOCAL_SYSTEM:0),
  1024. &hCAInfo);
  1025. _JumpCondition(S_OK != hr, CertCliErr);
  1026. _JumpConditionWithExpr(NULL==hCAInfo, CertCliErr, hr = E_FAIL);
  1027. hr=pDSManager->EnumCertTypesForCA
  1028. (hCAInfo,
  1029. (pCertWizardInfo->fMachine?CT_ENUM_MACHINE_TYPES | CT_FIND_LOCAL_SYSTEM:CT_ENUM_USER_TYPES),
  1030. &hCurCertType);
  1031. //the CA has to support some cert types
  1032. _JumpCondition(S_OK != hr, CertCliErr);
  1033. _JumpConditionWithExpr(NULL == hCurCertType, CertCliErr, hr = E_FAIL);
  1034. // Get the count of the cert types supported by this CA.
  1035. // We should have at least 1 cert type.
  1036. dwCertTypeCount = CACountCertTypes(hCurCertType);
  1037. _JumpConditionWithExpr(0 == dwCertTypeCount, CertCliErr, hr = E_FAIL);
  1038. // Allocate memory for all arrays we'll be manipulating.
  1039. for (dwIndex = 0; dwIndex < dwNumCTElemArrays; dwIndex++)
  1040. {
  1041. CAUTIL_CERTTYPE_ELEM_ARRAY ctea = certTypeElemArrays[dwIndex];
  1042. *(ctea.lpvArray) = NULL;
  1043. *(ctea.lpvArray) = WizardAlloc(ctea.dwElemSize * dwCertTypeCount);
  1044. _JumpCondition(NULL == *(ctea.lpvArray), MemoryErr);
  1045. memset(*(ctea.lpvArray), 0, ctea.dwElemSize * dwCertTypeCount);
  1046. }
  1047. dwValidCertType=0;
  1048. for(dwIndex=0; dwIndex < dwCertTypeCount; dwIndex++)
  1049. {
  1050. if (!CAUtilGetCertTypeNameAndExtensionsNoDS
  1051. (pCertWizardInfo,
  1052. pCertRequestInfo->pwszCertDNName,
  1053. hCurCertType,
  1054. &((*ppwszCertType) [dwValidCertType]),
  1055. &((*ppwszDisplayCertType) [dwValidCertType]),
  1056. &((*ppCertExtensions) [dwValidCertType]),
  1057. &((*ppdwKeySpec) [dwValidCertType]),
  1058. &((*ppdwMinKeySize) [dwValidCertType]),
  1059. &((*ppdwCSPCount) [dwValidCertType]),
  1060. &((*ppdwCSPList) [dwValidCertType]),
  1061. &((*ppdwRASignature) [dwValidCertType]),
  1062. &((*ppdwEnrollmentFlags) [dwValidCertType]),
  1063. &((*ppdwSubjectNameFlags) [dwValidCertType]),
  1064. &((*ppdwPrivateKeyFlags) [dwValidCertType]),
  1065. &((*ppdwGeneralFlags) [dwValidCertType])))
  1066. {
  1067. // No luck with this template. Try the next one.
  1068. goto next;
  1069. }
  1070. dwValidCertType++;
  1071. next:
  1072. //enum for the next cert types
  1073. hPreCertType=hCurCertType;
  1074. hr = pDSManager->EnumNextCertType(hPreCertType, &hCurCertType);
  1075. //free the old cert type
  1076. pDSManager->CloseCertType(hPreCertType);
  1077. hPreCertType=NULL;
  1078. if((S_OK != hr) || (NULL==hCurCertType))
  1079. break;
  1080. }
  1081. //copy the cert type count
  1082. *pdwCertType=dwValidCertType;
  1083. //have to have some valid cert types
  1084. _JumpConditionWithExpr(0 == (*pdwCertType), CertCliErr, hr = E_FAIL);
  1085. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1086. dwException = GetExceptionCode();
  1087. goto ExceptionErr;
  1088. }
  1089. fResult=TRUE;
  1090. CommonReturn:
  1091. //free memory
  1092. __try {
  1093. if (NULL != ppwszDisplayCertTypeName) { CAFreeCertTypeProperty(hCurCertType, ppwszDisplayCertTypeName); }
  1094. if (NULL != ppwszCertTypeName) { CAFreeCertTypeProperty(hCurCertType, ppwszCertTypeName); }
  1095. if (NULL != hPreCertType) { pDSManager->CloseCertType(hPreCertType); }
  1096. if (NULL != hCurCertType) { pDSManager->CloseCertType(hCurCertType); }
  1097. if (NULL != hCAInfo) { pDSManager->CloseCA(hCAInfo); }
  1098. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1099. SetLastError(GetExceptionCode());
  1100. }
  1101. return fResult;
  1102. ErrorReturn:
  1103. //free the memory in failure case
  1104. for (dwIndex = 0; dwIndex < dwNumCTElemArrays; dwIndex++)
  1105. {
  1106. CAUTIL_CERTTYPE_ELEM_ARRAY ctea = certTypeElemArrays[dwIndex];
  1107. if (NULL != ctea.lpvArray && NULL != *(ctea.lpvArray))
  1108. {
  1109. if (NULL != ctea.pElemDeallocator)
  1110. {
  1111. (ctea.pElemDeallocator)(*(ctea.lpvArray), dwCertTypeCount);
  1112. }
  1113. WizardFree(*(ctea.lpvArray));
  1114. *(ctea.lpvArray) = NULL;
  1115. }
  1116. }
  1117. fResult = FALSE;
  1118. goto CommonReturn;
  1119. SET_ERROR_VAR(CertCliErr, hr);
  1120. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1121. SET_ERROR_VAR(ExceptionErr, dwException)
  1122. }
  1123. //--------------------------------------------------------------------
  1124. //
  1125. //Retrieve the CA information based on a certificate
  1126. //
  1127. //---------------------------------------------------------------------
  1128. BOOL CAUtilRetrieveCAFromCert(IN CERT_WIZARD_INFO *pCertWizardInfo,
  1129. IN PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  1130. OUT LPWSTR *pwszCALocation,
  1131. OUT LPWSTR *pwszCAName)
  1132. {
  1133. BOOL fResult = FALSE;
  1134. CertDSManager *pDSManager = NULL;
  1135. CertRequester *pCertRequester = NULL;
  1136. DWORD dwException = 0;
  1137. HCAINFO hCAInfo = NULL;
  1138. HRESULT hr = S_OK;
  1139. LPWSTR *ppwszCAName = NULL;
  1140. LPWSTR *ppwszCALocation = NULL;
  1141. PCERT_INFO pCertInfo = NULL;
  1142. _JumpCondition(NULL==pwszCALocation || NULL==pwszCAName || NULL==pCertRequestInfo, InvalidArgErr);
  1143. //init
  1144. *pwszCALocation = NULL;
  1145. *pwszCAName = NULL;
  1146. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  1147. _JumpCondition(NULL == pCertRequester, InvalidArgErr);
  1148. pDSManager = pCertRequester->GetDSManager();
  1149. _JumpCondition(NULL == pDSManager, InvalidArgErr);
  1150. //get the DN name from the certificate
  1151. _JumpCondition(NULL == pCertRequestInfo->pRenewCertContext, InvalidArgErr);
  1152. pCertInfo = pCertRequestInfo->pRenewCertContext->pCertInfo;
  1153. _JumpCondition(NULL==pCertInfo, InvalidArgErr);
  1154. __try {
  1155. //get the certificate CA based on the DN
  1156. hr=CAFindByIssuerDN
  1157. (&(pCertInfo->Issuer),
  1158. NULL,
  1159. (pCertWizardInfo->fMachine?CA_FIND_LOCAL_SYSTEM:0),
  1160. &hCAInfo);
  1161. //now that we can not get a certificate based on the DN, we
  1162. //just get any CA on the DN
  1163. if(hr!= S_OK || hCAInfo==NULL)
  1164. {
  1165. hr=pDSManager->EnumFirstCA(NULL,
  1166. (pCertWizardInfo->fMachine?CA_FIND_LOCAL_SYSTEM:0),
  1167. &hCAInfo);
  1168. }
  1169. _JumpCondition(S_OK != hr || hCAInfo == NULL, CertCliErr);
  1170. //get the CA's name and machine name
  1171. hr = CAGetCAProperty
  1172. (hCAInfo,
  1173. CA_PROP_NAME,
  1174. &ppwszCAName);
  1175. _JumpCondition(S_OK != hr, CertCliErr);
  1176. _JumpConditionWithExpr(NULL == ppwszCAName, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  1177. hr=CAGetCAProperty
  1178. (hCAInfo,
  1179. CA_PROP_DNSNAME,
  1180. &ppwszCALocation);
  1181. _JumpCondition(S_OK != hr, CertCliErr);
  1182. _JumpConditionWithExpr(NULL == ppwszCALocation, CertCliErr, S_OK == hr ? hr = E_FAIL : hr);
  1183. //copy the result to the output parameter
  1184. *pwszCALocation = WizardAllocAndCopyWStr(ppwszCALocation[0]);
  1185. _JumpCondition(NULL == *pwszCALocation, TraceErr);
  1186. *pwszCAName = WizardAllocAndCopyWStr(ppwszCAName[0]);
  1187. _JumpCondition(NULL == *pwszCAName, TraceErr);
  1188. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1189. dwException = GetExceptionCode();
  1190. goto ExceptionErr;
  1191. }
  1192. fResult=TRUE;
  1193. CommonReturn:
  1194. //free memory
  1195. __try {
  1196. if (NULL != ppwszCAName) { CAFreeCAProperty(hCAInfo, ppwszCAName); }
  1197. if (NULL != ppwszCALocation) { CAFreeCAProperty(hCAInfo, ppwszCALocation); }
  1198. if (NULL != hCAInfo) { CACloseCA(hCAInfo); }
  1199. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1200. SetLastError(GetExceptionCode());
  1201. }
  1202. return fResult;
  1203. ErrorReturn:
  1204. //free the memory in failure case
  1205. if(NULL != pwszCALocation && NULL != *pwszCALocation)
  1206. {
  1207. WizardFree(*pwszCALocation);
  1208. *pwszCALocation=NULL;
  1209. }
  1210. if(NULL != pwszCAName && NULL != *pwszCAName)
  1211. {
  1212. WizardFree(*pwszCAName);
  1213. *pwszCAName=NULL;
  1214. }
  1215. fResult = FALSE;
  1216. goto CommonReturn;
  1217. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1218. SET_ERROR_VAR(CertCliErr, hr);
  1219. TRACE_ERROR(TraceErr);
  1220. SET_ERROR_VAR(ExceptionErr, dwException)
  1221. }