Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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