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.

3221 lines
84 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999
  5. //
  6. // File: enrlhelp.cpp
  7. //
  8. // Contents: Helper functions for smard card enrollment station
  9. //
  10. //----------------------------------------------------------------------------
  11. #define INC_OLE2
  12. #define SECURITY_WIN32 //Or in the sources file -DSECURITY_WIN32
  13. #include "stdafx.h"
  14. #include <windows.h>
  15. #include <wincrypt.h>
  16. #include <oleauto.h>
  17. #include <objbase.h>
  18. #include "security.h"
  19. #include "certca.h"
  20. #include <dbgdef.h>
  21. #include "unicode.h"
  22. #include "scrdenrl.h"
  23. #include "SCrdEnr.h"
  24. #include "xEnroll.h"
  25. #include "enrlhelp.h"
  26. #include "scenum.h"
  27. #include "wzrdpvk.h"
  28. UINT g_cfDsObjectPicker = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST);
  29. //-----------------------------------------------------------------------------
  30. // Memory routines
  31. //
  32. //-----------------------------------------------------------------------------
  33. void*
  34. MIDL_user_allocate(size_t cb)
  35. {
  36. return(SCrdEnrollAlloc(cb));
  37. }
  38. void
  39. MIDL_user_free(void *pb)
  40. {
  41. SCrdEnrollFree(pb);
  42. }
  43. LPVOID SCrdEnrollAlloc (ULONG cbSize)
  44. {
  45. return CoTaskMemAlloc(cbSize);
  46. }
  47. LPVOID SCrdEnrollRealloc (
  48. LPVOID pv,
  49. ULONG cbSize)
  50. {
  51. LPVOID pvTemp=NULL;
  52. if(NULL==pv)
  53. return CoTaskMemAlloc(cbSize);
  54. return CoTaskMemRealloc(pv, cbSize);
  55. }
  56. VOID SCrdEnrollFree (LPVOID pv)
  57. {
  58. if (pv)
  59. CoTaskMemFree(pv);
  60. }
  61. BOOL CertTypeFlagsToGenKeyFlags(IN OPTIONAL DWORD dwEnrollmentFlags,
  62. IN OPTIONAL DWORD dwSubjectNameFlags,
  63. IN OPTIONAL DWORD dwPrivateKeyFlags,
  64. IN OPTIONAL DWORD dwGeneralFlags,
  65. OUT DWORD *pdwGenKeyFlags)
  66. {
  67. // Define a locally scoped helper function. This allows us to gain the benefits of procedural
  68. // abstraction without corrupting the global namespace.
  69. //
  70. LocalScope(CertTypeMap):
  71. // Maps cert type flags of one category (enrollment flags, private key flags, etc...)
  72. // to their corresponding gen key flags. This function always returns successfully.
  73. //
  74. DWORD mapOneCertTypeCategory(IN DWORD dwOption, IN DWORD dwCertTypeFlags)
  75. {
  76. static DWORD const rgdwEnrollmentFlags[][2] = {
  77. { 0, 0 } // No enrollment flags mapped.
  78. };
  79. static DWORD const rgdwSubjectNameFlags[][2] = {
  80. { 0, 0 } // No subject name flags mapped.
  81. };
  82. static DWORD const rgdwPrivateKeyFlags[][2] = {
  83. { CT_FLAG_EXPORTABLE_KEY, CRYPT_EXPORTABLE }
  84. };
  85. static DWORD const rgdwGeneralFlags[][2] = {
  86. { 0, 0 } // No general flags mapped.
  87. };
  88. static DWORD const dwEnrollmentLen = sizeof(rgdwEnrollmentFlags) / sizeof(DWORD[2]);
  89. static DWORD const dwSubjectNameLen = sizeof(rgdwSubjectNameFlags) / sizeof(DWORD[2]);
  90. static DWORD const dwPrivateKeyLen = sizeof(rgdwPrivateKeyFlags) / sizeof(DWORD[2]);
  91. static DWORD const dwGeneralLen = sizeof(rgdwGeneralFlags) / sizeof(DWORD[2]);
  92. static DWORD const CERT_TYPE_INDEX = 0;
  93. static DWORD const GEN_KEY_INDEX = 1;
  94. DWORD const *pdwFlags;
  95. DWORD dwLen, dwIndex, dwResult = 0;
  96. switch (dwOption)
  97. {
  98. case CERTTYPE_ENROLLMENT_FLAG:
  99. pdwFlags = &rgdwEnrollmentFlags[0][0];
  100. dwLen = dwEnrollmentLen;
  101. break;
  102. case CERTTYPE_SUBJECT_NAME_FLAG:
  103. pdwFlags = &rgdwSubjectNameFlags[0][0];
  104. dwLen = dwSubjectNameLen;
  105. break;
  106. case CERTTYPE_PRIVATE_KEY_FLAG:
  107. pdwFlags = &rgdwPrivateKeyFlags[0][0];
  108. dwLen = dwPrivateKeyLen;
  109. break;
  110. case CERTTYPE_GENERAL_FLAG:
  111. pdwFlags = &rgdwGeneralFlags[0][0];
  112. dwLen = dwGeneralLen;
  113. break;
  114. }
  115. for (dwIndex = 0; dwIndex < dwLen; dwIndex++)
  116. {
  117. if (0 != (pdwFlags[CERT_TYPE_INDEX] & dwCertTypeFlags))
  118. {
  119. dwResult |= pdwFlags[GEN_KEY_INDEX];
  120. }
  121. pdwFlags += 2;
  122. }
  123. return dwResult;
  124. }
  125. EndLocalScope;
  126. //
  127. // Begin procedure body:
  128. //
  129. BOOL fResult;
  130. DWORD dwResult = 0;
  131. DWORD dwErr = ERROR_SUCCESS;
  132. // Input parameter validation:
  133. _JumpConditionWithExpr(pdwGenKeyFlags == NULL, Error, dwErr = ERROR_INVALID_PARAMETER);
  134. // Compute the gen key flags using the locally scope function.
  135. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_ENROLLMENT_FLAG, dwEnrollmentFlags);
  136. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_SUBJECT_NAME_FLAG, dwSubjectNameFlags);
  137. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_PRIVATE_KEY_FLAG, dwPrivateKeyFlags);
  138. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_GENERAL_FLAG, dwGeneralFlags);
  139. // Assign the out parameter:
  140. *pdwGenKeyFlags = dwResult;
  141. fResult = TRUE;
  142. CommonReturn:
  143. return fResult;
  144. Error:
  145. fResult = FALSE;
  146. SetLastError(dwErr);
  147. goto CommonReturn;
  148. }
  149. //----------------------------------------------------------------------------
  150. // CallBack fro cert selection call back
  151. //
  152. //----------------------------------------------------------------------------
  153. BOOL WINAPI SelectSignCertCallBack(
  154. PCCERT_CONTEXT pCertContext,
  155. BOOL *pfInitialSelectedCert,
  156. void *pvCallbackData)
  157. {
  158. BOOL fRet = FALSE;
  159. DWORD cbData=0;
  160. SCrdEnroll_CERT_SELECT_INFO *pCertSelectInfo;
  161. PCERT_ENHKEY_USAGE pUsage = NULL;
  162. CHAR *pszOID = NULL;
  163. DWORD i;
  164. BOOL fFoundOid;
  165. if(!pCertContext)
  166. {
  167. goto done;
  168. }
  169. //the certificate has to have the CERT_KEY_PROV_INFO_PROP_ID
  170. if(!CertGetCertificateContextProperty(pCertContext,
  171. CERT_KEY_PROV_INFO_PROP_ID,
  172. NULL,
  173. &cbData))
  174. {
  175. goto done;
  176. }
  177. if(0==cbData)
  178. {
  179. goto done;
  180. }
  181. pCertSelectInfo = (SCrdEnroll_CERT_SELECT_INFO *)pvCallbackData;
  182. if(NULL == pCertSelectInfo)
  183. {
  184. goto done;
  185. }
  186. if (NULL == pCertSelectInfo->pwszCertTemplateName ||
  187. L'\0' == pCertSelectInfo->pwszCertTemplateName[0])
  188. {
  189. goto done;
  190. }
  191. switch (pCertSelectInfo->dwFlags)
  192. {
  193. case SCARD_SELECT_TEMPLATENAME:
  194. //ask to check template name
  195. if(!VerifyCertTemplateName(
  196. pCertContext,
  197. pCertSelectInfo->pwszCertTemplateName))
  198. {
  199. goto done;
  200. }
  201. break;
  202. case SCARD_SELECT_EKU:
  203. cbData = 0;
  204. while (TRUE)
  205. {
  206. cbData = WideCharToMultiByte(
  207. GetACP(),
  208. 0,
  209. pCertSelectInfo->pwszCertTemplateName,
  210. -1,
  211. pszOID,
  212. cbData,
  213. NULL,
  214. NULL);
  215. if(0 == cbData)
  216. {
  217. goto done;
  218. }
  219. if (NULL != pszOID)
  220. {
  221. break;
  222. }
  223. pszOID = (CHAR*)LocalAlloc(LMEM_FIXED, cbData);
  224. if (NULL == pszOID)
  225. {
  226. goto done;
  227. }
  228. }
  229. cbData = 0;
  230. while (TRUE)
  231. {
  232. if (!CertGetEnhancedKeyUsage(
  233. pCertContext,
  234. CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
  235. pUsage,
  236. &cbData))
  237. {
  238. goto done;
  239. }
  240. if (NULL != pUsage)
  241. {
  242. //done
  243. break;
  244. }
  245. pUsage = (PCERT_ENHKEY_USAGE)LocalAlloc(LMEM_FIXED, cbData);
  246. if (NULL == pUsage)
  247. {
  248. goto done;
  249. }
  250. }
  251. fFoundOid = FALSE;
  252. for (i = 0 ; i < pUsage->cUsageIdentifier; ++i)
  253. {
  254. if (0 == strcmp(pszOID, pUsage->rgpszUsageIdentifier[i]))
  255. {
  256. fFoundOid = TRUE;
  257. break;
  258. }
  259. }
  260. if (!fFoundOid)
  261. {
  262. //not found
  263. goto done;
  264. }
  265. break;
  266. default:
  267. //invalid_parameter
  268. goto done;
  269. }
  270. //make sure the certificate pass the chain building
  271. if(!VerifyCertChain(pCertContext))
  272. {
  273. goto done;
  274. }
  275. fRet = TRUE;
  276. done:
  277. if (NULL != pUsage)
  278. {
  279. LocalFree(pUsage);
  280. }
  281. if (NULL != pszOID)
  282. {
  283. LocalFree(pszOID);
  284. }
  285. return fRet;
  286. }
  287. //-------------------------------------------------------------------------
  288. // GetName
  289. //
  290. //--------------------------------------------------------------------------
  291. BOOL GetName(LPWSTR pwszName,
  292. EXTENDED_NAME_FORMAT NameFormat,
  293. EXTENDED_NAME_FORMAT DesiredFormat,
  294. LPWSTR *ppwszDesiredName)
  295. {
  296. BOOL fResult = FALSE;
  297. DWORD cbSize = 0;
  298. *ppwszDesiredName = NULL;
  299. if(!TranslateNameW(
  300. pwszName,
  301. NameFormat,
  302. DesiredFormat,
  303. NULL,
  304. &cbSize))
  305. goto TraceErr;
  306. *ppwszDesiredName=(LPWSTR)SCrdEnrollAlloc((cbSize + 1) * sizeof(WCHAR));
  307. if(NULL == *ppwszDesiredName)
  308. goto MemoryErr;
  309. if(!TranslateNameW(
  310. pwszName,
  311. NameFormat,
  312. DesiredFormat,
  313. *ppwszDesiredName,
  314. &cbSize))
  315. goto TraceErr;
  316. fResult = TRUE;
  317. CommonReturn:
  318. return fResult;
  319. ErrorReturn:
  320. if(*ppwszDesiredName)
  321. {
  322. SCrdEnrollFree(*ppwszDesiredName);
  323. *ppwszDesiredName = NULL;
  324. }
  325. fResult = FALSE;
  326. goto CommonReturn;
  327. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  328. TRACE_ERROR(TraceErr);
  329. }
  330. //-------------------------------------------------------------------------
  331. // VerifyCertChain
  332. //
  333. //--------------------------------------------------------------------------
  334. BOOL VerifyCertChain(PCCERT_CONTEXT pCertContext)
  335. {
  336. PCCERT_CHAIN_CONTEXT pCertChainContext = NULL;
  337. CERT_CHAIN_PARA CertChainPara;
  338. BOOL fResult=FALSE;
  339. DWORD dwChainError=CERT_TRUST_IS_NOT_TIME_VALID |
  340. CERT_TRUST_IS_NOT_TIME_NESTED |
  341. CERT_TRUST_IS_REVOKED |
  342. CERT_TRUST_IS_NOT_SIGNATURE_VALID |
  343. CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
  344. CERT_TRUST_IS_UNTRUSTED_ROOT |
  345. CERT_TRUST_IS_CYCLIC |
  346. CERT_TRUST_IS_PARTIAL_CHAIN |
  347. CERT_TRUST_CTL_IS_NOT_TIME_VALID |
  348. CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID |
  349. CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE;
  350. memset(&CertChainPara, 0, sizeof(CertChainPara));
  351. CertChainPara.cbSize = sizeof(CertChainPara);
  352. if (!CertGetCertificateChain(
  353. HCCE_CURRENT_USER,
  354. pCertContext,
  355. NULL,
  356. NULL,
  357. &CertChainPara,
  358. CERT_CHAIN_REVOCATION_CHECK_CHAIN,
  359. NULL,
  360. &pCertChainContext))
  361. goto CLEANUP;
  362. //
  363. // make sure there is at least 1 simple chain
  364. //
  365. if (pCertChainContext->cChain == 0)
  366. goto CLEANUP;
  367. // make sure that we have a good simple chain
  368. if(dwChainError & (pCertChainContext->rgpChain[0]->TrustStatus.dwErrorStatus))
  369. goto CLEANUP;
  370. fResult = TRUE;
  371. CLEANUP:
  372. if (pCertChainContext != NULL)
  373. CertFreeCertificateChain(pCertChainContext);
  374. return fResult;
  375. }
  376. //-------------------------------------------------------------------------
  377. // VerifyCertTemplateName
  378. //
  379. //--------------------------------------------------------------------------
  380. BOOL VerifyCertTemplateName(PCCERT_CONTEXT pCertContext,
  381. LPWSTR pwszCertTemplateName)
  382. {
  383. BOOL fResult=FALSE;
  384. PCERT_EXTENSION pCertTypeExtension=NULL;
  385. DWORD cbCertType=0;
  386. CERT_NAME_VALUE *pCertType=NULL;
  387. if((!pCertContext) || (!pwszCertTemplateName))
  388. goto CLEANUP;
  389. //find the extension for cert type
  390. if(NULL==(pCertTypeExtension=CertFindExtension(
  391. szOID_ENROLL_CERTTYPE_EXTENSION,
  392. pCertContext->pCertInfo->cExtension,
  393. pCertContext->pCertInfo->rgExtension)))
  394. goto CLEANUP;
  395. if(!CryptDecodeObject(pCertContext->dwCertEncodingType,
  396. X509_UNICODE_ANY_STRING,
  397. pCertTypeExtension->Value.pbData,
  398. pCertTypeExtension->Value.cbData,
  399. 0,
  400. NULL,
  401. &cbCertType) || (0==cbCertType))
  402. goto CLEANUP;
  403. pCertType=(CERT_NAME_VALUE *)SCrdEnrollAlloc(cbCertType);
  404. if(NULL==pCertType)
  405. goto CLEANUP;
  406. if(!CryptDecodeObject(pCertContext->dwCertEncodingType,
  407. X509_UNICODE_ANY_STRING,
  408. pCertTypeExtension->Value.pbData,
  409. pCertTypeExtension->Value.cbData,
  410. 0,
  411. (void *)pCertType,
  412. &cbCertType))
  413. goto CLEANUP;
  414. if(0 != _wcsicmp((LPWSTR)(pCertType->Value.pbData), pwszCertTemplateName))
  415. goto CLEANUP;
  416. fResult=TRUE;
  417. CLEANUP:
  418. if(pCertType)
  419. SCrdEnrollFree(pCertType);
  420. return fResult;
  421. }
  422. //----------------------------------------------------------------------------
  423. //
  424. // CopyWideString
  425. //
  426. //----------------------------------------------------------------------------
  427. LPWSTR CopyWideString(LPCWSTR wsz)
  428. {
  429. DWORD cch = 0;
  430. LPWSTR wszOut = NULL;
  431. if(wsz == NULL) {
  432. SetLastError(ERROR_INVALID_PARAMETER);
  433. return(NULL);
  434. }
  435. cch = wcslen(wsz) + 1;
  436. if( (wszOut = (LPWSTR) SCrdEnrollAlloc(sizeof(WCHAR) * cch)) == NULL ) {
  437. SetLastError(ERROR_OUTOFMEMORY);
  438. return(NULL);
  439. }
  440. wcscpy(wszOut, wsz);
  441. return(wszOut);
  442. }
  443. //----------------------------------------------------------------------------
  444. //
  445. // CopyWideStrings
  446. //
  447. //----------------------------------------------------------------------------
  448. LPWSTR* CopyWideStrings(LPWSTR* rgpwsz)
  449. {
  450. DWORD dwCount = 1;
  451. DWORD dwIndex = 0;
  452. DWORD cb = 0;
  453. LPWSTR *ppwsz;
  454. LPWSTR *rgpwszOut = NULL;
  455. LPWSTR pwszCur;
  456. if (NULL != rgpwsz)
  457. {
  458. //get count of strings
  459. for (ppwsz = rgpwsz; NULL != *ppwsz; ppwsz++)
  460. {
  461. ++dwCount;
  462. cb += (wcslen(*ppwsz) + 1) * sizeof(WCHAR);
  463. }
  464. }
  465. // allocate buffer
  466. rgpwszOut = (LPWSTR*)SCrdEnrollAlloc(dwCount * sizeof(WCHAR*) + cb);
  467. if (NULL == rgpwszOut)
  468. {
  469. SetLastError(ERROR_OUTOFMEMORY);
  470. goto error;
  471. }
  472. if (NULL != rgpwsz)
  473. {
  474. pwszCur = (LPWSTR)(rgpwszOut + dwCount);
  475. for(ppwsz = rgpwsz; NULL != *ppwsz; ppwsz++)
  476. {
  477. rgpwszOut[dwIndex] = pwszCur;
  478. wcscpy(pwszCur, *ppwsz);
  479. pwszCur += wcslen(pwszCur) + 1;
  480. ++dwIndex;
  481. }
  482. }
  483. rgpwszOut[dwIndex] = NULL;
  484. error:
  485. return(rgpwszOut);
  486. }
  487. //--------------------------------------------------------------------------
  488. //
  489. // Decode a generic BLOB
  490. //
  491. //--------------------------------------------------------------------------
  492. BOOL DecodeGenericBLOB(DWORD dwEncodingType, LPCSTR lpszStructType,
  493. const BYTE *pbEncoded, DWORD cbEncoded,void **ppStructInfo)
  494. {
  495. DWORD cbStructInfo=0;
  496. //decode the object. No copying
  497. if(!CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded, cbEncoded,
  498. 0,NULL, &cbStructInfo))
  499. return FALSE;
  500. *ppStructInfo=SCrdEnrollAlloc(cbStructInfo);
  501. if(!(*ppStructInfo))
  502. {
  503. SetLastError(E_OUTOFMEMORY);
  504. return FALSE;
  505. }
  506. return CryptDecodeObject(dwEncodingType,lpszStructType,pbEncoded, cbEncoded,
  507. 0,*ppStructInfo,&cbStructInfo);
  508. }
  509. //----------------------------------------------------------------------------
  510. //
  511. // GetNameFromPKCS10
  512. //
  513. //----------------------------------------------------------------------------
  514. BOOL GetNameFromPKCS10(BYTE *pbPKCS10,
  515. DWORD cbPKCS10,
  516. DWORD dwFlags,
  517. LPSTR pszOID,
  518. LPWSTR *ppwszName)
  519. {
  520. BOOL fResult=FALSE;
  521. DWORD errBefore= GetLastError();
  522. DWORD dwRDNIndex=0;
  523. DWORD dwAttrCount=0;
  524. DWORD dwAttrIndex=0;
  525. CERT_RDN_ATTR *pCertRDNAttr=NULL;
  526. CERT_REQUEST_INFO *pCertRequestInfo=NULL;
  527. CERT_NAME_INFO *pCertNameInfo=NULL;
  528. *ppwszName=NULL;
  529. if(!DecodeGenericBLOB(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  530. X509_CERT_REQUEST_TO_BE_SIGNED,
  531. pbPKCS10,
  532. cbPKCS10,
  533. (void **)&pCertRequestInfo))
  534. goto TraceErr;
  535. if(!DecodeGenericBLOB(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  536. X509_UNICODE_NAME,
  537. (pCertRequestInfo->Subject).pbData,
  538. (pCertRequestInfo->Subject).cbData,
  539. (void **)&pCertNameInfo))
  540. goto TraceErr;
  541. //search for the OID requested.
  542. *ppwszName = (LPWSTR)SCrdEnrollAlloc(sizeof(WCHAR));
  543. if(NULL == (*ppwszName))
  544. goto MemoryErr;
  545. *(*ppwszName)=L'\0';
  546. for(dwRDNIndex=0; dwRDNIndex<pCertNameInfo->cRDN; dwRDNIndex++)
  547. {
  548. dwAttrCount=(pCertNameInfo->rgRDN)[dwRDNIndex].cRDNAttr;
  549. for(dwAttrIndex=0; dwAttrIndex<dwAttrCount; dwAttrIndex++)
  550. {
  551. pCertRDNAttr=&((pCertNameInfo->rgRDN)[dwRDNIndex].rgRDNAttr[dwAttrIndex]);
  552. if(_stricmp(pszOID, pCertRDNAttr->pszObjId)==0)
  553. {
  554. if(0 != wcslen(*ppwszName))
  555. wcscat(*ppwszName, L"; ");
  556. (*ppwszName) = (LPWSTR)SCrdEnrollRealloc
  557. (*ppwszName, sizeof(WCHAR) *
  558. (wcslen(*ppwszName) + wcslen(L"; ") +
  559. wcslen((LPWSTR)((pCertRDNAttr->Value).pbData))+1));
  560. if(NULL == *ppwszName)
  561. goto MemoryErr;
  562. wcscat(*ppwszName, (LPWSTR)((pCertRDNAttr->Value).pbData));
  563. }
  564. }
  565. }
  566. if(0 == wcslen(*ppwszName))
  567. goto NotFindErr;
  568. fResult=TRUE;
  569. CommonReturn:
  570. if(pCertRequestInfo)
  571. SCrdEnrollFree(pCertRequestInfo);
  572. if(pCertNameInfo)
  573. SCrdEnrollFree(pCertNameInfo);
  574. SetLastError(errBefore);
  575. return fResult;
  576. ErrorReturn:
  577. errBefore = GetLastError();
  578. if(*ppwszName)
  579. {
  580. SCrdEnrollFree(*ppwszName);
  581. *ppwszName=NULL;
  582. }
  583. fResult=FALSE;
  584. goto CommonReturn;
  585. TRACE_ERROR(TraceErr);
  586. SET_ERROR(NotFindErr, CRYPT_E_NOT_FOUND);
  587. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  588. }
  589. //----------------------------------------------------------------------------
  590. //
  591. // SearchAndDeleteCert
  592. //
  593. //----------------------------------------------------------------------------
  594. BOOL SearchAndDeleteCert(PCCERT_CONTEXT pCertContext)
  595. {
  596. BOOL fResult=FALSE;
  597. DWORD errBefore= GetLastError();
  598. HCERTSTORE hCertStore=NULL;
  599. PCCERT_CONTEXT pFoundCert=NULL;
  600. CERT_BLOB HashBlob;
  601. memset(&HashBlob, 0, sizeof(CERT_BLOB));
  602. if(NULL==pCertContext)
  603. goto InvalidArgErr;
  604. //open the temporary store
  605. hCertStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  606. g_dwMsgAndCertEncodingType,
  607. NULL,
  608. CERT_SYSTEM_STORE_CURRENT_USER,
  609. g_MyStoreName);
  610. if(NULL==hCertStore)
  611. goto TraceErr;
  612. //get the SHA1 hash
  613. if(!CertGetCertificateContextProperty(
  614. pCertContext,
  615. CERT_SHA1_HASH_PROP_ID,
  616. NULL,
  617. &(HashBlob.cbData)))
  618. goto TraceErr;
  619. HashBlob.pbData=(BYTE *)SCrdEnrollAlloc(HashBlob.cbData);
  620. if(NULL==(HashBlob.pbData))
  621. goto MemoryErr;
  622. if(!CertGetCertificateContextProperty(
  623. pCertContext,
  624. CERT_SHA1_HASH_PROP_ID,
  625. HashBlob.pbData,
  626. &(HashBlob.cbData)))
  627. goto TraceErr;
  628. pFoundCert=CertFindCertificateInStore(
  629. hCertStore,
  630. X509_ASN_ENCODING,
  631. 0,
  632. CERT_FIND_SHA1_HASH,
  633. &HashBlob,
  634. NULL);
  635. if(pFoundCert)
  636. CertDeleteCertificateFromStore(pFoundCert);
  637. fResult=TRUE;
  638. CommonReturn:
  639. if(hCertStore)
  640. CertCloseStore(hCertStore, 0);
  641. if(HashBlob.pbData)
  642. SCrdEnrollFree(HashBlob.pbData);
  643. SetLastError(errBefore);
  644. return fResult;
  645. ErrorReturn:
  646. errBefore = GetLastError();
  647. fResult=FALSE;
  648. goto CommonReturn;
  649. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  650. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  651. TRACE_ERROR(TraceErr);
  652. }
  653. //--------------------------------------------------------------------------
  654. //
  655. // FormatMessageUnicode
  656. //
  657. //--------------------------------------------------------------------------
  658. BOOL FormatMessageUnicode(LPWSTR *ppwszFormat,LPWSTR wszFormat,...)
  659. {
  660. va_list argList;
  661. DWORD cbMsg=0;
  662. BOOL fResult=FALSE;
  663. HRESULT hr=S_OK;
  664. if(NULL == ppwszFormat)
  665. goto InvalidArgErr;
  666. // format message into requested buffer
  667. va_start(argList, wszFormat);
  668. cbMsg = FormatMessageU(
  669. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  670. wszFormat,
  671. 0, // dwMessageId
  672. 0, // dwLanguageId
  673. (LPWSTR) (ppwszFormat),
  674. 0, // minimum size to allocate
  675. &argList);
  676. va_end(argList);
  677. if(!cbMsg)
  678. goto FormatMessageError;
  679. fResult=TRUE;
  680. CommonReturn:
  681. return fResult;
  682. ErrorReturn:
  683. fResult=FALSE;
  684. goto CommonReturn;
  685. TRACE_ERROR(FormatMessageError);
  686. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  687. }
  688. //-----------------------------------------------------------------------
  689. //
  690. // IsNewerCert
  691. //
  692. // Return TRUE is pFirstCert has a later starting date of pSecondCert
  693. //------------------------------------------------------------------------
  694. BOOL IsNewerCert(PCCERT_CONTEXT pFirstCert,
  695. PCCERT_CONTEXT pSecondCert)
  696. {
  697. if(NULL == pSecondCert)
  698. return TRUE;
  699. if(NULL == pFirstCert)
  700. return FALSE;
  701. if(1 != CompareFileTime(&(pFirstCert->pCertInfo->NotBefore),
  702. &(pSecondCert->pCertInfo->NotBefore)))
  703. return FALSE;
  704. return TRUE;
  705. }
  706. //-----------------------------------------------------------------------
  707. //
  708. // SmartCardCSP
  709. //
  710. // Return TRUE is the CSP is a smart card CSP. If anything went wrong,
  711. // we will return TRUE for as a safe guard.
  712. //------------------------------------------------------------------------
  713. BOOL SmartCardCSP(PCCERT_CONTEXT pCertContext)
  714. {
  715. BOOL fResult = TRUE;
  716. DWORD cbData = 0;
  717. DWORD dwImpType=0;
  718. CRYPT_KEY_PROV_INFO *pProvInfo=NULL;
  719. HCRYPTPROV hProv = NULL;
  720. if(NULL == pCertContext)
  721. goto CLEANUP;
  722. //the certificate has to have the CERT_KEY_PROV_INFO_PROP_ID
  723. if(!CertGetCertificateContextProperty(pCertContext,
  724. CERT_KEY_PROV_INFO_PROP_ID,
  725. NULL,
  726. &cbData))
  727. goto CLEANUP;
  728. if((cbData == 0) || (NULL == (pProvInfo =(CRYPT_KEY_PROV_INFO *)SCrdEnrollAlloc(cbData))))
  729. goto CLEANUP;
  730. if(!CertGetCertificateContextProperty(pCertContext,
  731. CERT_KEY_PROV_INFO_PROP_ID,
  732. pProvInfo,
  733. &cbData))
  734. goto CLEANUP;
  735. if(!CryptAcquireContextU(&hProv,
  736. NULL,
  737. pProvInfo->pwszProvName,
  738. pProvInfo->dwProvType,
  739. CRYPT_VERIFYCONTEXT))
  740. goto CLEANUP;
  741. cbData = sizeof(dwImpType);
  742. if(!CryptGetProvParam(hProv,
  743. PP_IMPTYPE,
  744. (BYTE *)(&dwImpType),
  745. &cbData,
  746. 0))
  747. goto CLEANUP;
  748. if(0 == (CRYPT_IMPL_REMOVABLE & dwImpType))
  749. fResult = FALSE;
  750. CLEANUP:
  751. if(hProv)
  752. CryptReleaseContext(hProv, 0);
  753. if(pProvInfo)
  754. SCrdEnrollFree(pProvInfo);
  755. return fResult;
  756. }
  757. //-----------------------------------------------------------------------
  758. //
  759. // ChKInsertedCardSigningCert
  760. //
  761. // This function checks to see if the inserted smart card matches
  762. // the signing certificate. That is, they are actually the same cert
  763. // with the same public key
  764. //
  765. //------------------------------------------------------------------------
  766. BOOL ChKInsertedCardSigningCert(LPWSTR pwszInsertProvider,
  767. DWORD dwInsertProviderType,
  768. LPWSTR pwszReaderName,
  769. PCCERT_CONTEXT pSignCertContext,
  770. LPSTR pszSignProvider,
  771. DWORD dwSignProviderType,
  772. LPSTR pszSignContainer,
  773. BOOL *pfSame)
  774. {
  775. BOOL fResult=FALSE;
  776. DWORD cbData=0;
  777. CRYPT_KEY_PROV_INFO *pKeyProvInfo=NULL;
  778. CERT_PUBLIC_KEY_INFO *pPubInfo=NULL;
  779. HCRYPTPROV hProv=NULL;
  780. LPWSTR pwszInsertContainer=NULL;
  781. LPWSTR pwszSignProvider=NULL;
  782. if(NULL==pwszInsertProvider || NULL == pwszReaderName ||
  783. NULL == pSignCertContext || NULL == pszSignProvider ||
  784. NULL == pszSignContainer || NULL == pfSame)
  785. goto InvalidArgErr;
  786. *pfSame=FALSE;
  787. //get the key specification from the signing cert
  788. if(!CertGetCertificateContextProperty(
  789. pSignCertContext,
  790. CERT_KEY_PROV_INFO_PROP_ID,
  791. NULL,
  792. &cbData) || (0==cbData))
  793. goto TraceErr;
  794. pKeyProvInfo=(CRYPT_KEY_PROV_INFO *)SCrdEnrollAlloc(cbData);
  795. if(NULL==pKeyProvInfo)
  796. goto MemoryErr;
  797. if(!CertGetCertificateContextProperty(
  798. pSignCertContext,
  799. CERT_KEY_PROV_INFO_PROP_ID,
  800. pKeyProvInfo,
  801. &cbData))
  802. goto TraceErr;
  803. //build a default container name with the reader information
  804. if(!FormatMessageUnicode(&pwszInsertContainer,
  805. L"\\\\.\\%1!s!\\",
  806. pwszReaderName))
  807. goto TraceErr;
  808. //get the hProv from the reader's card
  809. if(!CryptAcquireContextU(&hProv,
  810. pwszInsertContainer,
  811. pwszInsertProvider,
  812. dwInsertProviderType,
  813. CRYPT_SILENT))
  814. {
  815. //check to see if we have an empty card
  816. if((GetLastError() == NTE_BAD_KEYSET) ||
  817. (GetLastError() == NTE_KEYSET_NOT_DEF))
  818. {
  819. //we have an empty card
  820. *pfSame=FALSE;
  821. fResult=TRUE;
  822. goto CommonReturn;
  823. }
  824. else
  825. goto TraceErr;
  826. }
  827. //get the public key information
  828. cbData=0;
  829. if(!CryptExportPublicKeyInfo(hProv,
  830. pKeyProvInfo->dwKeySpec,
  831. pSignCertContext->dwCertEncodingType,
  832. NULL,
  833. &cbData) || (0 == cbData))
  834. {
  835. //the insert card does not have a private key
  836. *pfSame=FALSE;
  837. fResult=TRUE;
  838. goto CommonReturn;
  839. }
  840. pPubInfo = (CERT_PUBLIC_KEY_INFO *)SCrdEnrollAlloc(cbData);
  841. if(NULL == pPubInfo)
  842. goto MemoryErr;
  843. if(!CryptExportPublicKeyInfo(hProv,
  844. pKeyProvInfo->dwKeySpec,
  845. pSignCertContext->dwCertEncodingType,
  846. pPubInfo,
  847. &cbData))
  848. {
  849. //the insert card does not have a private key
  850. *pfSame=FALSE;
  851. fResult=TRUE;
  852. goto CommonReturn;
  853. }
  854. if(CertComparePublicKeyInfo(pSignCertContext->dwCertEncodingType,
  855. pPubInfo,
  856. &(pSignCertContext->pCertInfo->SubjectPublicKeyInfo)))
  857. {
  858. //make sure that we have the same CSP name
  859. pwszSignProvider=MkWStr(pszSignProvider);
  860. if(NULL != pwszSignProvider)
  861. {
  862. //case insensitive compare of the two csp names
  863. if(0 == _wcsicmp(pwszSignProvider, pwszInsertProvider))
  864. *pfSame=TRUE;
  865. else
  866. *pfSame=FALSE;
  867. }
  868. else
  869. {
  870. //we are out of memory. Assume same CSP here
  871. *pfSame=TRUE;
  872. }
  873. }
  874. else
  875. *pfSame=FALSE;
  876. fResult=TRUE;
  877. CommonReturn:
  878. if(pwszSignProvider)
  879. FreeWStr(pwszSignProvider);
  880. if(pPubInfo)
  881. SCrdEnrollFree(pPubInfo);
  882. if(pKeyProvInfo)
  883. SCrdEnrollFree(pKeyProvInfo);
  884. if(hProv)
  885. CryptReleaseContext(hProv, 0);
  886. if(pwszInsertContainer)
  887. LocalFree((HLOCAL)pwszInsertContainer);
  888. return fResult;
  889. ErrorReturn:
  890. fResult=FALSE;
  891. goto CommonReturn;
  892. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  893. TRACE_ERROR(TraceErr);
  894. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  895. }
  896. //-----------------------------------------------------------------------
  897. //
  898. // DeleteKeySet
  899. //
  900. // If the user's smart card is not empty, we delete the private key
  901. //
  902. //------------------------------------------------------------------------
  903. BOOL DeleteKeySet(LPWSTR pwszUserCSPName,
  904. DWORD dwUserCSPType,
  905. LPWSTR pwszReaderName)
  906. {
  907. BOOL fResult=FALSE;
  908. DWORD dwSize=0;
  909. HCRYPTPROV hDeleteProv=NULL; //no need to free this
  910. HCRYPTPROV hProv=NULL;
  911. LPWSTR pwszDefaultContainer=NULL;
  912. LPSTR pszContainer=NULL;
  913. LPWSTR pwszContainer=NULL;
  914. if(NULL == pwszUserCSPName || NULL == pwszReaderName)
  915. goto InvalidArgErr;
  916. if(!FormatMessageUnicode(&pwszDefaultContainer,
  917. L"\\\\.\\%1!s!\\",
  918. pwszReaderName))
  919. goto TraceErr;
  920. //get the hProv from the reader's card
  921. if(!CryptAcquireContextU(&hProv,
  922. pwszDefaultContainer,
  923. pwszUserCSPName,
  924. dwUserCSPType,
  925. CRYPT_SILENT))
  926. {
  927. //check to see if we have an empty card
  928. if((GetLastError() == NTE_BAD_KEYSET) ||
  929. (GetLastError() == NTE_KEYSET_NOT_DEF))
  930. {
  931. //we have an empty card
  932. fResult=TRUE;
  933. goto CommonReturn;
  934. }
  935. else
  936. goto TraceErr;
  937. }
  938. //get the container name
  939. dwSize = 0;
  940. if(!CryptGetProvParam(hProv,
  941. PP_CONTAINER,
  942. NULL,
  943. &dwSize,
  944. 0) || (0==dwSize))
  945. goto TraceErr;
  946. pszContainer = (LPSTR) SCrdEnrollAlloc(dwSize);
  947. if(NULL == pszContainer)
  948. goto MemoryErr;
  949. if(!CryptGetProvParam(hProv,
  950. PP_CONTAINER,
  951. (BYTE *)pszContainer,
  952. &dwSize,
  953. 0))
  954. goto TraceErr;
  955. //release the context
  956. if(hProv)
  957. {
  958. CryptReleaseContext(hProv, 0);
  959. hProv=NULL;
  960. }
  961. //build the fully qualified container name
  962. if(!FormatMessageUnicode(&pwszContainer,
  963. L"\\\\.\\%1!s!\\%2!S!",
  964. pwszReaderName,
  965. pszContainer))
  966. goto TraceErr;
  967. //delete the container
  968. if(!CryptAcquireContextU(&hDeleteProv,
  969. pwszContainer,
  970. pwszUserCSPName,
  971. dwUserCSPType,
  972. CRYPT_DELETEKEYSET))
  973. {
  974. //check to see if we have an empty card
  975. if(GetLastError() == NTE_BAD_KEYSET)
  976. {
  977. //we have an empty card
  978. fResult=TRUE;
  979. goto CommonReturn;
  980. }
  981. else
  982. goto TraceErr;
  983. }
  984. fResult=TRUE;
  985. CommonReturn:
  986. if(pwszDefaultContainer)
  987. LocalFree((HLOCAL)pwszDefaultContainer);
  988. if(pwszContainer)
  989. LocalFree((HLOCAL)pwszContainer);
  990. if(pszContainer)
  991. SCrdEnrollFree(pszContainer);
  992. if(hProv)
  993. CryptReleaseContext(hProv, 0);
  994. return fResult;
  995. ErrorReturn:
  996. fResult=FALSE;
  997. goto CommonReturn;
  998. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  999. TRACE_ERROR(TraceErr);
  1000. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1001. }
  1002. //-----------------------------------------------------------------------
  1003. //
  1004. // ChkSCardStatus
  1005. //
  1006. // This function makes sure that the smart card enrollment station has the
  1007. // correct number of readers connected to the station, and the correct number
  1008. // of smart cards inserted into the readers. If everything looks good,
  1009. // the user smart card is initialized (old key container deleted) and a fully
  1010. // qualified key container name, in the format of "\\.\ReaderName\ContainerName",
  1011. // will be returned.
  1012. //
  1013. //------------------------------------------------------------------------
  1014. HRESULT ChkSCardStatus(BOOL fSCardSigningCert,
  1015. PCCERT_CONTEXT pSigningCertCertContext,
  1016. LPSTR pszCSPNameSigningCert,
  1017. DWORD dwCSPTypeSigningCert,
  1018. LPSTR pszContainerSigningCert,
  1019. LPWSTR pwszSelectedCSP,
  1020. LPWSTR *ppwszNewContainerName)
  1021. {
  1022. HRESULT hr=E_FAIL;
  1023. DWORD dwExpectedReader=0;
  1024. DWORD dwReader=0;
  1025. DWORD dwSCard=0;
  1026. WCHAR wszProvider[MAX_PATH];
  1027. DWORD dwProviderType=0;
  1028. DWORD dwCount=0;
  1029. BOOL fFindSigningCert=FALSE;
  1030. DWORD errBefore=0;
  1031. BOOL fSameCert=FALSE;
  1032. DWORD dwUserCSPType=0;
  1033. LPCWSTR pwszReaderName=NULL; //no need to free. Point to internal data
  1034. LPWSTR pwszUserReaderName=NULL; //no need to free . Point to internal data
  1035. GUID guidContainerName;
  1036. LPVOID pvContext = NULL;
  1037. LPWSTR pwszNewContainerName=NULL;
  1038. LPWSTR pwszUserCSPName=NULL;
  1039. char * sz = NULL;
  1040. RPC_STATUS rpc_status;
  1041. if(NULL == pszCSPNameSigningCert || NULL == pszContainerSigningCert ||
  1042. NULL == ppwszNewContainerName || NULL == pSigningCertCertContext ||
  1043. NULL == pwszSelectedCSP)
  1044. goto CLEANUP;
  1045. *ppwszNewContainerName=NULL;
  1046. if(fSCardSigningCert)
  1047. dwExpectedReader=2;
  1048. else
  1049. dwExpectedReader=1;
  1050. dwReader = CountReaders(NULL);
  1051. //check the # of smart card readers
  1052. if(dwReader < dwExpectedReader)
  1053. {
  1054. hr=SCARD_E_READER_UNAVAILABLE;
  1055. goto CLEANUP;
  1056. }
  1057. dwSCard = ScanReaders(&pvContext);
  1058. //no smart card is inserted
  1059. if( 0 == dwSCard || NULL == pvContext)
  1060. {
  1061. hr=SCARD_E_NO_SMARTCARD;
  1062. goto CLEANUP;
  1063. }
  1064. //we have more than expected # of smart card inserted
  1065. if(dwSCard > dwExpectedReader)
  1066. {
  1067. // seems ERROR_TOO_MANY_OPEN_FILES is closest one for this case
  1068. hr=HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES);
  1069. goto CLEANUP;
  1070. }
  1071. dwCount=0;
  1072. dwProviderType=0;
  1073. wszProvider[0]=L'\0';
  1074. pwszReaderName=NULL;
  1075. fSameCert=FALSE;
  1076. //now, we loop through we all inserted cards and make sure:
  1077. //1. We find the signing certificate if applicable
  1078. //2. We find a valid user certificate
  1079. while (EnumInsertedCards(
  1080. pvContext,
  1081. wszProvider,
  1082. sizeof(wszProvider)/sizeof(wszProvider[0]),
  1083. &dwProviderType,
  1084. &pwszReaderName))
  1085. {
  1086. if((NULL == pwszReaderName) || (0 == wcslen(wszProvider)))
  1087. {
  1088. //we can not determine the status of the smart card
  1089. hr = SCARD_E_CARD_UNSUPPORTED;
  1090. goto CLEANUP;
  1091. }
  1092. if (!ChKInsertedCardSigningCert(
  1093. wszProvider,
  1094. dwProviderType,
  1095. (LPWSTR)pwszReaderName,
  1096. pSigningCertCertContext,
  1097. pszCSPNameSigningCert,
  1098. dwCSPTypeSigningCert,
  1099. pszContainerSigningCert,
  1100. &fSameCert))
  1101. {
  1102. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1103. errBefore=E_UNEXPECTED;
  1104. hr = CodeToHR(GetLastError());
  1105. goto CLEANUP;
  1106. }
  1107. if(TRUE == fSameCert)
  1108. {
  1109. if(TRUE == fSCardSigningCert)
  1110. {
  1111. if(TRUE == fFindSigningCert)
  1112. {
  1113. //too many signing cards. Not expected
  1114. hr = SCARD_E_CARD_UNSUPPORTED;
  1115. goto CLEANUP;
  1116. }
  1117. else
  1118. fFindSigningCert=TRUE;
  1119. }
  1120. else
  1121. {
  1122. //we should not expect a siging certificate
  1123. hr=SCARD_E_CARD_UNSUPPORTED;
  1124. goto CLEANUP;
  1125. }
  1126. }
  1127. else
  1128. {
  1129. //this is a user card.
  1130. if(NULL != (pwszUserCSPName))
  1131. {
  1132. //too many user cards.
  1133. // seems ERROR_TOO_MANY_OPEN_FILES is closest one for this case
  1134. hr=HRESULT_FROM_WIN32(ERROR_TOO_MANY_OPEN_FILES);
  1135. goto CLEANUP;
  1136. }
  1137. pwszUserCSPName = CopyWideString(wszProvider);
  1138. if(NULL == pwszUserCSPName)
  1139. {
  1140. hr=E_OUTOFMEMORY;
  1141. goto CLEANUP;
  1142. }
  1143. dwUserCSPType = dwProviderType;
  1144. pwszUserReaderName = (LPWSTR)pwszReaderName;
  1145. }
  1146. dwCount++;
  1147. if(dwCount >= dwSCard)
  1148. break;
  1149. dwProviderType=0;
  1150. pwszReaderName=NULL;
  1151. wszProvider[0]=L'\0';
  1152. fSameCert=FALSE;
  1153. }
  1154. if((TRUE == fSCardSigningCert) && (FALSE == fFindSigningCert))
  1155. {
  1156. //we failed to find the signing certificate
  1157. hr=SCARD_E_NO_SUCH_CERTIFICATE;
  1158. goto CLEANUP;
  1159. }
  1160. if(NULL == pwszUserCSPName)
  1161. {
  1162. //we failed to find the target user certificate
  1163. hr=SCARD_E_NO_SMARTCARD;
  1164. goto CLEANUP;
  1165. }
  1166. //make sure the pwszUserCSPName matches with the CSP selected by the admin
  1167. if(0 != _wcsicmp(pwszUserCSPName, pwszSelectedCSP))
  1168. {
  1169. hr=SCARD_E_PROTO_MISMATCH;
  1170. goto CLEANUP;
  1171. }
  1172. //delete the key set from the user's certificate
  1173. if(!DeleteKeySet(pwszUserCSPName,
  1174. dwUserCSPType,
  1175. pwszUserReaderName))
  1176. {
  1177. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1178. errBefore=E_UNEXPECTED;
  1179. hr = CodeToHR(GetLastError());
  1180. goto CLEANUP;
  1181. }
  1182. //Build the fully qualified container name with a GUID
  1183. // get a container based on a guid
  1184. rpc_status = UuidCreate(&guidContainerName);
  1185. if (RPC_S_OK != rpc_status && RPC_S_UUID_LOCAL_ONLY != rpc_status)
  1186. {
  1187. hr = rpc_status;
  1188. goto CLEANUP;
  1189. }
  1190. rpc_status = UuidToStringA(&guidContainerName, (unsigned char **) &sz);
  1191. if (RPC_S_OK != rpc_status)
  1192. {
  1193. hr = rpc_status;
  1194. goto CLEANUP;
  1195. }
  1196. if(NULL == sz)
  1197. {
  1198. hr=E_OUTOFMEMORY;
  1199. goto CLEANUP;
  1200. }
  1201. //although the chance is VERY low, we could generate a same GUID
  1202. //as the signing cert's container.
  1203. if(0 == _stricmp(sz,pszContainerSigningCert))
  1204. {
  1205. //we will have to do this again
  1206. RpcStringFree((unsigned char **) &sz);
  1207. sz=NULL;
  1208. rpc_status = UuidCreate(&guidContainerName);
  1209. if (RPC_S_OK != rpc_status && RPC_S_UUID_LOCAL_ONLY != rpc_status)
  1210. {
  1211. hr = rpc_status;
  1212. goto CLEANUP;
  1213. }
  1214. rpc_status = UuidToStringA(&guidContainerName, (unsigned char **) &sz);
  1215. if (RPC_S_OK != rpc_status)
  1216. {
  1217. hr = rpc_status;
  1218. goto CLEANUP;
  1219. }
  1220. if(NULL == sz)
  1221. {
  1222. hr=E_OUTOFMEMORY;
  1223. goto CLEANUP;
  1224. }
  1225. //since we are guaranted a new GUID, we should be fine here
  1226. if(0 == _stricmp(sz,pszContainerSigningCert))
  1227. {
  1228. //can not support this smart card
  1229. hr = SCARD_E_CARD_UNSUPPORTED;
  1230. goto CLEANUP;
  1231. }
  1232. }
  1233. if(!FormatMessageUnicode(&pwszNewContainerName,
  1234. L"\\\\.\\%1!s!\\%2!S!",
  1235. pwszUserReaderName,
  1236. sz))
  1237. {
  1238. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1239. errBefore=E_UNEXPECTED;
  1240. hr = CodeToHR(GetLastError());
  1241. goto CLEANUP;
  1242. }
  1243. *ppwszNewContainerName = pwszNewContainerName;
  1244. pwszNewContainerName = NULL;
  1245. hr=S_OK;
  1246. CLEANUP:
  1247. if(pwszUserCSPName)
  1248. SCrdEnrollFree(pwszUserCSPName);
  1249. if(sz)
  1250. RpcStringFree((unsigned char **) &sz);
  1251. if(pvContext)
  1252. EndReaderScan(&pvContext);
  1253. if(pwszNewContainerName)
  1254. LocalFree((HLOCAL)pwszNewContainerName);
  1255. return hr;
  1256. }
  1257. //-----------------------------------------------------------------------
  1258. //
  1259. // SignWithCert
  1260. //
  1261. // We sign a dummy message with the signing certificate so that
  1262. // the smart card insert cert dialogue will be prompted
  1263. //
  1264. //------------------------------------------------------------------------
  1265. BOOL SignWithCert(LPSTR pszCSPName,
  1266. DWORD dwCSPType,
  1267. PCCERT_CONTEXT pSigningCert)
  1268. {
  1269. BOOL fResult=FALSE;
  1270. DWORD errBefore= GetLastError();
  1271. HRESULT hr=E_FAIL;
  1272. CRYPT_SIGN_MESSAGE_PARA signMsgPara;
  1273. DWORD cbData=0;
  1274. BYTE *pbData=NULL;
  1275. IEnroll *pIEnroll=NULL;
  1276. LPWSTR pwszCSPName=NULL;
  1277. LPWSTR pwszOID=NULL;
  1278. LPSTR pszOID=NULL;
  1279. char szMessage[] = "MyMessage";
  1280. LPSTR pszMessage = szMessage;
  1281. BYTE* pbMessage = (BYTE*) pszMessage;
  1282. DWORD cbMessage = sizeof(szMessage);
  1283. memset(&signMsgPara, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA));
  1284. if(NULL == pszCSPName)
  1285. goto InvalidArgErr;
  1286. pwszCSPName = MkWStr(pszCSPName);
  1287. if(NULL == pwszCSPName)
  1288. goto MemoryErr;
  1289. //use xEnroll to get the correct hash algorithm for the
  1290. //CSP
  1291. if(NULL == (pIEnroll=PIEnrollGetNoCOM()))
  1292. goto TraceErr;
  1293. //set the CSP information
  1294. if(S_OK != (hr=pIEnroll->put_ProviderType(dwCSPType)))
  1295. goto SetErr;
  1296. if(S_OK !=(hr=pIEnroll->put_ProviderNameWStr(pwszCSPName)))
  1297. goto SetErr;
  1298. if(S_OK != (hr=pIEnroll->get_HashAlgorithmWStr(&pwszOID)))
  1299. goto SetErr;
  1300. if(!MkMBStr(NULL, 0, pwszOID, &pszOID))
  1301. goto TraceErr;
  1302. signMsgPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
  1303. signMsgPara.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
  1304. signMsgPara.pSigningCert = pSigningCert;
  1305. signMsgPara.HashAlgorithm.pszObjId = pszOID;
  1306. signMsgPara.cMsgCert = 1;
  1307. signMsgPara.rgpMsgCert = &pSigningCert;
  1308. cbData = 0;
  1309. if( !CryptSignMessage(
  1310. &signMsgPara,
  1311. FALSE,
  1312. 1,
  1313. (const BYTE **) &(pbMessage),
  1314. &(cbMessage) ,
  1315. NULL,
  1316. &cbData)|| (0 == cbData))
  1317. goto TraceErr;
  1318. pbData = (BYTE *)SCrdEnrollAlloc(cbData);
  1319. if(NULL == pbData)
  1320. goto MemoryErr;
  1321. if( !CryptSignMessage(
  1322. &signMsgPara,
  1323. FALSE,
  1324. 1,
  1325. (const BYTE **) &(pbMessage),
  1326. &(cbMessage) ,
  1327. pbData,
  1328. &cbData))
  1329. goto TraceErr;
  1330. fResult=TRUE;
  1331. CommonReturn:
  1332. if(pbData)
  1333. SCrdEnrollFree(pbData);
  1334. if(pwszCSPName)
  1335. FreeWStr(pwszCSPName);
  1336. if(pszOID)
  1337. FreeMBStr(NULL,pszOID);
  1338. //the memory from xEnroll is freed via LocalFree
  1339. //since we use the PIEnrollGetNoCOM function
  1340. if(pwszOID)
  1341. LocalFree(pwszOID);
  1342. if(pIEnroll)
  1343. pIEnroll->Release();
  1344. SetLastError(errBefore);
  1345. return fResult;
  1346. ErrorReturn:
  1347. errBefore = GetLastError();
  1348. fResult=FALSE;
  1349. goto CommonReturn;
  1350. TRACE_ERROR(TraceErr);
  1351. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1352. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1353. SET_ERROR_VAR(SetErr, hr);
  1354. }
  1355. //-----------------------------------------------------------------------
  1356. //
  1357. // GetSelectedUserName
  1358. //
  1359. //------------------------------------------------------------------------
  1360. HRESULT GetSelectedUserName(IDsObjectPicker *pDsObjectPicker,
  1361. LPWSTR *ppwszSelectedUserSAM,
  1362. LPWSTR *ppwszSelectedUserUPN)
  1363. {
  1364. HRESULT hr= E_FAIL;
  1365. DWORD errBefore= GetLastError();
  1366. BOOL fGotStgMedium = FALSE;
  1367. LPWSTR pwszPath=NULL;
  1368. DWORD dwIndex =0 ;
  1369. DWORD dwCount=0;
  1370. IDataObject *pdo = NULL;
  1371. PDS_SELECTION_LIST pDsSelList=NULL;
  1372. WCHAR wszWinNT[]=L"WinNT://";
  1373. STGMEDIUM stgmedium =
  1374. {
  1375. TYMED_HGLOBAL,
  1376. NULL,
  1377. NULL
  1378. };
  1379. FORMATETC formatetc =
  1380. {
  1381. (CLIPFORMAT)g_cfDsObjectPicker,
  1382. NULL,
  1383. DVASPECT_CONTENT,
  1384. -1,
  1385. TYMED_HGLOBAL
  1386. };
  1387. //input check
  1388. if((NULL == ppwszSelectedUserSAM) || (NULL == ppwszSelectedUserUPN))
  1389. goto InvalidArgErr;
  1390. *ppwszSelectedUserSAM = NULL;
  1391. *ppwszSelectedUserUPN = NULL;
  1392. if(NULL == pDsObjectPicker)
  1393. goto InvalidArgErr;
  1394. if(S_OK != (hr = pDsObjectPicker->InvokeDialog(NULL, &pdo)))
  1395. goto SetErr;
  1396. if(S_OK != (hr = pdo->GetData(&formatetc, &stgmedium)))
  1397. goto SetErr;
  1398. fGotStgMedium = TRUE;
  1399. pDsSelList = (PDS_SELECTION_LIST)GlobalLock(stgmedium.hGlobal);
  1400. if(!pDsSelList)
  1401. goto TraceErr;
  1402. //Get the SAM name
  1403. if((pDsSelList->aDsSelection[0]).pwzADsPath == NULL)
  1404. goto UnexpectedErr;
  1405. //the ADsPath is in the form of "WinNT://"
  1406. if(wcslen((pDsSelList->aDsSelection[0]).pwzADsPath) <= wcslen(wszWinNT))
  1407. goto UnexpectedErr;
  1408. if( 0 != _wcsnicmp((pDsSelList->aDsSelection[0]).pwzADsPath, wszWinNT, wcslen(wszWinNT)))
  1409. goto UnexpectedErr;
  1410. pwszPath = ((pDsSelList->aDsSelection[0]).pwzADsPath) + wcslen(wszWinNT);
  1411. *ppwszSelectedUserSAM=CopyWideString(pwszPath);
  1412. if(NULL == (*ppwszSelectedUserSAM))
  1413. goto MemoryErr;
  1414. //search for the "/" and make it "\". Since the ADsPath is in the form
  1415. //of "WinNT://domain/name". We need the SAM name in the form of
  1416. //domain\name
  1417. dwCount = wcslen(*ppwszSelectedUserSAM);
  1418. for(dwIndex = 0; dwIndex < dwCount; dwIndex++)
  1419. {
  1420. if((*ppwszSelectedUserSAM)[dwIndex] == L'/')
  1421. {
  1422. (*ppwszSelectedUserSAM)[dwIndex] = L'\\';
  1423. break;
  1424. }
  1425. }
  1426. //get the UPN name
  1427. if((pDsSelList->aDsSelection[0]).pwzUPN != NULL)
  1428. {
  1429. if(0 != _wcsicmp(L"",(pDsSelList->aDsSelection[0]).pwzUPN))
  1430. {
  1431. *ppwszSelectedUserUPN= CopyWideString((pDsSelList->aDsSelection[0]).pwzUPN);
  1432. if(NULL == (*ppwszSelectedUserUPN))
  1433. goto MemoryErr;
  1434. //if we already have a UPN name, get the SAM name from TraslateName
  1435. if(*ppwszSelectedUserSAM)
  1436. {
  1437. SCrdEnrollFree(*ppwszSelectedUserSAM);
  1438. *ppwszSelectedUserSAM=NULL;
  1439. }
  1440. if(!GetName(*ppwszSelectedUserUPN,
  1441. NameUserPrincipal,
  1442. NameSamCompatible,
  1443. ppwszSelectedUserSAM))
  1444. goto TraceErr;
  1445. }
  1446. }
  1447. hr=S_OK;
  1448. CommonReturn:
  1449. if(pDsSelList)
  1450. GlobalUnlock(stgmedium.hGlobal);
  1451. if (TRUE == fGotStgMedium)
  1452. ReleaseStgMedium(&stgmedium);
  1453. if(pdo)
  1454. pdo->Release();
  1455. SetLastError(errBefore);
  1456. return hr;
  1457. ErrorReturn:
  1458. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1459. errBefore=E_UNEXPECTED;
  1460. hr = CodeToHR(errBefore);
  1461. //we should free the memory for the output
  1462. if(ppwszSelectedUserSAM)
  1463. {
  1464. if(*ppwszSelectedUserSAM)
  1465. {
  1466. SCrdEnrollFree(*ppwszSelectedUserSAM);
  1467. *ppwszSelectedUserSAM=NULL;
  1468. }
  1469. }
  1470. if(ppwszSelectedUserUPN)
  1471. {
  1472. if(*ppwszSelectedUserUPN)
  1473. {
  1474. SCrdEnrollFree(*ppwszSelectedUserUPN);
  1475. *ppwszSelectedUserUPN=NULL;
  1476. }
  1477. }
  1478. goto CommonReturn;
  1479. SET_ERROR_VAR(SetErr, hr);
  1480. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1481. TRACE_ERROR(TraceErr);
  1482. SET_ERROR(UnexpectedErr, E_UNEXPECTED);
  1483. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1484. }
  1485. //-----------------------------------------------------------------------
  1486. //
  1487. // CodeToHR
  1488. //
  1489. //------------------------------------------------------------------------
  1490. HRESULT CodeToHR(HRESULT hr)
  1491. {
  1492. if (S_OK != hr && S_FALSE != hr &&
  1493. (!FAILED(hr) || 0x0 == (LONG)HRESULT_FACILITY(hr)))
  1494. {
  1495. hr = HRESULT_FROM_WIN32(hr);
  1496. if (0x0 == (LONG)HRESULT_CODE(hr))
  1497. {
  1498. // A call failed without properly setting an error condition!
  1499. hr = E_UNEXPECTED;
  1500. }
  1501. }
  1502. return(hr);
  1503. }
  1504. //-----------------------------------------------------------------------
  1505. //
  1506. // ValidCSP
  1507. //
  1508. //------------------------------------------------------------------------
  1509. BOOL ValidCSP(DWORD dwProviderType, LPWSTR pwszName)
  1510. {
  1511. HCRYPTPROV hProv=NULL;
  1512. BOOL fValid=FALSE;
  1513. DWORD dwImpType=0;
  1514. DWORD dwSize=sizeof(dwImpType);
  1515. if(CryptAcquireContextU(&hProv,
  1516. NULL,
  1517. pwszName,
  1518. dwProviderType,
  1519. CRYPT_VERIFYCONTEXT))
  1520. {
  1521. if(CryptGetProvParam(hProv,
  1522. PP_IMPTYPE,
  1523. (BYTE *)(&dwImpType),
  1524. &dwSize,
  1525. 0))
  1526. {
  1527. if(CRYPT_IMPL_REMOVABLE & dwImpType)
  1528. fValid=TRUE;
  1529. }
  1530. }
  1531. if(hProv)
  1532. CryptReleaseContext(hProv, 0);
  1533. return fValid;
  1534. }
  1535. //-----------------------------------------------------------------------
  1536. //
  1537. // InitlializeCSPList
  1538. //
  1539. //------------------------------------------------------------------------
  1540. BOOL InitlializeCSPList(DWORD *pdwCSPCount, SCrdEnroll_CSP_INFO **prgCSPInfo)
  1541. {
  1542. BOOL fResult=FALSE;
  1543. DWORD errBefore= GetLastError();
  1544. DWORD dwIndex=0;
  1545. DWORD dwProviderType=0;
  1546. DWORD cbSize=0;
  1547. SCrdEnroll_CSP_INFO *rgCSPInfo=NULL;
  1548. LPWSTR pwszName=NULL;
  1549. *pdwCSPCount=0;
  1550. *prgCSPInfo=NULL;
  1551. while(CryptEnumProvidersU(
  1552. dwIndex,
  1553. 0,
  1554. 0,
  1555. &dwProviderType,
  1556. NULL,
  1557. &cbSize))
  1558. {
  1559. pwszName=(LPWSTR)SCrdEnrollAlloc(cbSize);
  1560. if(NULL==pwszName)
  1561. goto MemoryErr;
  1562. if(!CryptEnumProvidersU(
  1563. dwIndex,
  1564. 0,
  1565. 0,
  1566. &dwProviderType,
  1567. pwszName,
  1568. &cbSize))
  1569. goto TraceErr;
  1570. if(ValidCSP(dwProviderType, pwszName))
  1571. {
  1572. rgCSPInfo=(SCrdEnroll_CSP_INFO *)SCrdEnrollRealloc(*prgCSPInfo,
  1573. ((*pdwCSPCount) + 1) * sizeof(SCrdEnroll_CSP_INFO));
  1574. if(NULL==rgCSPInfo)
  1575. goto MemoryErr;
  1576. *prgCSPInfo=rgCSPInfo;
  1577. memset(&(*prgCSPInfo)[*pdwCSPCount], 0, sizeof(SCrdEnroll_CSP_INFO));
  1578. (*prgCSPInfo)[*pdwCSPCount].pwszCSPName=pwszName;
  1579. pwszName=NULL;
  1580. (*prgCSPInfo)[*pdwCSPCount].dwCSPType=dwProviderType;
  1581. (*pdwCSPCount)++;
  1582. }
  1583. else
  1584. {
  1585. SCrdEnrollFree(pwszName);
  1586. pwszName=NULL;
  1587. }
  1588. dwIndex++;
  1589. dwProviderType=0;
  1590. cbSize=0;
  1591. }
  1592. if((*pdwCSPCount == 0) || (*prgCSPInfo == NULL))
  1593. goto NoItemErr;
  1594. fResult=TRUE;
  1595. CommonReturn:
  1596. if(pwszName)
  1597. SCrdEnrollFree(pwszName);
  1598. SetLastError(errBefore);
  1599. return fResult;
  1600. ErrorReturn:
  1601. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1602. errBefore=E_UNEXPECTED;
  1603. //we need to free all the memory
  1604. FreeCSPInfo(*pdwCSPCount, *prgCSPInfo);
  1605. *pdwCSPCount=0;
  1606. *prgCSPInfo=NULL;
  1607. goto CommonReturn;
  1608. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1609. TRACE_ERROR(TraceErr);
  1610. SET_ERROR(NoItemErr,ERROR_NO_MORE_ITEMS);
  1611. }
  1612. //-----------------------------------------------------------------------
  1613. //
  1614. // FreeCSPInfo
  1615. //
  1616. //------------------------------------------------------------------------
  1617. void FreeCSPInfo(DWORD dwCSPCount, SCrdEnroll_CSP_INFO *prgCSPInfo)
  1618. {
  1619. DWORD dwIndex=0;
  1620. if(prgCSPInfo)
  1621. {
  1622. for(dwIndex=0; dwIndex < dwCSPCount; dwIndex++)
  1623. {
  1624. if(prgCSPInfo[dwIndex].pwszCSPName)
  1625. SCrdEnrollFree(prgCSPInfo[dwIndex].pwszCSPName);
  1626. }
  1627. SCrdEnrollFree(prgCSPInfo);
  1628. }
  1629. }
  1630. //-----------------------------------------------------------------------
  1631. //
  1632. // FreeCAInfoElement
  1633. //
  1634. //------------------------------------------------------------------------
  1635. void FreeCAInfoElement(SCrdEnroll_CA_INFO *pCAInfo)
  1636. {
  1637. if(pCAInfo)
  1638. {
  1639. if(pCAInfo->pwszCAName)
  1640. SCrdEnrollFree(pCAInfo->pwszCAName);
  1641. if(pCAInfo->pwszCALocation)
  1642. SCrdEnrollFree(pCAInfo->pwszCALocation);
  1643. if(pCAInfo->pwszCADisplayName)
  1644. SCrdEnrollFree(pCAInfo->pwszCADisplayName);
  1645. memset(pCAInfo, 0, sizeof(SCrdEnroll_CA_INFO));
  1646. }
  1647. }
  1648. //-----------------------------------------------------------------------
  1649. //
  1650. // FreeCAInfo
  1651. //
  1652. //------------------------------------------------------------------------
  1653. void FreeCAInfo(DWORD dwCACount, SCrdEnroll_CA_INFO *rgCAInfo)
  1654. {
  1655. DWORD dwIndex=0;
  1656. if(rgCAInfo)
  1657. {
  1658. for(dwIndex=0; dwIndex < dwCACount; dwIndex++)
  1659. FreeCAInfoElement(&(rgCAInfo[dwIndex]));
  1660. SCrdEnrollFree(rgCAInfo);
  1661. }
  1662. }
  1663. //-----------------------------------------------------------------------
  1664. //
  1665. // FreeCTInfoElement
  1666. //
  1667. //------------------------------------------------------------------------
  1668. void FreeCTInfoElement(SCrdEnroll_CT_INFO * pCTInfo)
  1669. {
  1670. if(pCTInfo)
  1671. {
  1672. if(pCTInfo->pCertTypeExtensions)
  1673. CAFreeCertTypeExtensions(NULL,pCTInfo->pCertTypeExtensions);
  1674. if(pCTInfo->pwszCTName)
  1675. SCrdEnrollFree(pCTInfo->pwszCTName);
  1676. if(pCTInfo->pwszCTDisplayName)
  1677. SCrdEnrollFree(pCTInfo->pwszCTDisplayName);
  1678. if(pCTInfo->rgCAInfo)
  1679. FreeCAInfo(pCTInfo->dwCACount, pCTInfo->rgCAInfo);
  1680. if (NULL != pCTInfo->rgpwszSupportedCSPs)
  1681. {
  1682. SCrdEnrollFree(pCTInfo->rgpwszSupportedCSPs);
  1683. }
  1684. memset(pCTInfo, 0, sizeof(SCrdEnroll_CT_INFO));
  1685. }
  1686. }
  1687. //-----------------------------------------------------------------------
  1688. //
  1689. // FreeCTInfo(DWORD dwCTCount, SCrdEnroll_CT_INFO *rgCTInfo);
  1690. //
  1691. //------------------------------------------------------------------------
  1692. void FreeCTInfo(DWORD dwCTCount, SCrdEnroll_CT_INFO *rgCTInfo)
  1693. {
  1694. DWORD dwIndex=0;
  1695. if(rgCTInfo)
  1696. {
  1697. for(dwIndex=0; dwIndex < dwCTCount; dwIndex++)
  1698. FreeCTInfoElement(&(rgCTInfo[dwIndex]));
  1699. SCrdEnrollFree(rgCTInfo);
  1700. }
  1701. }
  1702. //-----------------------------------------------------------------------
  1703. //
  1704. // GetCertTypeProperties
  1705. //
  1706. //------------------------------------------------------------------------
  1707. BOOL GetCertTypeProperties(HCERTTYPE hCurCertType,
  1708. SCrdEnroll_CT_INFO *pCertInfo)
  1709. {
  1710. BOOL fResult=FALSE;
  1711. DWORD errBefore= GetLastError();
  1712. HRESULT hr=S_OK;
  1713. DWORD dwCertType=0;
  1714. DWORD dwMinKeySize;
  1715. DWORD dwEnrollmentFlags;
  1716. DWORD dwSubjectNameFlags;
  1717. DWORD dwPrivateKeyFlags;
  1718. DWORD dwGeneralFlags;
  1719. DWORD dwGenKeyFlags;
  1720. LPWSTR *rgpwszSupportedCSPs = NULL;
  1721. LPWSTR *ppwszDisplayCertTypeName=NULL;
  1722. LPWSTR *ppwszCertTypeName=NULL;
  1723. if((NULL==pCertInfo) || (NULL == hCurCertType))
  1724. goto InvalidArgErr;
  1725. //
  1726. // Get all of the cert type flags.
  1727. //
  1728. // Get enrollment flags:
  1729. if (S_OK != (hr=MyCAGetCertTypeFlagsEx
  1730. (hCurCertType,
  1731. CERTTYPE_ENROLLMENT_FLAG,
  1732. &pCertInfo->dwEnrollmentFlags)))
  1733. goto CertCliErr;
  1734. // Get subject name flags:
  1735. if (S_OK != (hr=MyCAGetCertTypeFlagsEx
  1736. (hCurCertType,
  1737. CERTTYPE_SUBJECT_NAME_FLAG,
  1738. &pCertInfo->dwSubjectNameFlags)))
  1739. goto CertCliErr;
  1740. // Get private key flags.
  1741. if(S_OK != (hr = MyCAGetCertTypeFlagsEx
  1742. (hCurCertType,
  1743. CERTTYPE_PRIVATE_KEY_FLAG,
  1744. &pCertInfo->dwPrivateKeyFlags)))
  1745. goto CertCliErr;
  1746. // Get general flags:
  1747. if (S_OK != (hr=MyCAGetCertTypeFlagsEx
  1748. (hCurCertType,
  1749. CERTTYPE_GENERAL_FLAG,
  1750. &pCertInfo->dwGeneralFlags)))
  1751. goto CertCliErr;
  1752. //detremine machine boolean flag
  1753. pCertInfo->fMachine = (0x0 != (pCertInfo->dwGeneralFlags & CT_FLAG_MACHINE_TYPE)) ? TRUE : FALSE;
  1754. // Extract gen key flags from the type flags.
  1755. dwGenKeyFlags = 0;
  1756. if (!(CertTypeFlagsToGenKeyFlags
  1757. (pCertInfo->dwEnrollmentFlags,
  1758. pCertInfo->dwSubjectNameFlags,
  1759. pCertInfo->dwPrivateKeyFlags,
  1760. pCertInfo->dwGeneralFlags,
  1761. &pCertInfo->dwGenKeyFlags)))
  1762. goto CertCliErr;
  1763. // Get key spec:
  1764. if(S_OK != (hr= CAGetCertTypeKeySpec(hCurCertType, &(pCertInfo->dwKeySpec))))
  1765. goto CertCliErr;
  1766. //get the display name of the cert type
  1767. hr=CAGetCertTypeProperty(
  1768. hCurCertType,
  1769. CERTTYPE_PROP_FRIENDLY_NAME,
  1770. &ppwszDisplayCertTypeName);
  1771. if(S_OK != hr || NULL==ppwszDisplayCertTypeName)
  1772. {
  1773. if(S_OK == hr)
  1774. hr=E_FAIL;
  1775. goto CertCliErr;
  1776. }
  1777. //copy the name
  1778. pCertInfo->pwszCTDisplayName=CopyWideString(ppwszDisplayCertTypeName[0]);
  1779. if(NULL==(pCertInfo->pwszCTDisplayName))
  1780. goto MemoryErr;
  1781. //get the machine readable name of the cert type
  1782. hr=CAGetCertTypeProperty(
  1783. hCurCertType,
  1784. CERTTYPE_PROP_DN,
  1785. &ppwszCertTypeName);
  1786. if(S_OK != hr || NULL==ppwszCertTypeName)
  1787. {
  1788. if(S_OK == hr)
  1789. hr=E_FAIL;
  1790. goto CertCliErr;
  1791. }
  1792. //copy the name
  1793. pCertInfo->pwszCTName=CopyWideString(ppwszCertTypeName[0]);
  1794. if(NULL==(pCertInfo->pwszCTName))
  1795. goto MemoryErr;
  1796. //copy the certType extensions
  1797. if(S_OK != (hr=CAGetCertTypeExtensions(
  1798. hCurCertType,
  1799. &(pCertInfo->pCertTypeExtensions))))
  1800. goto CertCliErr;
  1801. //copy csp list supported by template
  1802. hr = CAGetCertTypeProperty(
  1803. hCurCertType,
  1804. CERTTYPE_PROP_CSP_LIST,
  1805. &rgpwszSupportedCSPs);
  1806. if (S_OK != hr)
  1807. {
  1808. goto CertCliErr;
  1809. }
  1810. pCertInfo->rgpwszSupportedCSPs = CopyWideStrings(rgpwszSupportedCSPs);
  1811. if (NULL == pCertInfo->rgpwszSupportedCSPs)
  1812. {
  1813. goto MemoryErr;
  1814. }
  1815. pCertInfo->dwCurrentCSP = 0; //first one
  1816. //
  1817. // Set V2 properties.
  1818. // If we're dealing with a v2 cert type, add v2 properties.
  1819. // Otherwise, insert defaults.
  1820. //
  1821. if (S_OK != (hr=MyCAGetCertTypePropertyEx
  1822. (hCurCertType,
  1823. CERTTYPE_PROP_SCHEMA_VERSION,
  1824. &dwCertType)))
  1825. goto CertCliErr;
  1826. if (dwCertType == CERTTYPE_SCHEMA_VERSION_1)
  1827. {
  1828. // Just a v1 cert type, it won't have v2 properties.
  1829. // Set left half-word of the type flags to 0. This means that
  1830. // that the min key size is not specified.
  1831. pCertInfo->dwGenKeyFlags &= 0x0000FFFF;
  1832. pCertInfo->dwRASignature = 0;
  1833. }
  1834. else // We must have a v2 (or greater) cert type.
  1835. {
  1836. // Get the minimum key size of the cert type
  1837. if (S_OK != (hr=MyCAGetCertTypePropertyEx
  1838. (hCurCertType,
  1839. CERTTYPE_PROP_MIN_KEY_SIZE,
  1840. (LPVOID)&dwMinKeySize)))
  1841. goto CertCliErr;
  1842. // store the minimum key size in the left half-word of the
  1843. // type flags.
  1844. pCertInfo->dwGenKeyFlags =
  1845. (dwMinKeySize << 16) | (pCertInfo->dwGenKeyFlags & 0x0000FFFF) ;
  1846. // Get the number of RA signatures required for this cert type.
  1847. if (S_OK != (hr=MyCAGetCertTypePropertyEx
  1848. (hCurCertType,
  1849. CERTTYPE_PROP_RA_SIGNATURE,
  1850. (LPVOID)(&pCertInfo->dwRASignature))))
  1851. goto CertCliErr;
  1852. }
  1853. fResult=TRUE;
  1854. CommonReturn:
  1855. if(ppwszDisplayCertTypeName)
  1856. CAFreeCertTypeProperty(hCurCertType, ppwszDisplayCertTypeName);
  1857. if(ppwszCertTypeName)
  1858. CAFreeCertTypeProperty(hCurCertType, ppwszCertTypeName);
  1859. if (NULL != rgpwszSupportedCSPs)
  1860. {
  1861. CAFreeCertTypeProperty(hCurCertType, rgpwszSupportedCSPs);
  1862. }
  1863. SetLastError(errBefore);
  1864. return fResult;
  1865. ErrorReturn:
  1866. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1867. errBefore=E_UNEXPECTED;
  1868. //in error case, free the memory and memset to 0
  1869. if(pCertInfo)
  1870. FreeCTInfoElement(pCertInfo);
  1871. goto CommonReturn;
  1872. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1873. SET_ERROR_VAR(CertCliErr, hr);
  1874. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1875. }
  1876. //--------------------------------------------------------------------
  1877. //
  1878. // IsMachineCertType
  1879. //
  1880. //--------------------------------------------------------------------
  1881. BOOL IsMachineCertType(HCERTTYPE hCertType)
  1882. {
  1883. DWORD dwCertType=0;
  1884. if(S_OK != CAGetCertTypeFlags(hCertType, &dwCertType))
  1885. return FALSE;
  1886. if(CT_FLAG_MACHINE_TYPE & dwCertType)
  1887. return TRUE;
  1888. return FALSE;
  1889. }
  1890. //-----------------------------------------------------------------------
  1891. // Get a list of allowed cert types
  1892. //
  1893. //------------------------------------------------------------------------
  1894. /*BOOL GetAllowedCertTypeName(LPWSTR **pawszAllowedCertTypes)
  1895. {
  1896. DWORD dwErr=0;
  1897. KEYSVC_TYPE dwServiceType=KeySvcMachine;
  1898. DWORD cTypes=0;
  1899. DWORD dwSize=0;
  1900. CHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1]={0};
  1901. DWORD cbArray = 0;
  1902. DWORD i=0;
  1903. LPWSTR wszCurrentType;
  1904. BOOL fResult=FALSE;
  1905. KEYSVCC_HANDLE hKeyService=NULL;
  1906. PKEYSVC_UNICODE_STRING pCertTypes = NULL;
  1907. dwSize=sizeof(szComputerName);
  1908. if(0==GetComputerNameA(szComputerName, &dwSize))
  1909. goto TraceErr;
  1910. dwErr = KeyOpenKeyService(szComputerName,
  1911. dwServiceType,
  1912. NULL,
  1913. NULL, // no authentication string right now
  1914. NULL,
  1915. &hKeyService);
  1916. if(dwErr != ERROR_SUCCESS)
  1917. {
  1918. SetLastError(dwErr);
  1919. goto TraceErr;
  1920. }
  1921. dwErr = KeyEnumerateAvailableCertTypes(hKeyService,
  1922. NULL,
  1923. &cTypes,
  1924. &pCertTypes);
  1925. if(dwErr != ERROR_SUCCESS)
  1926. {
  1927. SetLastError(dwErr);
  1928. goto TraceErr;
  1929. }
  1930. cbArray = (cTypes+1)*sizeof(LPWSTR);
  1931. // Convert into a simple array
  1932. for(i=0; i < cTypes; i++)
  1933. {
  1934. cbArray += pCertTypes[i].Length;
  1935. }
  1936. *pawszAllowedCertTypes = (LPWSTR *)SCrdEnrollAlloc(cbArray);
  1937. if(*pawszAllowedCertTypes == NULL)
  1938. goto MemoryErr;
  1939. memset(*pawszAllowedCertTypes, 0, cbArray);
  1940. wszCurrentType = (LPWSTR)(&((*pawszAllowedCertTypes)[cTypes + 1]));
  1941. for(i=0; i < cTypes; i++)
  1942. {
  1943. (*pawszAllowedCertTypes)[i] = wszCurrentType;
  1944. wcscpy(wszCurrentType, pCertTypes[i].Buffer);
  1945. wszCurrentType += wcslen(wszCurrentType)+1;
  1946. }
  1947. fResult=TRUE;
  1948. CommonReturn:
  1949. //memory from the KeyService
  1950. if(pCertTypes)
  1951. LocalFree((HLOCAL)pCertTypes);
  1952. if(hKeyService)
  1953. KeyCloseKeyService(hKeyService, NULL);
  1954. return fResult;
  1955. ErrorReturn:
  1956. fResult=FALSE;
  1957. goto CommonReturn;
  1958. TRACE_ERROR(TraceErr);
  1959. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1960. } */
  1961. //--------------------------------------------------------------------
  1962. //
  1963. // CheckAccessPermission
  1964. //
  1965. //--------------------------------------------------------------------
  1966. BOOL CheckAccessPermission(HCERTTYPE hCertType)
  1967. {
  1968. //make sure the principal making this call has access to request
  1969. //this cert type, even if he's requesting on behalf of another.
  1970. //
  1971. HRESULT hr = S_OK;
  1972. HANDLE hHandle = NULL;
  1973. HANDLE hClientToken = NULL;
  1974. hHandle = GetCurrentThread();
  1975. if (NULL == hHandle)
  1976. {
  1977. hr = HRESULT_FROM_WIN32(GetLastError());
  1978. }
  1979. else
  1980. {
  1981. if (!OpenThreadToken(hHandle,
  1982. TOKEN_QUERY,
  1983. TRUE, // open as self
  1984. &hClientToken))
  1985. {
  1986. hr = HRESULT_FROM_WIN32(GetLastError());
  1987. CloseHandle(hHandle);
  1988. hHandle = NULL;
  1989. }
  1990. }
  1991. if(hr != S_OK)
  1992. {
  1993. hHandle = GetCurrentProcess();
  1994. if (NULL == hHandle)
  1995. {
  1996. hr = HRESULT_FROM_WIN32(GetLastError());
  1997. }
  1998. else
  1999. {
  2000. HANDLE hProcessToken = NULL;
  2001. hr = S_OK;
  2002. if (!OpenProcessToken(hHandle,
  2003. TOKEN_DUPLICATE,
  2004. &hProcessToken))
  2005. {
  2006. hr = HRESULT_FROM_WIN32(GetLastError());
  2007. CloseHandle(hHandle);
  2008. hHandle = NULL;
  2009. }
  2010. else
  2011. {
  2012. if(!DuplicateToken(hProcessToken,
  2013. SecurityImpersonation,
  2014. &hClientToken))
  2015. {
  2016. hr = HRESULT_FROM_WIN32(GetLastError());
  2017. CloseHandle(hHandle);
  2018. hHandle = NULL;
  2019. }
  2020. CloseHandle(hProcessToken);
  2021. }
  2022. }
  2023. }
  2024. if(hr == S_OK)
  2025. {
  2026. hr = CACertTypeAccessCheck(
  2027. hCertType,
  2028. hClientToken);
  2029. CloseHandle(hClientToken);
  2030. }
  2031. if(hHandle)
  2032. {
  2033. CloseHandle(hHandle);
  2034. }
  2035. return (S_OK == hr);
  2036. }
  2037. //--------------------------------------------------------------------
  2038. //
  2039. // TokenCheckAccessPermission
  2040. //
  2041. //--------------------------------------------------------------------
  2042. BOOL TokenCheckAccessPermission(HANDLE hToken, HCERTTYPE hCertType)
  2043. {
  2044. HRESULT hr=E_FAIL;
  2045. if(hToken)
  2046. {
  2047. hr = CACertTypeAccessCheck(
  2048. hCertType,
  2049. hToken);
  2050. return (S_OK == hr);
  2051. }
  2052. return CheckAccessPermission(hCertType);
  2053. }
  2054. //--------------------------------------------------------------------
  2055. //
  2056. // CheckCAPermission
  2057. //
  2058. //--------------------------------------------------------------------
  2059. BOOL CheckCAPermission(HCAINFO hCAInfo)
  2060. {
  2061. //make sure the principal making this call has access to request
  2062. //this cert type, even if he's requesting on behalf of another.
  2063. //
  2064. HRESULT hr = S_OK;
  2065. HANDLE hHandle = NULL;
  2066. HANDLE hClientToken = NULL;
  2067. hHandle = GetCurrentThread();
  2068. if (NULL == hHandle)
  2069. {
  2070. hr = HRESULT_FROM_WIN32(GetLastError());
  2071. }
  2072. else
  2073. {
  2074. if (!OpenThreadToken(hHandle,
  2075. TOKEN_QUERY,
  2076. TRUE, // open as self
  2077. &hClientToken))
  2078. {
  2079. hr = HRESULT_FROM_WIN32(GetLastError());
  2080. CloseHandle(hHandle);
  2081. hHandle = NULL;
  2082. }
  2083. }
  2084. if(hr != S_OK)
  2085. {
  2086. hHandle = GetCurrentProcess();
  2087. if (NULL == hHandle)
  2088. {
  2089. hr = HRESULT_FROM_WIN32(GetLastError());
  2090. }
  2091. else
  2092. {
  2093. HANDLE hProcessToken = NULL;
  2094. hr = S_OK;
  2095. if (!OpenProcessToken(hHandle,
  2096. TOKEN_DUPLICATE,
  2097. &hProcessToken))
  2098. {
  2099. hr = HRESULT_FROM_WIN32(GetLastError());
  2100. CloseHandle(hHandle);
  2101. hHandle = NULL;
  2102. }
  2103. else
  2104. {
  2105. if(!DuplicateToken(hProcessToken,
  2106. SecurityImpersonation,
  2107. &hClientToken))
  2108. {
  2109. hr = HRESULT_FROM_WIN32(GetLastError());
  2110. CloseHandle(hHandle);
  2111. hHandle = NULL;
  2112. }
  2113. CloseHandle(hProcessToken);
  2114. }
  2115. }
  2116. }
  2117. if(hr == S_OK)
  2118. {
  2119. hr = CAAccessCheck(
  2120. hCAInfo,
  2121. hClientToken);
  2122. CloseHandle(hClientToken);
  2123. }
  2124. if(hHandle)
  2125. {
  2126. CloseHandle(hHandle);
  2127. }
  2128. return (S_OK == hr);
  2129. }
  2130. //--------------------------------------------------------------------
  2131. //
  2132. // TokenCheckCAPermission
  2133. //
  2134. //--------------------------------------------------------------------
  2135. BOOL TokenCheckCAPermission(HANDLE hToken, HCAINFO hCAInfo)
  2136. {
  2137. HRESULT hr=E_FAIL;
  2138. if(hToken)
  2139. {
  2140. hr = CAAccessCheck(
  2141. hCAInfo,
  2142. hToken);
  2143. return (S_OK == hr);
  2144. }
  2145. return CheckCAPermission(hCAInfo);
  2146. }
  2147. //--------------------------------------------------------------------
  2148. //
  2149. // CheckSubjectRequirement
  2150. //
  2151. //--------------------------------------------------------------------
  2152. /*BOOL CheckSubjectRequirement(HCERTTYPE hCurCertType)
  2153. {
  2154. DWORD dwFlags=0;
  2155. //check the subject requirement of the cert type
  2156. if(S_OK != CAGetCertTypeFlags(hCurCertType, &dwFlags))
  2157. return FALSE;
  2158. if(CT_FLAG_IS_SUBJECT_REQ & dwFlags)
  2159. return FALSE;
  2160. return TRUE;
  2161. } */
  2162. //-----------------------------------------------------------------------
  2163. //
  2164. // GetCAProperties
  2165. //
  2166. //------------------------------------------------------------------------
  2167. BOOL GetCAProperties(HCAINFO hCurCAInfo,
  2168. SCrdEnroll_CA_INFO *pCAInfo)
  2169. {
  2170. BOOL fResult=FALSE;
  2171. DWORD errBefore= GetLastError();
  2172. HRESULT hr=S_OK;
  2173. LPWSTR *ppwszNameProp=NULL;
  2174. LPWSTR *ppwszLocationProp=NULL;
  2175. LPWSTR *ppwszDisplayNameProp=NULL;
  2176. //get the CAName
  2177. hr=CAGetCAProperty(
  2178. hCurCAInfo,
  2179. CA_PROP_NAME,
  2180. &ppwszNameProp);
  2181. if((S_OK != hr) || (NULL==ppwszNameProp))
  2182. {
  2183. if(!FAILED(hr))
  2184. hr=E_FAIL;
  2185. goto CertCliErr;
  2186. }
  2187. pCAInfo->pwszCAName=CopyWideString(ppwszNameProp[0]);
  2188. if(NULL == pCAInfo->pwszCAName)
  2189. goto MemoryErr;
  2190. //get the CADisplayName
  2191. hr=CAGetCAProperty(
  2192. hCurCAInfo,
  2193. CA_PROP_DISPLAY_NAME,
  2194. &ppwszDisplayNameProp);
  2195. if((S_OK != hr) || (NULL==ppwszDisplayNameProp))
  2196. {
  2197. if(!FAILED(hr))
  2198. hr=E_FAIL;
  2199. goto CertCliErr;
  2200. }
  2201. pCAInfo->pwszCADisplayName=CopyWideString(ppwszDisplayNameProp[0]);
  2202. if(NULL == pCAInfo->pwszCADisplayName)
  2203. goto MemoryErr;
  2204. //get the CA location
  2205. hr=CAGetCAProperty(
  2206. hCurCAInfo,
  2207. CA_PROP_DNSNAME,
  2208. &ppwszLocationProp);
  2209. if((S_OK != hr) || (NULL==ppwszLocationProp))
  2210. {
  2211. if(!FAILED(hr))
  2212. hr=E_FAIL;
  2213. goto CertCliErr;
  2214. }
  2215. //copy the name
  2216. pCAInfo->pwszCALocation=CopyWideString(ppwszLocationProp[0]);
  2217. if(NULL == pCAInfo->pwszCALocation)
  2218. goto MemoryErr;
  2219. fResult=TRUE;
  2220. CommonReturn:
  2221. if(ppwszNameProp)
  2222. CAFreeCAProperty(hCurCAInfo, ppwszNameProp);
  2223. if(ppwszLocationProp)
  2224. CAFreeCAProperty(hCurCAInfo, ppwszLocationProp);
  2225. if(ppwszDisplayNameProp)
  2226. CAFreeCAProperty(hCurCAInfo, ppwszDisplayNameProp);
  2227. SetLastError(errBefore);
  2228. return fResult;
  2229. ErrorReturn:
  2230. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  2231. errBefore=E_UNEXPECTED;
  2232. //in error case, free the memory and memset to 0
  2233. if(pCAInfo)
  2234. FreeCAInfoElement(pCAInfo);
  2235. goto CommonReturn;
  2236. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2237. SET_ERROR_VAR(CertCliErr, hr);
  2238. }
  2239. //-----------------------------------------------------------------------
  2240. //
  2241. // GetCAInfoFromCertType
  2242. //
  2243. //------------------------------------------------------------------------
  2244. BOOL GetCAInfoFromCertType(HANDLE hToken,
  2245. LPWSTR pwszCTName,
  2246. DWORD *pdwValidCA,
  2247. SCrdEnroll_CA_INFO **prgCAInfo)
  2248. {
  2249. BOOL fResult=FALSE;
  2250. HRESULT hr=S_OK;
  2251. DWORD errBefore= GetLastError();
  2252. DWORD dwCACount=0;
  2253. DWORD dwValidCA=0;
  2254. SCrdEnroll_CA_INFO *rgCAInfo=NULL;
  2255. HCAINFO hCurCAInfo=NULL;
  2256. HCAINFO hPreCAInfo=NULL;
  2257. //init
  2258. *pdwValidCA=0;
  2259. *prgCAInfo=NULL;
  2260. if(NULL == pwszCTName)
  2261. goto InvalidArgErr;
  2262. hr = CAFindByCertType(
  2263. pwszCTName,
  2264. NULL,
  2265. 0,
  2266. &hCurCAInfo);
  2267. if( hr!=S_OK || NULL==hCurCAInfo)
  2268. {
  2269. if(S_OK == hr)
  2270. hr=E_FAIL;
  2271. goto CertCliErr;
  2272. }
  2273. //get the CA count
  2274. dwCACount=CACountCAs(hCurCAInfo);
  2275. if(0==dwCACount)
  2276. {
  2277. hr=E_FAIL;
  2278. goto CertCliErr;
  2279. }
  2280. //allocate memory
  2281. rgCAInfo=(SCrdEnroll_CA_INFO *)SCrdEnrollAlloc(dwCACount *
  2282. sizeof(SCrdEnroll_CA_INFO));
  2283. if(NULL == rgCAInfo)
  2284. goto MemoryErr;
  2285. memset(rgCAInfo, 0, dwCACount * sizeof(SCrdEnroll_CA_INFO));
  2286. dwValidCA=0;
  2287. while(hCurCAInfo)
  2288. {
  2289. //get the CA information
  2290. if(TokenCheckCAPermission(hToken, hCurCAInfo))
  2291. {
  2292. if(GetCAProperties(hCurCAInfo, &(rgCAInfo[dwValidCA])))
  2293. {
  2294. //increment the count
  2295. dwValidCA++;
  2296. }
  2297. }
  2298. //enum for the CA
  2299. hPreCAInfo=hCurCAInfo;
  2300. hr=CAEnumNextCA(
  2301. hPreCAInfo,
  2302. &hCurCAInfo);
  2303. //free the old CA Info
  2304. CACloseCA(hPreCAInfo);
  2305. hPreCAInfo=NULL;
  2306. if((S_OK != hr) || (NULL==hCurCAInfo))
  2307. break;
  2308. }
  2309. if( (0 == dwValidCA) || (NULL == rgCAInfo))
  2310. {
  2311. hr=E_FAIL;
  2312. goto CertCliErr;
  2313. }
  2314. //copy the output data
  2315. *pdwValidCA=dwValidCA;
  2316. *prgCAInfo=rgCAInfo;
  2317. fResult=TRUE;
  2318. CommonReturn:
  2319. if(hPreCAInfo)
  2320. CACloseCA(hPreCAInfo);
  2321. if(hCurCAInfo)
  2322. CACloseCA(hCurCAInfo);
  2323. SetLastError(errBefore);
  2324. return fResult;
  2325. ErrorReturn:
  2326. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  2327. errBefore=E_UNEXPECTED;
  2328. if(rgCAInfo)
  2329. FreeCAInfo(dwValidCA, rgCAInfo);
  2330. //NULL the output
  2331. *pdwValidCA=0;
  2332. *prgCAInfo=NULL;
  2333. goto CommonReturn;
  2334. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2335. SET_ERROR_VAR(CertCliErr, hr);
  2336. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2337. }
  2338. //-----------------------------------------------------------------------
  2339. //
  2340. // InitializeCTList
  2341. //
  2342. //------------------------------------------------------------------------
  2343. BOOL InitializeCTList(DWORD *pdwCTIndex,
  2344. DWORD *pdwCTCount,
  2345. SCrdEnroll_CT_INFO **prgCTInfo)
  2346. {
  2347. BOOL fResult=FALSE;
  2348. HRESULT hr=S_OK;
  2349. DWORD errBefore= GetLastError();
  2350. HCERTTYPE hCurCertType=NULL;
  2351. HCERTTYPE hPreCertType=NULL;
  2352. DWORD dwCertTypeCount=0;
  2353. DWORD dwIndex=0;
  2354. DWORD dwValidCertType=0;
  2355. SCrdEnroll_CT_INFO * rgCTInfo=NULL;
  2356. HANDLE hThread=NULL; //no need to close
  2357. HANDLE hToken=NULL;
  2358. *pdwCTIndex=0;
  2359. *pdwCTCount=0;
  2360. *prgCTInfo=NULL;
  2361. //first of all, we need to revert to ourselves if we are under impersonation
  2362. hThread=GetCurrentThread();
  2363. if(NULL != hThread)
  2364. {
  2365. if(OpenThreadToken(hThread,
  2366. TOKEN_IMPERSONATE | TOKEN_QUERY,
  2367. FALSE,
  2368. &hToken))
  2369. {
  2370. if(hToken)
  2371. {
  2372. //no need to check for return here. If this failed, just go on
  2373. RevertToSelf();
  2374. }
  2375. }
  2376. }
  2377. //get the 1st CT, including both machine and user cert types
  2378. hr=CAEnumCertTypes(CT_ENUM_USER_TYPES | CT_ENUM_MACHINE_TYPES, &hCurCertType);
  2379. if((S_OK != hr) || (NULL==hCurCertType))
  2380. {
  2381. if(S_OK != hr)
  2382. hr=E_FAIL;
  2383. goto CertCliErr;
  2384. }
  2385. //get the count of the cert types supported by this CA
  2386. dwCertTypeCount=CACountCertTypes(hCurCertType);
  2387. if(0==dwCertTypeCount)
  2388. {
  2389. hr=E_FAIL;
  2390. goto CertCliErr;
  2391. }
  2392. //allocate memory
  2393. rgCTInfo=(SCrdEnroll_CT_INFO *)SCrdEnrollAlloc(dwCertTypeCount *
  2394. sizeof(SCrdEnroll_CT_INFO));
  2395. if(NULL == rgCTInfo)
  2396. goto MemoryErr;
  2397. memset(rgCTInfo, 0, dwCertTypeCount * sizeof(SCrdEnroll_CT_INFO));
  2398. dwValidCertType = 0;
  2399. while(hCurCertType)
  2400. {
  2401. if(TokenCheckAccessPermission(hToken, hCurCertType) &&
  2402. GetCertTypeProperties(hCurCertType, &(rgCTInfo[dwValidCertType]))
  2403. )
  2404. {
  2405. dwValidCertType++;
  2406. }
  2407. //enum for the next cert types
  2408. hPreCertType=hCurCertType;
  2409. hr=CAEnumNextCertType(
  2410. hPreCertType,
  2411. &hCurCertType);
  2412. //free the old cert type
  2413. CACloseCertType(hPreCertType);
  2414. hPreCertType=NULL;
  2415. if((S_OK != hr) || (NULL==hCurCertType))
  2416. break;
  2417. }
  2418. //now that we have find all the cert types, we need to find one cert
  2419. //that has the associated CA information
  2420. //if hToken, we are running as the certserv's ASP pages. We need to retrieve all the
  2421. // CA's information since we are in the revert to self mode.
  2422. if(NULL == hToken)
  2423. {
  2424. for(dwIndex=0; dwIndex < dwValidCertType; dwIndex++)
  2425. {
  2426. //we do not consider the machine cert types
  2427. if(TRUE == rgCTInfo[dwIndex].fMachine)
  2428. continue;
  2429. //mark that we have queried the CA information of the
  2430. //certType
  2431. rgCTInfo[dwIndex].fCAInfo=TRUE;
  2432. if(GetCAInfoFromCertType(NULL,
  2433. rgCTInfo[dwIndex].pwszCTName,
  2434. &(rgCTInfo[dwIndex].dwCACount),
  2435. &(rgCTInfo[dwIndex].rgCAInfo)))
  2436. break;
  2437. }
  2438. if(dwIndex == dwValidCertType)
  2439. {
  2440. hr=E_FAIL;
  2441. goto CertCliErr;
  2442. }
  2443. }
  2444. else
  2445. {
  2446. for(dwIndex=0; dwIndex < dwValidCertType; dwIndex++)
  2447. {
  2448. //mark that we have queried the CA information of the
  2449. //certType
  2450. rgCTInfo[dwIndex].fCAInfo=TRUE;
  2451. GetCAInfoFromCertType( hToken,
  2452. rgCTInfo[dwIndex].pwszCTName,
  2453. &(rgCTInfo[dwIndex].dwCACount),
  2454. &(rgCTInfo[dwIndex].rgCAInfo));
  2455. }
  2456. }
  2457. if((0 == dwValidCertType) || (NULL == rgCTInfo))
  2458. {
  2459. hr=E_FAIL;
  2460. goto CertCliErr;
  2461. }
  2462. *pdwCTIndex=dwIndex;
  2463. *pdwCTCount=dwValidCertType;
  2464. *prgCTInfo=rgCTInfo;
  2465. fResult=TRUE;
  2466. CommonReturn:
  2467. if(hPreCertType)
  2468. CACloseCertType(hPreCertType);
  2469. if(hCurCertType)
  2470. CACloseCertType(hCurCertType);
  2471. //if hToken is valid, we reverted to ourselves.
  2472. if(hToken)
  2473. {
  2474. SetThreadToken(&hThread, hToken);
  2475. CloseHandle(hToken);
  2476. }
  2477. SetLastError(errBefore);
  2478. return fResult;
  2479. ErrorReturn:
  2480. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  2481. errBefore=E_UNEXPECTED;
  2482. //free all the memory
  2483. if(rgCTInfo)
  2484. FreeCTInfo(dwValidCertType, rgCTInfo);
  2485. //NULL the output
  2486. *pdwCTIndex=0;
  2487. *pdwCTCount=0;
  2488. *prgCTInfo=NULL;
  2489. goto CommonReturn;
  2490. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2491. SET_ERROR_VAR(CertCliErr, hr);
  2492. }
  2493. //-----------------------------------------------------------------------
  2494. //
  2495. // RetrieveCAName
  2496. //
  2497. //------------------------------------------------------------------------
  2498. BOOL RetrieveCAName(DWORD dwFlags,
  2499. SCrdEnroll_CA_INFO *pCAInfo,
  2500. LPWSTR *ppwszName)
  2501. {
  2502. DWORD dwSize = 0;
  2503. BOOL fResult=FALSE;
  2504. if(NULL == ppwszName)
  2505. goto InvalidArgErr;
  2506. if(dwFlags == SCARD_ENROLL_CA_MACHINE_NAME)
  2507. *ppwszName = CopyWideString(pCAInfo->pwszCALocation);
  2508. else
  2509. {
  2510. if(dwFlags == SCARD_ENROLL_CA_DISPLAY_NAME)
  2511. *ppwszName = CopyWideString(pCAInfo->pwszCADisplayName);
  2512. else
  2513. {
  2514. if(dwFlags == SCARD_ENROLL_CA_UNIQUE_NAME)
  2515. {
  2516. dwSize = wcslen(pCAInfo->pwszCALocation) + wcslen(pCAInfo->pwszCADisplayName) + wcslen(L"\\") + 2;
  2517. *ppwszName = (LPWSTR)SCrdEnrollAlloc(sizeof(WCHAR) * dwSize);
  2518. if(NULL == (*ppwszName))
  2519. goto MemoryErr;
  2520. wcscpy(*ppwszName, pCAInfo->pwszCALocation);
  2521. wcscat(*ppwszName, L"\\");
  2522. wcscat(*ppwszName, pCAInfo->pwszCADisplayName);
  2523. }
  2524. else
  2525. *ppwszName = CopyWideString(pCAInfo->pwszCAName);
  2526. }
  2527. }
  2528. if(NULL == (*ppwszName))
  2529. goto MemoryErr;
  2530. fResult=TRUE;
  2531. CommonReturn:
  2532. return fResult;
  2533. ErrorReturn:
  2534. fResult=FALSE;
  2535. goto CommonReturn;
  2536. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2537. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2538. }