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.

2660 lines
72 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: scrdenr.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // SCrdEnr.cpp : Implementation of CSCrdEnr
  11. #define SECURITY_WIN32 //Or in the sources file -DSECURITY_WIN32
  12. #include "stdafx.h"
  13. #include <windows.h>
  14. #include <wincrypt.h>
  15. #include <unicode.h>
  16. #include <oleauto.h>
  17. #include <objbase.h>
  18. #include <cryptui.h>
  19. #include "certca.h"
  20. #include "certsrv.h"
  21. #include "security.h"
  22. #include <dbgdef.h>
  23. #include "scrdenrl.h"
  24. #include "SCrdEnr.h"
  25. #include "enrlhelp.h"
  26. #include "xEnroll.h"
  27. #include "wzrdpvk.h"
  28. /////////////////////////////////////////////////////////////////////////////
  29. // CSCrdEnr
  30. CSCrdEnr::CSCrdEnr(void)
  31. {
  32. DWORD dwIndex=0;
  33. DSOP_SCOPE_INIT_INFO ScopeInit;
  34. DSOP_INIT_INFO InitInfo;
  35. m_dwCTCount=0;
  36. m_dwCTIndex=0;
  37. m_rgCTInfo=NULL;
  38. m_pwszUserUPN=NULL;
  39. m_pwszUserSAM=NULL;
  40. m_pEnrolledCert=NULL;
  41. m_dwCSPCount=0;
  42. m_dwCSPIndex=0;
  43. m_rgCSPInfo=NULL;
  44. m_lEnrollmentStatus = CR_DISP_INCOMPLETE;
  45. m_pSigningCert=NULL;
  46. m_fSCardSigningCert=FALSE;
  47. m_pszCSPNameSigningCert=NULL;
  48. m_dwCSPTypeSigningCert=0;
  49. m_pszContainerSigningCert=NULL;
  50. m_pDsObjectPicker=NULL;
  51. m_pCachedCTEs = NULL; //no need to free
  52. m_pwszCachedCTEOid = NULL;
  53. m_pCachedCTE = NULL;
  54. // track whether our critsec is initialized
  55. m_fInitializedCriticalSection = FALSE;
  56. if(!FAILED(CoInitialize(NULL)))
  57. m_fInitialize=TRUE;
  58. // Initialize functions who's loading we've deferred.
  59. InitializeThunks();
  60. __try
  61. {
  62. InitializeCriticalSection(&m_cSection);
  63. m_fInitializedCriticalSection = TRUE;
  64. }
  65. __except(EXCEPTION_EXECUTE_HANDLER)
  66. {
  67. }
  68. //we now need to get the CSP list
  69. InitlializeCSPList(&m_dwCSPCount, &m_rgCSPInfo);
  70. //we now need to initialize the CA and its cert types
  71. InitializeCTList(&m_dwCTIndex, &m_dwCTCount, &m_rgCTInfo);
  72. //init for the user selection dialogue
  73. memset(&ScopeInit, 0, sizeof(DSOP_SCOPE_INIT_INFO));
  74. memset(&InitInfo, 0, sizeof(InitInfo));
  75. ScopeInit.cbSize = sizeof(DSOP_SCOPE_INIT_INFO);
  76. ScopeInit.flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN|DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  77. ScopeInit.flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; //this will give us the SAM name for the user
  78. ScopeInit.FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  79. ScopeInit.FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  80. InitInfo.cbSize = sizeof(InitInfo);
  81. InitInfo.pwzTargetComputer = NULL; // NULL == local machine
  82. InitInfo.cDsScopeInfos = 1;
  83. InitInfo.aDsScopeInfos = &ScopeInit;
  84. InitInfo.flOptions = 0; //we are doing single select
  85. //create the COM object
  86. if (S_OK == CoCreateInstance
  87. (CLSID_DsObjectPicker,
  88. NULL,
  89. CLSCTX_INPROC_SERVER,
  90. IID_IDsObjectPicker,
  91. (void **) &m_pDsObjectPicker))
  92. {
  93. if(S_OK != (m_pDsObjectPicker->Initialize(&InitInfo)))
  94. {
  95. m_pDsObjectPicker->Release();
  96. m_pDsObjectPicker=NULL;
  97. }
  98. }
  99. else
  100. m_pDsObjectPicker=NULL;
  101. }
  102. CSCrdEnr::~CSCrdEnr(void)
  103. {
  104. if(m_pDsObjectPicker)
  105. m_pDsObjectPicker->Release();
  106. if(m_rgCTInfo)
  107. FreeCTInfo(m_dwCTCount, m_rgCTInfo);
  108. if(m_rgCSPInfo)
  109. FreeCSPInfo(m_dwCSPCount, m_rgCSPInfo);
  110. if(m_pwszUserUPN)
  111. SCrdEnrollFree(m_pwszUserUPN);
  112. if(m_pwszUserSAM)
  113. SCrdEnrollFree(m_pwszUserSAM);
  114. if(m_pSigningCert)
  115. CertFreeCertificateContext(m_pSigningCert);
  116. if(m_pszCSPNameSigningCert)
  117. SCrdEnrollFree(m_pszCSPNameSigningCert);
  118. if(m_pszContainerSigningCert)
  119. SCrdEnrollFree(m_pszContainerSigningCert);
  120. if(m_pEnrolledCert)
  121. CertFreeCertificateContext(m_pEnrolledCert);
  122. if (NULL != m_pwszCachedCTEOid)
  123. {
  124. LocalFree(m_pwszCachedCTEOid);
  125. }
  126. if (NULL != m_pCachedCTE)
  127. {
  128. LocalFree(m_pCachedCTE);
  129. }
  130. if(m_fInitialize)
  131. CoUninitialize();
  132. if (m_fInitializedCriticalSection)
  133. DeleteCriticalSection(&m_cSection);
  134. }
  135. STDMETHODIMP CSCrdEnr::get_CSPCount(long * pVal)
  136. {
  137. if(NULL==pVal)
  138. return E_INVALIDARG;
  139. EnterCriticalSection(&m_cSection);
  140. *pVal = (long)m_dwCSPCount;
  141. LeaveCriticalSection(&m_cSection);
  142. return S_OK;
  143. }
  144. STDMETHODIMP CSCrdEnr::get_CSPName(BSTR * pVal)
  145. {
  146. HRESULT hr = S_OK;
  147. EnterCriticalSection(&m_cSection);
  148. if(NULL==m_rgCSPInfo || 0==m_dwCSPCount)
  149. {
  150. *pVal=NULL;
  151. hr=E_INVALIDARG;
  152. }
  153. else
  154. {
  155. if( NULL == (*pVal = SysAllocString(m_rgCSPInfo[m_dwCSPIndex].pwszCSPName)))
  156. hr = E_OUTOFMEMORY;
  157. }
  158. LeaveCriticalSection(&m_cSection);
  159. return(hr);
  160. }
  161. STDMETHODIMP CSCrdEnr::put_CSPName(BSTR newVal)
  162. {
  163. HRESULT hr= E_FAIL;
  164. DWORD errBefore= GetLastError();
  165. DWORD dwIndex=0;
  166. EnterCriticalSection(&m_cSection);
  167. if(NULL == m_rgCSPInfo || 0 == m_dwCSPCount || NULL == newVal)
  168. goto InvalidArgErr;
  169. for(dwIndex=0; dwIndex < m_dwCSPCount; dwIndex++)
  170. {
  171. if(0 == _wcsicmp(newVal, m_rgCSPInfo[dwIndex].pwszCSPName))
  172. {
  173. m_dwCSPIndex=dwIndex;
  174. break;
  175. }
  176. }
  177. if(dwIndex == m_dwCSPCount)
  178. goto InvalidArgErr;
  179. hr=S_OK;
  180. CommonReturn:
  181. LeaveCriticalSection(&m_cSection);
  182. SetLastError(errBefore);
  183. return hr;
  184. ErrorReturn:
  185. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  186. errBefore=E_UNEXPECTED;
  187. hr = CodeToHR(errBefore);
  188. goto CommonReturn;
  189. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  190. }
  191. STDMETHODIMP CSCrdEnr::selectUserName
  192. (/* [in] */ DWORD dwFlags)
  193. {
  194. HRESULT hr= E_FAIL;
  195. DWORD errBefore= GetLastError();
  196. LPWSTR pwszSelectedUserSAM=NULL;
  197. LPWSTR pwszSelectedUserUPN=NULL;
  198. EnterCriticalSection(&m_cSection);
  199. if(NULL == m_pDsObjectPicker)
  200. goto InvalidArgErr;
  201. if(S_OK != (hr = GetSelectedUserName(m_pDsObjectPicker,
  202. &pwszSelectedUserSAM,
  203. &pwszSelectedUserUPN)))
  204. goto SelectUserErr;
  205. //we should at least have the UserSAM name
  206. if(NULL == pwszSelectedUserSAM)
  207. {
  208. if(pwszSelectedUserUPN)
  209. SCrdEnrollFree(pwszSelectedUserUPN);
  210. goto UnexpectedErr;
  211. }
  212. if(m_pwszUserSAM)
  213. {
  214. SCrdEnrollFree(m_pwszUserSAM);
  215. m_pwszUserSAM=NULL;
  216. }
  217. if(m_pwszUserUPN)
  218. {
  219. SCrdEnrollFree(m_pwszUserUPN);
  220. m_pwszUserUPN=NULL;
  221. }
  222. m_pwszUserSAM=pwszSelectedUserSAM;
  223. m_pwszUserUPN=pwszSelectedUserUPN;
  224. hr=S_OK;
  225. CommonReturn:
  226. LeaveCriticalSection(&m_cSection);
  227. SetLastError(errBefore);
  228. return hr;
  229. ErrorReturn:
  230. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  231. errBefore=E_UNEXPECTED;
  232. hr = CodeToHR(errBefore);
  233. goto CommonReturn;
  234. SET_ERROR_VAR(SelectUserErr, hr);
  235. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  236. SET_ERROR(UnexpectedErr, E_UNEXPECTED);
  237. }
  238. STDMETHODIMP CSCrdEnr::enroll
  239. (/* [in] */ DWORD dwFlags)
  240. {
  241. HRESULT hr = E_FAIL;
  242. DWORD errBefore = GetLastError();
  243. ULONG cbSize = 0;
  244. SCrdEnroll_CA_INFO *pCAInfo = NULL;
  245. SCrdEnroll_CT_INFO *pCertTypeInfo = NULL;
  246. BSTR bstrAttribs = NULL;
  247. BSTR bstrCA = NULL;
  248. BSTR bstrCertificate = NULL;
  249. BSTR bstrReq = NULL;
  250. LPWSTR pwszRequesterName = NULL;
  251. ICertRequest2 *pICertRequest = NULL;
  252. IEnroll4 *pIEnroll = NULL;
  253. CRYPT_DATA_BLOB PKCS10Blob;
  254. CRYPT_DATA_BLOB PKCS7Request;
  255. CRYPT_DATA_BLOB PKCS7Response;
  256. DWORD dwDisposition;
  257. DWORD dwRequestID;
  258. LPWSTR pwszNewContainerName=NULL;
  259. PCCERT_CONTEXT pArchivalCert = NULL;
  260. LONG lKeySpec = XEKL_KEYSPEC_KEYX;
  261. LONG lKeyMin, lKeyMax;
  262. DWORD dwKeyMin, dwKeyMax, dwKeySize;
  263. //------------------------------------------------------------
  264. //
  265. // Define locally scoped utility functions:
  266. //
  267. //------------------------------------------------------------
  268. LocalScope(EnrollUtilities):
  269. BSTR bstrConcat(LPWSTR pwsz1, LPWSTR pwsz2, LPWSTR pwsz3, LPWSTR pwsz4)
  270. {
  271. // Note: assumes valid input parameters!
  272. BSTR bstrResult = NULL;
  273. LPWSTR pwszResult = NULL;
  274. pwszResult = (LPWSTR)SCrdEnrollAlloc(sizeof(WCHAR) * (wcslen(pwsz1) + wcslen(pwsz2) + wcslen(pwsz3) + wcslen(pwsz4) + 1));
  275. if (pwszResult == NULL) { return NULL; }
  276. else {
  277. wcscpy(pwszResult, pwsz1);
  278. wcscat(pwszResult, pwsz2);
  279. wcscat(pwszResult, pwsz3);
  280. wcscat(pwszResult, pwsz4);
  281. // Convert the result to a BSTR
  282. bstrResult = SysAllocString(pwszResult);
  283. // Free the temporary storage.
  284. SCrdEnrollFree(pwszResult);
  285. // Return the result.
  286. return bstrResult;
  287. }
  288. }
  289. DWORD ICEnrollDispositionToCryptuiStatus(IN DWORD dwDisposition)
  290. {
  291. switch (dwDisposition)
  292. {
  293. case CR_DISP_INCOMPLETE: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED;
  294. case CR_DISP_DENIED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED;
  295. case CR_DISP_ISSUED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_CERT_ISSUED;
  296. case CR_DISP_ISSUED_OUT_OF_BAND: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY;
  297. case CR_DISP_UNDER_SUBMISSION: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION;
  298. case CR_DISP_ERROR: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  299. default:
  300. // Should never happen
  301. return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  302. }
  303. }
  304. EndLocalScope;
  305. //------------------------------------------------------------
  306. //
  307. // Begin procedure body
  308. //
  309. //------------------------------------------------------------
  310. memset(&PKCS10Blob, 0, sizeof(CRYPT_DATA_BLOB));
  311. memset(&PKCS7Request, 0, sizeof(CRYPT_DATA_BLOB));
  312. memset(&PKCS7Response, 0, sizeof(CRYPT_DATA_BLOB));
  313. EnterCriticalSection(&m_cSection);
  314. //check for the status of the smart cards in the reader.
  315. //return the fully qualified container name for the new user
  316. //smart card
  317. if(S_OK != (hr = ChkSCardStatus(m_fSCardSigningCert,
  318. m_pSigningCert,
  319. m_pszCSPNameSigningCert,
  320. m_dwCSPTypeSigningCert,
  321. m_pszContainerSigningCert,
  322. m_rgCSPInfo[m_dwCSPIndex].pwszCSPName,
  323. &pwszNewContainerName)))
  324. goto StatusErr;
  325. //delete the old certificate
  326. if(m_pEnrolledCert)
  327. {
  328. CertFreeCertificateContext(m_pEnrolledCert);
  329. m_pEnrolledCert=NULL;
  330. }
  331. //init enrollment status
  332. m_lEnrollmentStatus = CR_DISP_INCOMPLETE;
  333. //make sure that we have the correct information for processing
  334. //the enrollment request
  335. if(0 == m_dwCTCount || NULL == m_rgCTInfo || 0 == m_dwCSPCount ||
  336. NULL == m_rgCSPInfo || NULL == m_pSigningCert ||
  337. ((NULL == m_pwszUserSAM) && (NULL == m_pwszUserUPN)))
  338. goto InvalidArgErr;
  339. //make sure that we have some CA
  340. pCertTypeInfo=&(m_rgCTInfo[m_dwCTIndex]);
  341. if(NULL == pCertTypeInfo->rgCAInfo || 0 == pCertTypeInfo->dwCACount)
  342. goto InvalidArgErr;
  343. pCAInfo=&(pCertTypeInfo->rgCAInfo[pCertTypeInfo->dwCAIndex]);
  344. if(NULL == (pIEnroll=MyPIEnroll4GetNoCOM()))
  345. goto TraceErr;
  346. //we use our own My store to store the enrolled certificate
  347. if(S_OK != (hr = pIEnroll->put_MyStoreNameWStr((LPWSTR)g_MyStoreName)))
  348. goto xEnrollErr;
  349. //we always use a new key
  350. if(S_OK != (hr=pIEnroll->put_UseExistingKeySet(FALSE)))
  351. goto xEnrollErr;
  352. //we the key container name
  353. if(S_OK != (hr=pIEnroll->put_ContainerNameWStr(pwszNewContainerName)))
  354. goto xEnrollErr;
  355. //set the CSP information
  356. if(S_OK != (hr=pIEnroll->put_ProviderType(m_rgCSPInfo[m_dwCSPIndex].dwCSPType)))
  357. goto xEnrollErr;
  358. if(S_OK !=(hr=pIEnroll->put_ProviderNameWStr(m_rgCSPInfo[m_dwCSPIndex].pwszCSPName)))
  359. goto xEnrollErr;
  360. //dwKeySpec
  361. if(S_OK !=(hr=pIEnroll->put_KeySpec(pCertTypeInfo->dwKeySpec)))
  362. goto xEnrollErr;
  363. //private key flags. Left half-word is the key size.
  364. //If the key size is 0, then specify a default key size.
  365. if (0 == (pCertTypeInfo->dwGenKeyFlags & 0xFFFF0000))
  366. {
  367. // If min key size is not set, use 1024 bits.
  368. pCertTypeInfo->dwGenKeyFlags |= (1024 << 16);
  369. }
  370. dwKeySize = (pCertTypeInfo->dwGenKeyFlags & 0xFFFF0000) >> 16;
  371. if (0x0 != dwKeySize)
  372. {
  373. //make sure key size is in the range
  374. //let's get CSP key size information
  375. if (AT_SIGNATURE == pCertTypeInfo->dwKeySpec)
  376. {
  377. lKeySpec = XEKL_KEYSPEC_SIG;
  378. }
  379. hr = pIEnroll->GetKeyLenEx(XEKL_KEYSIZE_MIN, lKeySpec, &lKeyMin);
  380. // don't have error check because the CSP may not support it
  381. if (S_OK == hr)
  382. {
  383. hr = pIEnroll->GetKeyLenEx(XEKL_KEYSIZE_MAX, lKeySpec, &lKeyMax);
  384. if (S_OK != hr)
  385. {
  386. goto xEnrollErr;
  387. }
  388. dwKeyMin = (DWORD)lKeyMin;
  389. dwKeyMax = (DWORD)lKeyMax;
  390. if (dwKeySize < dwKeyMin)
  391. {
  392. //reset the current key size
  393. pCertTypeInfo->dwGenKeyFlags &= 0x0000FFFF;
  394. //set adjusted size
  395. pCertTypeInfo->dwGenKeyFlags |= ((dwKeyMin & 0x0000FFFF) << 16);
  396. }
  397. if (dwKeySize > dwKeyMax)
  398. {
  399. //reset the current key size
  400. pCertTypeInfo->dwGenKeyFlags &= 0x0000FFFF;
  401. //set adjusted size
  402. pCertTypeInfo->dwGenKeyFlags |= ((dwKeyMax & 0x0000FFFF) << 16);
  403. }
  404. }
  405. }
  406. if (S_OK !=(hr=pIEnroll->put_GenKeyFlags(pCertTypeInfo->dwGenKeyFlags)))
  407. goto xEnrollErr;
  408. // S/MIME supported?
  409. if (S_OK !=(hr=pIEnroll->put_EnableSMIMECapabilities
  410. (pCertTypeInfo->dwEnrollmentFlags & CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS)))
  411. goto xEnrollErr;
  412. // Set archival cert, if one has been specified.
  413. // bstrCA <-- CA_location\CA_Name
  414. //
  415. bstrCA = local.bstrConcat
  416. (pCAInfo->pwszCALocation,
  417. L"\\",
  418. pCAInfo->pwszCADisplayName ? pCAInfo->pwszCADisplayName : pCAInfo->pwszCAName,
  419. L"\0");
  420. if (NULL == bstrCA)
  421. goto MemoryErr;
  422. if (pCertTypeInfo->dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL)
  423. {
  424. if (S_OK != (hr = this->GetCAExchangeCertificate(bstrCA, &pArchivalCert)))
  425. goto xEnrollErr;
  426. if (S_OK != (hr = pIEnroll->SetPrivateKeyArchiveCertificate(pArchivalCert)))
  427. goto xEnrollErr;
  428. }
  429. //cert Type extensions
  430. if(pCertTypeInfo->pCertTypeExtensions)
  431. {
  432. if(S_OK != (hr=pIEnroll->AddExtensionsToRequest
  433. (pCertTypeInfo->pCertTypeExtensions)))
  434. goto xEnrollErr;
  435. }
  436. //no smart card stuff
  437. if(S_OK != (hr=pIEnroll->put_ReuseHardwareKeyIfUnableToGenNew(FALSE)))
  438. goto xEnrollErr;
  439. //create a PKCS10 request
  440. if(FAILED(hr=pIEnroll->createPKCS10WStr(NULL,
  441. NULL,
  442. &PKCS10Blob)))
  443. goto xEnrollErr;
  444. //add the name value pair of the enroll-on-behalf
  445. pwszRequesterName=MkWStr(wszPROPREQUESTERNAME);
  446. if(NULL==pwszRequesterName)
  447. goto MemoryErr;
  448. if(S_OK != (hr=pIEnroll->AddNameValuePairToSignatureWStr(
  449. pwszRequesterName, m_pwszUserSAM)))
  450. goto xEnrollErr;
  451. //sign the request
  452. if(S_OK != (hr=pIEnroll->CreatePKCS7RequestFromRequest(
  453. &PKCS10Blob,
  454. m_pSigningCert,
  455. &PKCS7Request)))
  456. goto xEnrollErr;
  457. //send the request to the CA
  458. //we set the purpose to the renew so that the format
  459. //will be a PKCS7
  460. bstrReq = SysAllocStringByteLen((LPCSTR)PKCS7Request.pbData, PKCS7Request.cbData);
  461. if (NULL == bstrReq)
  462. goto MemoryErr;
  463. bstrAttribs = NULL;
  464. // RECALL: bstrCA <-- CA_location\CA_Name
  465. if (pICertRequest == NULL)
  466. {
  467. if (S_OK != (hr = CoCreateInstance
  468. (CLSID_CCertRequest,
  469. NULL,
  470. CLSCTX_INPROC_SERVER,
  471. IID_ICertRequest2,
  472. (void**)&pICertRequest)))
  473. goto xEnrollErr;
  474. }
  475. if (S_OK != (hr = pICertRequest->Submit
  476. (CR_IN_BINARY | CR_IN_PKCS7,
  477. bstrReq,
  478. bstrAttribs,
  479. bstrCA,
  480. (long *)&dwDisposition)))
  481. goto xEnrollErr;
  482. //use CR_DISP_ as enrollment status
  483. m_lEnrollmentStatus = dwDisposition;
  484. // check pending and save pending info
  485. // however, smart card enrollment station don't know how to deal with
  486. // this pending requests, may not necessary to do that
  487. if (CR_DISP_UNDER_SUBMISSION == m_lEnrollmentStatus)
  488. {
  489. hr = pICertRequest->GetRequestId((long *)&dwRequestID);
  490. if (S_OK != hr)
  491. {
  492. goto xEnrollErr;
  493. }
  494. hr = pIEnroll->setPendingRequestInfoWStr(
  495. dwRequestID,
  496. pCAInfo->pwszCALocation,
  497. NULL != pCAInfo->pwszCADisplayName ?
  498. pCAInfo->pwszCADisplayName : pCAInfo->pwszCAName,
  499. NULL);
  500. }
  501. if (CR_DISP_ISSUED != m_lEnrollmentStatus)
  502. {
  503. //if not issued, return
  504. goto CommonReturn;
  505. }
  506. //must be CR_DISP_ISSUED
  507. hr = pICertRequest->GetCertificate(
  508. CR_OUT_BINARY | CR_OUT_CHAIN, &bstrCertificate);
  509. if (S_OK != hr)
  510. {
  511. goto xEnrollErr;
  512. }
  513. // Marshal the cert into a CRYPT_DATA_BLOB, and install it:
  514. PKCS7Response.pbData = (LPBYTE)bstrCertificate;
  515. PKCS7Response.cbData = SysStringByteLen(bstrCertificate);
  516. m_pEnrolledCert = pIEnroll->getCertContextFromPKCS7(&PKCS7Response);
  517. if (NULL == m_pEnrolledCert)
  518. {
  519. hr = HRESULT_FROM_WIN32(GetLastError());
  520. goto TraceErr;
  521. }
  522. hr=pIEnroll->acceptPKCS7Blob(&PKCS7Response);
  523. //we delete the enrolled certificate from the "My" store since it is added by
  524. //xEnroll. No need to check the error
  525. SearchAndDeleteCert(m_pEnrolledCert);
  526. if(S_OK != hr)
  527. {
  528. goto TraceErr;
  529. }
  530. hr=S_OK;
  531. CommonReturn:
  532. LeaveCriticalSection(&m_cSection);
  533. if(pwszNewContainerName)
  534. LocalFree((HLOCAL)pwszNewContainerName);
  535. if(pwszRequesterName)
  536. FreeWStr(pwszRequesterName);
  537. //the memory from xEnroll is freed via LocalFree
  538. //since we use the PIEnrollGetNoCOM function
  539. if(PKCS10Blob.pbData)
  540. LocalFree(PKCS10Blob.pbData);
  541. if(PKCS7Request.pbData)
  542. LocalFree(PKCS7Request.pbData);
  543. if (NULL != pArchivalCert)
  544. CertFreeCertificateContext(pArchivalCert);
  545. // PKCS7Respone's data is just an alias to m_pEnrolledCert's data: we don't need to free it.
  546. if (NULL != bstrAttribs) { SysFreeString(bstrAttribs); }
  547. if (NULL != bstrCA) { SysFreeString(bstrCA); }
  548. if (NULL != bstrCertificate) { SysFreeString(bstrCertificate); }
  549. if (NULL != pICertRequest) { pICertRequest->Release(); }
  550. if(pIEnroll)
  551. pIEnroll->Release();
  552. SetLastError(errBefore);
  553. return hr;
  554. ErrorReturn:
  555. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  556. errBefore=E_UNEXPECTED;
  557. hr = CodeToHR(errBefore);
  558. //if an error has occurred, the free the enrolled certificate
  559. if(m_pEnrolledCert)
  560. {
  561. CertFreeCertificateContext(m_pEnrolledCert);
  562. m_pEnrolledCert=NULL;
  563. }
  564. goto CommonReturn;
  565. TRACE_ERROR(TraceErr);
  566. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  567. SET_ERROR_VAR(xEnrollErr, hr);
  568. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  569. SET_ERROR_VAR(StatusErr, hr);
  570. }
  571. HRESULT CSCrdEnr::GetCAExchangeCertificate(IN BSTR bstrCAQualifiedName,
  572. OUT PCCERT_CONTEXT *ppCert)
  573. {
  574. HRESULT hr = S_OK;
  575. ICertRequest2 *pICertRequest = NULL;
  576. VARIANT varExchangeCertificate;
  577. // Input validation:
  578. if (NULL == bstrCAQualifiedName || NULL == ppCert)
  579. return E_INVALIDARG;
  580. // Init:
  581. *ppCert = NULL;
  582. varExchangeCertificate.vt = VT_EMPTY;
  583. varExchangeCertificate.bstrVal = NULL;
  584. if (S_OK != (hr = CoCreateInstance
  585. (CLSID_CCertRequest,
  586. NULL,
  587. CLSCTX_INPROC_SERVER,
  588. IID_ICertRequest2,
  589. (void**)&pICertRequest)))
  590. goto ErrorReturn;
  591. if (S_OK != (hr = pICertRequest->GetCAProperty
  592. (bstrCAQualifiedName, // CA Name/CA Location
  593. CR_PROP_CAXCHGCERT, // Get the exchange certificate from the CA.
  594. 0, // Unused
  595. PROPTYPE_BINARY, //
  596. CR_OUT_BINARY, //
  597. &varExchangeCertificate // Variant type representing the certificate.
  598. )))
  599. goto ErrorReturn;
  600. if (VT_BSTR != varExchangeCertificate.vt || NULL == varExchangeCertificate.bstrVal)
  601. goto UnexpectedErr;
  602. *ppCert = CertCreateCertificateContext
  603. (X509_ASN_ENCODING,
  604. (LPBYTE)varExchangeCertificate.bstrVal,
  605. SysStringByteLen(varExchangeCertificate.bstrVal));
  606. if (*ppCert == NULL)
  607. goto CertCliErr;
  608. CommonReturn:
  609. if (NULL != pICertRequest) { pICertRequest->Release(); }
  610. if (NULL != varExchangeCertificate.bstrVal) { SysFreeString(varExchangeCertificate.bstrVal); }
  611. return hr;
  612. ErrorReturn:
  613. if (ppCert != NULL && *ppCert != NULL)
  614. {
  615. CertFreeCertificateContext(*ppCert);
  616. *ppCert = NULL;
  617. }
  618. goto CommonReturn;
  619. SET_HRESULT(CertCliErr, HRESULT_FROM_WIN32(GetLastError()));
  620. SET_HRESULT(UnexpectedErr, E_UNEXPECTED);
  621. }
  622. STDMETHODIMP CSCrdEnr::selectSigningCertificate
  623. (/* [in] */ DWORD dwFlags,
  624. /* [in] */ BSTR bstrCertTemplateName)
  625. {
  626. HRESULT hr= E_FAIL;
  627. DWORD errBefore= GetLastError();
  628. CRYPTUI_SELECTCERTIFICATE_STRUCT SelCert;
  629. BOOL fSCardSigningCert=FALSE;
  630. DWORD dwCSPTypeSigningCert=0;
  631. DWORD dwSize=0;
  632. DWORD dwImpType=0;
  633. SCrdEnroll_CERT_SELECT_INFO CertSelectInfo;
  634. HCRYPTPROV hProv=NULL; //no need to free it
  635. LPSTR pszContainerSigningCert=NULL;
  636. LPSTR pszCSPNameSigningCert=NULL;
  637. PCCERT_CONTEXT pSigningCert=NULL;
  638. HCERTSTORE hMyStore=NULL;
  639. CERT_CHAIN_PARA ChainParams;
  640. CERT_CHAIN_POLICY_PARA ChainPolicy;
  641. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  642. CERT_CHAIN_CONTEXT const *pCertChain = NULL;
  643. memset(&SelCert, 0, sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT));
  644. EnterCriticalSection(&m_cSection);
  645. //select a signing certificate in my store with private key
  646. hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  647. g_dwMsgAndCertEncodingType,
  648. NULL,
  649. CERT_SYSTEM_STORE_CURRENT_USER,
  650. L"my");
  651. if(NULL==hMyStore)
  652. goto TraceErr;
  653. CertSelectInfo.dwFlags = dwFlags;
  654. CertSelectInfo.pwszCertTemplateName = bstrCertTemplateName;
  655. SelCert.dwSize=sizeof(CRYPTUI_SELECTCERTIFICATE_STRUCT);
  656. SelCert.cDisplayStores=1;
  657. SelCert.rghDisplayStores=&hMyStore;
  658. SelCert.pFilterCallback=SelectSignCertCallBack;
  659. SelCert.pvCallbackData=&CertSelectInfo;
  660. pSigningCert=CryptUIDlgSelectCertificate(&SelCert);
  661. if(NULL==pSigningCert)
  662. {
  663. //user clicks on the cancel button.
  664. hr=S_OK;
  665. goto CommonReturn;
  666. }
  667. //verification on the cert
  668. ZeroMemory(&ChainParams, sizeof(ChainParams));
  669. ChainParams.cbSize = sizeof(ChainParams);
  670. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  671. //get cert chain 1st
  672. if (!CertGetCertificateChain(
  673. HCCE_CURRENT_USER, //enrollment agent
  674. pSigningCert, //signing cert
  675. NULL, //use current system time
  676. NULL, //no additional stores
  677. &ChainParams, //chain params
  678. 0, //no crl check
  679. NULL, //reserved
  680. &pCertChain))
  681. {
  682. hr = HRESULT_FROM_WIN32(GetLastError());
  683. goto CertGetCertificateChainError;
  684. }
  685. ZeroMemory(&ChainPolicy, sizeof(ChainPolicy));
  686. ChainPolicy.cbSize = sizeof(ChainPolicy);
  687. ChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
  688. ZeroMemory(&PolicyStatus, sizeof(PolicyStatus));
  689. PolicyStatus.cbSize = sizeof(PolicyStatus);
  690. PolicyStatus.lChainIndex = -1;
  691. PolicyStatus.lElementIndex = -1;
  692. //verify the chain
  693. if (!CertVerifyCertificateChainPolicy(
  694. CERT_CHAIN_POLICY_BASE, //basic
  695. pCertChain,
  696. &ChainPolicy,
  697. &PolicyStatus))
  698. {
  699. hr = HRESULT_FROM_WIN32(GetLastError());
  700. goto CertVerifyCertificateChainPolicyError;
  701. }
  702. if (S_OK != PolicyStatus.dwError)
  703. {
  704. hr = PolicyStatus.dwError;
  705. goto CertVerifyCertificateChainPolicyError;
  706. }
  707. //get the hProv
  708. if(!CryptAcquireCertificatePrivateKey(
  709. pSigningCert,
  710. CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  711. NULL,
  712. &hProv, //this handle is cached and no need to be freed
  713. NULL,
  714. NULL))
  715. goto TraceErr;
  716. //get related information
  717. //impType
  718. dwSize = sizeof(dwImpType);
  719. if(!CryptGetProvParam(hProv,
  720. PP_IMPTYPE,
  721. (BYTE *)(&dwImpType),
  722. &dwSize,
  723. 0))
  724. goto TraceErr;
  725. if(CRYPT_IMPL_REMOVABLE & dwImpType)
  726. fSCardSigningCert=TRUE;
  727. //CSP Type
  728. dwSize = sizeof(dwCSPTypeSigningCert);
  729. if(!CryptGetProvParam(hProv,
  730. PP_PROVTYPE,
  731. (BYTE *)(&dwCSPTypeSigningCert),
  732. &dwSize,
  733. 0))
  734. {
  735. goto TraceErr;
  736. }
  737. //CSP name
  738. dwSize = 0;
  739. if(!CryptGetProvParam(hProv,
  740. PP_NAME,
  741. NULL,
  742. &dwSize,
  743. 0) || (0==dwSize))
  744. goto TraceErr;
  745. pszCSPNameSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
  746. if(NULL == pszCSPNameSigningCert)
  747. goto MemoryErr;
  748. if(!CryptGetProvParam(hProv,
  749. PP_NAME,
  750. (BYTE *)pszCSPNameSigningCert,
  751. &dwSize,
  752. 0))
  753. goto TraceErr;
  754. //Container name
  755. dwSize = 0;
  756. if(!CryptGetProvParam(hProv,
  757. PP_CONTAINER,
  758. NULL,
  759. &dwSize,
  760. 0) || (0==dwSize))
  761. goto TraceErr;
  762. pszContainerSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
  763. if(NULL == pszContainerSigningCert)
  764. goto MemoryErr;
  765. if(!CryptGetProvParam(hProv,
  766. PP_CONTAINER,
  767. (BYTE *)pszContainerSigningCert,
  768. &dwSize,
  769. 0))
  770. goto TraceErr;
  771. //now, we need to perform a signig operation so that we
  772. //can invoke the smard card dialogue and cash the reader information
  773. //to the hProv handle. This operation is benign if the CSP of the signing
  774. //certificate is not on a smart card
  775. if(!SignWithCert(pszCSPNameSigningCert,
  776. dwCSPTypeSigningCert,
  777. pSigningCert))
  778. goto TraceErr;
  779. //the certificate looks good
  780. if(m_pSigningCert)
  781. CertFreeCertificateContext(m_pSigningCert);
  782. if(m_pszContainerSigningCert)
  783. SCrdEnrollFree(m_pszContainerSigningCert);
  784. if(m_pszCSPNameSigningCert)
  785. SCrdEnrollFree(m_pszCSPNameSigningCert);
  786. m_pSigningCert=pSigningCert;
  787. m_fSCardSigningCert = fSCardSigningCert;
  788. m_pszCSPNameSigningCert = pszCSPNameSigningCert;
  789. m_dwCSPTypeSigningCert = dwCSPTypeSigningCert;
  790. m_pszContainerSigningCert = pszContainerSigningCert;
  791. pSigningCert=NULL;
  792. pszCSPNameSigningCert=NULL;
  793. pszContainerSigningCert=NULL;
  794. hr=S_OK;
  795. CommonReturn:
  796. LeaveCriticalSection(&m_cSection);
  797. if(pSigningCert)
  798. CertFreeCertificateContext(pSigningCert);
  799. if(hMyStore)
  800. CertCloseStore(hMyStore, 0);
  801. if(pszContainerSigningCert)
  802. SCrdEnrollFree(pszContainerSigningCert);
  803. if(pszCSPNameSigningCert)
  804. SCrdEnrollFree(pszCSPNameSigningCert);
  805. if (NULL != pCertChain)
  806. {
  807. CertFreeCertificateChain(pCertChain);
  808. }
  809. SetLastError(errBefore);
  810. return hr;
  811. ErrorReturn:
  812. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  813. errBefore=E_UNEXPECTED;
  814. hr = CodeToHR(errBefore);
  815. goto CommonReturn;
  816. TRACE_ERROR(TraceErr);
  817. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  818. TRACE_ERROR(CertGetCertificateChainError)
  819. TRACE_ERROR(CertVerifyCertificateChainPolicyError)
  820. }
  821. STDMETHODIMP CSCrdEnr::setSigningCertificate
  822. (/* [in] */ DWORD dwFlags,
  823. /* [in] */ BSTR bstrCertTemplateName)
  824. {
  825. HRESULT hr= E_FAIL;
  826. DWORD errBefore= GetLastError();
  827. BOOL fSCardSigningCert=FALSE;
  828. DWORD dwCSPTypeSigningCert=0;
  829. DWORD dwSize=0;
  830. DWORD dwImpType=0;
  831. SCrdEnroll_CERT_SELECT_INFO CertSelectInfo;
  832. BOOL fSetCert=FALSE;
  833. HCRYPTPROV hProv=NULL; //no need to free it
  834. PCCERT_CONTEXT pPreCert=NULL; //no need to free it
  835. LPSTR pszContainerSigningCert=NULL;
  836. LPSTR pszCSPNameSigningCert=NULL;
  837. PCCERT_CONTEXT pSigningCert=NULL;
  838. HCERTSTORE hMyStore=NULL;
  839. EnterCriticalSection(&m_cSection);
  840. //mark if the signing cert is set previously
  841. if(m_pSigningCert)
  842. fSetCert=TRUE;
  843. //select a signing certificate in my store with private key
  844. hMyStore=CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  845. g_dwMsgAndCertEncodingType,
  846. NULL,
  847. CERT_SYSTEM_STORE_CURRENT_USER,
  848. L"my");
  849. if(NULL==hMyStore)
  850. goto TraceErr;
  851. CertSelectInfo.dwFlags = dwFlags;
  852. CertSelectInfo.pwszCertTemplateName = bstrCertTemplateName;
  853. while(pSigningCert = CertEnumCertificatesInStore(hMyStore, pPreCert))
  854. {
  855. //check for the certificate
  856. if(!SelectSignCertCallBack(pSigningCert, NULL, &CertSelectInfo))
  857. goto NextCert;
  858. //this is a detaul NO-UI selection. We can not handle the case
  859. //when the signing certificate is on a smart card
  860. if(SmartCardCSP(pSigningCert))
  861. goto NextCert;
  862. //get the hProv
  863. if(!CryptAcquireCertificatePrivateKey(
  864. pSigningCert,
  865. CRYPT_ACQUIRE_CACHE_FLAG | CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  866. NULL,
  867. &hProv, //this handle is cached and no need to be freed
  868. NULL,
  869. NULL))
  870. goto NextCert;
  871. //get related information
  872. //impType
  873. dwSize = sizeof(dwImpType);
  874. if(!CryptGetProvParam(hProv,
  875. PP_IMPTYPE,
  876. (BYTE *)(&dwImpType),
  877. &dwSize,
  878. 0))
  879. goto NextCert;
  880. if(CRYPT_IMPL_REMOVABLE & dwImpType)
  881. fSCardSigningCert=TRUE;
  882. //CSP Type
  883. dwSize = sizeof(dwCSPTypeSigningCert);
  884. if(!CryptGetProvParam(hProv,
  885. PP_PROVTYPE,
  886. (BYTE *)(&dwCSPTypeSigningCert),
  887. &dwSize,
  888. 0))
  889. goto NextCert;
  890. //CSP name
  891. dwSize = 0;
  892. if(!CryptGetProvParam(hProv,
  893. PP_NAME,
  894. NULL,
  895. &dwSize,
  896. 0) || (0==dwSize))
  897. goto NextCert;
  898. pszCSPNameSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
  899. if(NULL == pszCSPNameSigningCert)
  900. goto MemoryErr;
  901. if(!CryptGetProvParam(hProv,
  902. PP_NAME,
  903. (BYTE *)pszCSPNameSigningCert,
  904. &dwSize,
  905. 0))
  906. goto NextCert;
  907. //Container name
  908. dwSize = 0;
  909. if(!CryptGetProvParam(hProv,
  910. PP_CONTAINER,
  911. NULL,
  912. &dwSize,
  913. 0) || (0==dwSize))
  914. goto NextCert;
  915. pszContainerSigningCert = (LPSTR) SCrdEnrollAlloc(dwSize);
  916. if(NULL == pszContainerSigningCert)
  917. goto MemoryErr;
  918. if(!CryptGetProvParam(hProv,
  919. PP_CONTAINER,
  920. (BYTE *)pszContainerSigningCert,
  921. &dwSize,
  922. 0))
  923. goto NextCert;
  924. //now, we need to perform a signig operation so that we
  925. //can invoke the smard card dialogue and cash the reader information
  926. //to the hProv handle. This operation is benign if the CSP of the signing
  927. //certificate is not on a smart card
  928. if(!SignWithCert(pszCSPNameSigningCert,
  929. dwCSPTypeSigningCert,
  930. pSigningCert))
  931. goto NextCert;
  932. //the certificate looks good
  933. if((NULL == m_pSigningCert) || (TRUE == fSetCert) ||
  934. (IsNewerCert(pSigningCert, m_pSigningCert)))
  935. {
  936. fSetCert = FALSE;
  937. if(m_pSigningCert)
  938. {
  939. CertFreeCertificateContext(m_pSigningCert);
  940. m_pSigningCert = NULL;
  941. }
  942. m_pSigningCert=CertDuplicateCertificateContext(pSigningCert);
  943. if(NULL == m_pSigningCert)
  944. goto DupErr;
  945. //copy the data
  946. if(m_pszContainerSigningCert)
  947. SCrdEnrollFree(m_pszContainerSigningCert);
  948. if(m_pszCSPNameSigningCert)
  949. SCrdEnrollFree(m_pszCSPNameSigningCert);
  950. m_fSCardSigningCert = fSCardSigningCert;
  951. m_pszCSPNameSigningCert = pszCSPNameSigningCert;
  952. m_dwCSPTypeSigningCert = dwCSPTypeSigningCert;
  953. m_pszContainerSigningCert = pszContainerSigningCert;
  954. pszCSPNameSigningCert=NULL;
  955. pszContainerSigningCert=NULL;
  956. // should select the 1st matched cert
  957. break; //out of while loop
  958. }
  959. NextCert:
  960. if(pszContainerSigningCert)
  961. SCrdEnrollFree(pszContainerSigningCert);
  962. if(pszCSPNameSigningCert)
  963. SCrdEnrollFree(pszCSPNameSigningCert);
  964. pszCSPNameSigningCert=NULL;
  965. pszContainerSigningCert=NULL;
  966. fSCardSigningCert=FALSE;
  967. dwCSPTypeSigningCert=0;
  968. dwSize=0;
  969. dwImpType=0;
  970. pPreCert = pSigningCert;
  971. }
  972. //we should find a certificate
  973. if((NULL == m_pSigningCert) || (m_pSigningCert && (TRUE == fSetCert)))
  974. goto CryptNotFindErr;
  975. hr=S_OK;
  976. CommonReturn:
  977. LeaveCriticalSection(&m_cSection);
  978. if(pSigningCert)
  979. CertFreeCertificateContext(pSigningCert);
  980. if(hMyStore)
  981. CertCloseStore(hMyStore, 0);
  982. if(pszContainerSigningCert)
  983. SCrdEnrollFree(pszContainerSigningCert);
  984. if(pszCSPNameSigningCert)
  985. SCrdEnrollFree(pszCSPNameSigningCert);
  986. SetLastError(errBefore);
  987. return hr;
  988. ErrorReturn:
  989. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  990. errBefore=E_UNEXPECTED;
  991. hr = CodeToHR(errBefore);
  992. goto CommonReturn;
  993. TRACE_ERROR(DupErr);
  994. SET_ERROR(CryptNotFindErr, CRYPT_E_NOT_FOUND);
  995. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  996. TRACE_ERROR(TraceErr);
  997. }
  998. STDMETHODIMP CSCrdEnr::get_EnrollmentStatus
  999. ( /* [retval][out] */ LONG * plEnrollmentStatus)
  1000. {
  1001. if (plEnrollmentStatus == NULL)
  1002. {
  1003. return E_INVALIDARG;
  1004. }
  1005. EnterCriticalSection(&m_cSection);
  1006. *plEnrollmentStatus = m_lEnrollmentStatus;
  1007. LeaveCriticalSection(&m_cSection);
  1008. return S_OK;
  1009. }
  1010. STDMETHODIMP CSCrdEnr::getEnrolledCertificateName
  1011. (/*[in] */ DWORD dwFlags,
  1012. /* [retval][out] */ BSTR *pBstrCertName)
  1013. {
  1014. HRESULT hr= E_FAIL;
  1015. DWORD errBefore= GetLastError();
  1016. DWORD dwChar=0;
  1017. LPWSTR pwsz=NULL;
  1018. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
  1019. EnterCriticalSection(&m_cSection);
  1020. if(NULL == m_pEnrolledCert)
  1021. goto InvalidArgErr;
  1022. *pBstrCertName=NULL;
  1023. if(0 == (SCARD_ENROLL_NO_DISPLAY_CERT & dwFlags))
  1024. {
  1025. //view the certificate
  1026. memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
  1027. CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
  1028. CertViewStruct.pCertContext=m_pEnrolledCert;
  1029. CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE;
  1030. CryptUIDlgViewCertificate(&CertViewStruct, NULL);
  1031. }
  1032. dwChar=CertGetNameStringW(
  1033. m_pEnrolledCert,
  1034. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1035. 0,
  1036. NULL,
  1037. NULL,
  1038. 0);
  1039. if ((dwChar != 0) && (NULL != (pwsz = (LPWSTR)SCrdEnrollAlloc(dwChar * sizeof(WCHAR)))))
  1040. {
  1041. CertGetNameStringW(
  1042. m_pEnrolledCert,
  1043. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  1044. 0,
  1045. NULL,
  1046. pwsz,
  1047. dwChar);
  1048. if( NULL == (*pBstrCertName = SysAllocString(pwsz)) )
  1049. goto MemoryErr;
  1050. }
  1051. hr=S_OK;
  1052. CommonReturn:
  1053. LeaveCriticalSection(&m_cSection);
  1054. if(pwsz)
  1055. SCrdEnrollFree(pwsz);
  1056. SetLastError(errBefore);
  1057. return hr;
  1058. ErrorReturn:
  1059. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1060. errBefore=E_UNEXPECTED;
  1061. hr = CodeToHR(errBefore);
  1062. goto CommonReturn;
  1063. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1064. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1065. }
  1066. STDMETHODIMP CSCrdEnr::resetUser()
  1067. {
  1068. EnterCriticalSection(&m_cSection);
  1069. if(m_pwszUserUPN)
  1070. {
  1071. SCrdEnrollFree(m_pwszUserUPN);
  1072. m_pwszUserUPN=NULL;
  1073. }
  1074. if(m_pwszUserSAM)
  1075. {
  1076. SCrdEnrollFree(m_pwszUserSAM);
  1077. m_pwszUserSAM=NULL;
  1078. }
  1079. if(m_pEnrolledCert)
  1080. {
  1081. CertFreeCertificateContext(m_pEnrolledCert);
  1082. m_pEnrolledCert=NULL;
  1083. }
  1084. LeaveCriticalSection(&m_cSection);
  1085. return S_OK;
  1086. }
  1087. STDMETHODIMP CSCrdEnr::enumCSPName
  1088. (/* [in] */ DWORD dwIndex,
  1089. /* [in] */ DWORD dwFlags,
  1090. /* [retval][out] */ BSTR *pbstrCSPName)
  1091. {
  1092. HRESULT hr= E_FAIL;
  1093. DWORD errBefore= GetLastError();
  1094. EnterCriticalSection(&m_cSection);
  1095. if(NULL == pbstrCSPName)
  1096. goto InvalidArgErr;
  1097. *pbstrCSPName=NULL;
  1098. if(0 == m_dwCSPCount || NULL == m_rgCSPInfo)
  1099. goto InvalidArgErr;
  1100. if(dwIndex >= m_dwCSPCount)
  1101. goto NoItemErr;
  1102. if( NULL == (*pbstrCSPName = SysAllocString(m_rgCSPInfo[dwIndex].pwszCSPName)))
  1103. goto MemoryErr;
  1104. hr=S_OK;
  1105. CommonReturn:
  1106. LeaveCriticalSection(&m_cSection);
  1107. SetLastError(errBefore);
  1108. return hr;
  1109. ErrorReturn:
  1110. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1111. errBefore=E_UNEXPECTED;
  1112. hr = CodeToHR(errBefore);
  1113. goto CommonReturn;
  1114. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1115. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1116. SET_ERROR(NoItemErr,ERROR_NO_MORE_ITEMS);
  1117. }
  1118. STDMETHODIMP CSCrdEnr::getUserName
  1119. (/* [in] */ DWORD dwFlags,
  1120. /* [retval][out] */ BSTR *pbstrUserName)
  1121. {
  1122. HRESULT hr= E_FAIL;
  1123. DWORD errBefore= GetLastError();
  1124. EnterCriticalSection(&m_cSection);
  1125. if(!pbstrUserName)
  1126. goto InvalidArgErr;
  1127. *pbstrUserName = NULL;
  1128. if((NULL==m_pwszUserUPN) && (NULL==m_pwszUserSAM))
  1129. goto InvalidArgErr;
  1130. if(SCARD_ENROLL_UPN_NAME & dwFlags)
  1131. {
  1132. if(NULL == m_pwszUserUPN)
  1133. goto InvalidArgErr;
  1134. if( NULL == (*pbstrUserName = SysAllocString(m_pwszUserUPN)))
  1135. goto MemoryErr;
  1136. }
  1137. else
  1138. {
  1139. if(NULL == m_pwszUserSAM)
  1140. goto InvalidArgErr;
  1141. if( NULL == (*pbstrUserName = SysAllocString(m_pwszUserSAM)))
  1142. goto MemoryErr;
  1143. }
  1144. hr= S_OK;
  1145. CommonReturn:
  1146. LeaveCriticalSection(&m_cSection);
  1147. SetLastError(errBefore);
  1148. return hr;
  1149. ErrorReturn:
  1150. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1151. errBefore=E_UNEXPECTED;
  1152. hr = CodeToHR(errBefore);
  1153. goto CommonReturn;
  1154. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1155. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1156. }
  1157. STDMETHODIMP CSCrdEnr::setUserName
  1158. (/* [in] */ DWORD dwFlags,
  1159. /* [in] */ BSTR bstrUserName)
  1160. {
  1161. HRESULT hr= E_FAIL;
  1162. DWORD errBefore= GetLastError();
  1163. LPWSTR pwszSAM=NULL;
  1164. EnterCriticalSection(&m_cSection);
  1165. if(!bstrUserName)
  1166. goto InvalidArgErr;
  1167. if(SCARD_ENROLL_UPN_NAME & dwFlags)
  1168. {
  1169. //the UPN name has to have a corresponding SAM name
  1170. if(!GetName(bstrUserName, NameUserPrincipal, NameSamCompatible, &pwszSAM))
  1171. goto TraceErr;
  1172. if(m_pwszUserUPN)
  1173. {
  1174. SCrdEnrollFree(m_pwszUserUPN);
  1175. m_pwszUserUPN=NULL;
  1176. }
  1177. if(m_pwszUserSAM)
  1178. {
  1179. SCrdEnrollFree(m_pwszUserSAM);
  1180. m_pwszUserSAM=NULL;
  1181. }
  1182. if(NULL == (m_pwszUserUPN=CopyWideString(bstrUserName)))
  1183. goto MemoryErr;
  1184. m_pwszUserSAM=pwszSAM;
  1185. pwszSAM = NULL;
  1186. }
  1187. else
  1188. {
  1189. if(m_pwszUserUPN)
  1190. {
  1191. SCrdEnrollFree(m_pwszUserUPN);
  1192. m_pwszUserUPN=NULL;
  1193. }
  1194. if(m_pwszUserSAM)
  1195. {
  1196. SCrdEnrollFree(m_pwszUserSAM);
  1197. m_pwszUserSAM=NULL;
  1198. }
  1199. if(NULL == (m_pwszUserSAM=CopyWideString(bstrUserName)))
  1200. goto MemoryErr;
  1201. GetName(m_pwszUserSAM,
  1202. NameSamCompatible,
  1203. NameUserPrincipal,
  1204. &m_pwszUserUPN);
  1205. }
  1206. hr= S_OK;
  1207. CommonReturn:
  1208. LeaveCriticalSection(&m_cSection);
  1209. if(pwszSAM)
  1210. SCrdEnrollFree(pwszSAM);
  1211. SetLastError(errBefore);
  1212. return hr;
  1213. ErrorReturn:
  1214. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1215. errBefore=E_UNEXPECTED;
  1216. hr = CodeToHR(errBefore);
  1217. goto CommonReturn;
  1218. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1219. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1220. TRACE_ERROR(TraceErr);
  1221. }
  1222. STDMETHODIMP CSCrdEnr::getCertTemplateCount
  1223. (/* [in] */ DWORD dwFlags,
  1224. /* [retval][out] */ long *pdwCertTemplateCount)
  1225. {
  1226. return CertTemplateCountOrName(
  1227. 0, //index, doesn't matter what it is
  1228. dwFlags,
  1229. pdwCertTemplateCount,
  1230. NULL); //count
  1231. }
  1232. STDMETHODIMP CSCrdEnr::getCertTemplateName
  1233. (/* [in] */ DWORD dwFlags,
  1234. /* [retval][out] */ BSTR *pbstrCertTemplateName)
  1235. {
  1236. HRESULT hr = S_OK;
  1237. EnterCriticalSection(&m_cSection);
  1238. if(NULL==m_rgCTInfo || 0==m_dwCTCount)
  1239. {
  1240. *pbstrCertTemplateName=NULL;
  1241. hr=E_INVALIDARG;
  1242. }
  1243. else
  1244. {
  1245. if(dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME)
  1246. {
  1247. if( NULL == (*pbstrCertTemplateName = SysAllocString(m_rgCTInfo[m_dwCTIndex].pwszCTDisplayName)))
  1248. hr = E_OUTOFMEMORY;
  1249. }
  1250. else
  1251. {
  1252. if( NULL == (*pbstrCertTemplateName = SysAllocString(m_rgCTInfo[m_dwCTIndex].pwszCTName)))
  1253. hr = E_OUTOFMEMORY;
  1254. }
  1255. }
  1256. LeaveCriticalSection(&m_cSection);
  1257. return(hr);
  1258. }
  1259. STDMETHODIMP CSCrdEnr::setCertTemplateName
  1260. (/* [in] */ DWORD dwFlags,
  1261. /* [in] */ BSTR bstrCertTemplateName)
  1262. {
  1263. HRESULT hr= E_FAIL;
  1264. DWORD errBefore= GetLastError();
  1265. DWORD dwIndex=0;
  1266. EnterCriticalSection(&m_cSection);
  1267. if(NULL==m_rgCTInfo || 0==m_dwCTCount)
  1268. goto InvalidArgErr;
  1269. for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
  1270. {
  1271. if(dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME)
  1272. {
  1273. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTDisplayName))
  1274. {
  1275. m_dwCTIndex=dwIndex;
  1276. break;
  1277. }
  1278. }
  1279. else
  1280. {
  1281. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
  1282. {
  1283. m_dwCTIndex=dwIndex;
  1284. break;
  1285. }
  1286. }
  1287. }
  1288. if(dwIndex == m_dwCTCount)
  1289. goto InvalidArgErr;
  1290. //we need to get the CA information for the newly selected cert type
  1291. if(FALSE == m_rgCTInfo[m_dwCTIndex].fCAInfo)
  1292. {
  1293. GetCAInfoFromCertType(NULL,
  1294. m_rgCTInfo[m_dwCTIndex].pwszCTName,
  1295. &(m_rgCTInfo[m_dwCTIndex].dwCACount),
  1296. &(m_rgCTInfo[m_dwCTIndex].rgCAInfo));
  1297. m_rgCTInfo[m_dwCTIndex].dwCAIndex=0;
  1298. m_rgCTInfo[m_dwCTIndex].fCAInfo=TRUE;
  1299. }
  1300. hr=S_OK;
  1301. CommonReturn:
  1302. LeaveCriticalSection(&m_cSection);
  1303. SetLastError(errBefore);
  1304. return hr;
  1305. ErrorReturn:
  1306. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1307. errBefore=E_UNEXPECTED;
  1308. hr = CodeToHR(errBefore);
  1309. goto CommonReturn;
  1310. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1311. }
  1312. HRESULT CSCrdEnr::CertTemplateCountOrName(
  1313. IN DWORD dwIndex,
  1314. IN DWORD dwFlags,
  1315. OUT long *pdwCertTemplateCount,
  1316. OUT BSTR *pbstrCertTemplateName)
  1317. {
  1318. HRESULT hr;
  1319. DWORD errBefore = GetLastError();
  1320. DWORD dwIdx = 0;
  1321. DWORD dwValidCount = 0;
  1322. BOOL fCount;
  1323. WCHAR *pwszName;
  1324. DWORD const OFFLINE_SUBJECT_NAME_FLAGS =
  1325. CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT |
  1326. CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT_ALT_NAME;
  1327. EnterCriticalSection(&m_cSection);
  1328. if (NULL == pdwCertTemplateCount && NULL == pbstrCertTemplateName)
  1329. {
  1330. //can't be both
  1331. goto InvalidParamErr;
  1332. }
  1333. //set flag for use of count or enum
  1334. fCount = (NULL != pdwCertTemplateCount);
  1335. if (fCount)
  1336. {
  1337. //init out
  1338. *pdwCertTemplateCount = 0;
  1339. }
  1340. else
  1341. {
  1342. //init out
  1343. *pbstrCertTemplateName = NULL;
  1344. if (0 == m_dwCTCount || NULL == m_rgCTInfo)
  1345. {
  1346. //no templates
  1347. goto InvalidArgErr;
  1348. }
  1349. if (dwIndex >= m_dwCTCount)
  1350. {
  1351. goto NoItemErr;
  1352. }
  1353. }
  1354. //set default flags if not defined by caller
  1355. if (0x0 == (dwFlags & SCARD_ENROLL_USER_CERT_TEMPLATE) &&
  1356. 0x0 == (dwFlags & SCARD_ENROLL_MACHINE_CERT_TEMPLATE))
  1357. {
  1358. //assume both machine and user
  1359. dwFlags |= SCARD_ENROLL_USER_CERT_TEMPLATE |
  1360. SCARD_ENROLL_MACHINE_CERT_TEMPLATE;
  1361. }
  1362. if (0x0 == (dwFlags & SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE) &&
  1363. 0x0 == (dwFlags & SCARD_ENROLL_OFFLINE_CERT_TEMPLATE))
  1364. {
  1365. //assume both enterprise and offline
  1366. dwFlags |= SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE |
  1367. SCARD_ENROLL_OFFLINE_CERT_TEMPLATE;
  1368. }
  1369. for (dwIdx = 0; dwIdx < m_dwCTCount; dwIdx++)
  1370. {
  1371. if (0x0 == (dwFlags & SCARD_ENROLL_CROSS_CERT_TEMPLATE) &&
  1372. 0 < m_rgCTInfo[dwIdx].dwRASignature)
  1373. {
  1374. //don't include template require signatures
  1375. continue;
  1376. }
  1377. if((0x0 != (SCARD_ENROLL_USER_CERT_TEMPLATE & dwFlags) &&
  1378. FALSE == m_rgCTInfo[dwIdx].fMachine) ||
  1379. (0x0 != (SCARD_ENROLL_MACHINE_CERT_TEMPLATE & dwFlags) &&
  1380. TRUE == m_rgCTInfo[dwIdx].fMachine))
  1381. {
  1382. if (0 != (SCARD_ENROLL_ENTERPRISE_CERT_TEMPLATE & dwFlags) &&
  1383. 0 == (OFFLINE_SUBJECT_NAME_FLAGS &
  1384. m_rgCTInfo[dwIdx].dwSubjectNameFlags))
  1385. {
  1386. //enterprise user/machine and no subject DN required
  1387. dwValidCount++;
  1388. }
  1389. else if (0 != (SCARD_ENROLL_OFFLINE_CERT_TEMPLATE & dwFlags) &&
  1390. 0 != (OFFLINE_SUBJECT_NAME_FLAGS &
  1391. m_rgCTInfo[dwIdx].dwSubjectNameFlags))
  1392. {
  1393. //offline user/machine and subject DN required
  1394. dwValidCount++;
  1395. }
  1396. }
  1397. if (!fCount && dwValidCount == (dwIndex + 1))
  1398. {
  1399. //get name & hit the one by index. get display or real name
  1400. if (0x0 != (dwFlags & SCARD_ENROLL_CERT_TEMPLATE_DISPLAY_NAME))
  1401. {
  1402. //display name
  1403. pwszName = m_rgCTInfo[dwIdx].pwszCTDisplayName;
  1404. }
  1405. else
  1406. {
  1407. //real name
  1408. pwszName = m_rgCTInfo[dwIdx].pwszCTName;
  1409. }
  1410. *pbstrCertTemplateName = SysAllocString(pwszName);
  1411. if (NULL == *pbstrCertTemplateName)
  1412. {
  1413. goto MemoryErr;
  1414. }
  1415. else
  1416. {
  1417. //done
  1418. break;
  1419. }
  1420. }
  1421. }
  1422. if(!fCount && dwIdx == m_dwCTCount)
  1423. {
  1424. //go beyond
  1425. goto NoItemErr;
  1426. }
  1427. if (fCount)
  1428. {
  1429. *pdwCertTemplateCount = dwValidCount;
  1430. }
  1431. hr = S_OK;
  1432. CommonReturn:
  1433. LeaveCriticalSection(&m_cSection);
  1434. SetLastError(errBefore);
  1435. return hr;
  1436. ErrorReturn:
  1437. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1438. errBefore=E_UNEXPECTED;
  1439. hr = CodeToHR(errBefore);
  1440. goto CommonReturn;
  1441. SET_ERROR(InvalidArgErr, E_INVALIDARG)
  1442. SET_ERROR(InvalidParamErr, HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER))
  1443. SET_ERROR(MemoryErr, E_OUTOFMEMORY)
  1444. SET_ERROR(NoItemErr,ERROR_NO_MORE_ITEMS)
  1445. }
  1446. STDMETHODIMP CSCrdEnr::enumCertTemplateName
  1447. (/* [in] */ DWORD dwIndex,
  1448. /* [in] */ DWORD dwFlags,
  1449. /* [retval][out] */ BSTR *pbstrCertTemplateName)
  1450. {
  1451. return CertTemplateCountOrName(
  1452. dwIndex,
  1453. dwFlags,
  1454. NULL, //get name
  1455. pbstrCertTemplateName);
  1456. }
  1457. HRESULT CSCrdEnr::_getCertTemplateExtensionInfo(
  1458. IN CERT_EXTENSIONS *pCertTypeExtensions,
  1459. IN LONG lType,
  1460. OUT VOID *pExtInfo)
  1461. {
  1462. HRESULT hr;
  1463. DWORD cwc = 0;
  1464. DWORD dwCTE;
  1465. DWORD i;
  1466. BOOL fV2 = FALSE; //default v1 template
  1467. BOOL fDword = TRUE;
  1468. DWORD dwValue;
  1469. EnterCriticalSection(&m_cSection);
  1470. if (NULL == m_pCachedCTEs || m_pCachedCTEs != pCertTypeExtensions)
  1471. {
  1472. //new template, don't use cache
  1473. //free the current cache if any
  1474. if (NULL != m_pwszCachedCTEOid)
  1475. {
  1476. LocalFree(m_pwszCachedCTEOid);
  1477. m_pwszCachedCTEOid = NULL;
  1478. }
  1479. if (NULL != m_pCachedCTE)
  1480. {
  1481. LocalFree(m_pCachedCTE);
  1482. m_pCachedCTE = NULL;
  1483. }
  1484. //reset extension pointer
  1485. m_pCachedCTEs = NULL;
  1486. //loop to find CT extension
  1487. for (i = 0; i < pCertTypeExtensions->cExtension; ++i)
  1488. {
  1489. if (0 == _stricmp(pCertTypeExtensions->rgExtension[i].pszObjId,
  1490. szOID_CERTIFICATE_TEMPLATE))
  1491. {
  1492. //v2 template
  1493. fV2 = TRUE;
  1494. //cache it
  1495. m_pCachedCTEs = pCertTypeExtensions;
  1496. break;
  1497. }
  1498. }
  1499. if (!fV2)
  1500. {
  1501. //v1 template, return empty string
  1502. m_pwszCachedCTEOid = (WCHAR*)LocalAlloc(LMEM_FIXED, sizeof(WCHAR));
  1503. if (NULL == m_pwszCachedCTEOid)
  1504. {
  1505. hr = E_OUTOFMEMORY;
  1506. goto MemoryErr;
  1507. }
  1508. m_pwszCachedCTEOid[0] = L'\0';
  1509. }
  1510. else
  1511. {
  1512. //decode cert template extension
  1513. if (!CryptDecodeObjectEx(
  1514. X509_ASN_ENCODING,
  1515. X509_CERTIFICATE_TEMPLATE,
  1516. pCertTypeExtensions->rgExtension[i].Value.pbData,
  1517. pCertTypeExtensions->rgExtension[i].Value.cbData,
  1518. CRYPT_DECODE_ALLOC_FLAG,
  1519. NULL, //use default LocalAlloc
  1520. (void*)&m_pCachedCTE,
  1521. &dwCTE))
  1522. {
  1523. hr = HRESULT_FROM_WIN32(GetLastError());
  1524. goto CryptDecodeObjectExErr;
  1525. }
  1526. //have to convert asn to wchar
  1527. while (TRUE)
  1528. {
  1529. cwc = MultiByteToWideChar(
  1530. GetACP(),
  1531. 0,
  1532. m_pCachedCTE->pszObjId,
  1533. -1,
  1534. m_pwszCachedCTEOid,
  1535. cwc);
  1536. if (0 >= cwc)
  1537. {
  1538. hr = HRESULT_FROM_WIN32(GetLastError());
  1539. goto MultiByteToWideCharErr;
  1540. }
  1541. if (NULL != m_pwszCachedCTEOid)
  1542. {
  1543. //done
  1544. break;
  1545. }
  1546. m_pwszCachedCTEOid = (WCHAR*)LocalAlloc(LMEM_FIXED,
  1547. cwc * sizeof(WCHAR));
  1548. if (NULL == m_pwszCachedCTEOid)
  1549. {
  1550. hr = E_OUTOFMEMORY;
  1551. goto MemoryErr;
  1552. }
  1553. }
  1554. }
  1555. }
  1556. //hit here, either from cached or new cache
  1557. switch (lType)
  1558. {
  1559. case SCARD_CTINFO_EXT_OID:
  1560. *(WCHAR**)pExtInfo = m_pwszCachedCTEOid;
  1561. break;
  1562. case SCARD_CTINFO_EXT_MAJOR:
  1563. if (NULL != m_pCachedCTE)
  1564. {
  1565. *(LONG*)pExtInfo = m_pCachedCTE->dwMajorVersion;
  1566. }
  1567. else
  1568. {
  1569. //must be v1
  1570. *(LONG*)pExtInfo = 0;
  1571. }
  1572. break;
  1573. case SCARD_CTINFO_EXT_MINOR:
  1574. if (NULL != m_pCachedCTE)
  1575. {
  1576. *(LONG*)pExtInfo = m_pCachedCTE->dwMinorVersion;
  1577. }
  1578. else
  1579. {
  1580. //must be v1
  1581. *(LONG*)pExtInfo = 0;
  1582. }
  1583. break;
  1584. case SCARD_CTINFO_EXT_MINOR_FLAG:
  1585. if (NULL != m_pCachedCTE)
  1586. {
  1587. *(LONG*)pExtInfo = m_pCachedCTE->fMinorVersion;
  1588. }
  1589. else
  1590. {
  1591. //must be v1
  1592. *(LONG*)pExtInfo = 0;
  1593. }
  1594. break;
  1595. default:
  1596. hr = E_INVALIDARG;
  1597. goto InvalidArgError;
  1598. }
  1599. hr = S_OK;
  1600. ErrorReturn:
  1601. LeaveCriticalSection(&m_cSection);
  1602. return hr;
  1603. TRACE_ERROR(CryptDecodeObjectExErr)
  1604. TRACE_ERROR(MemoryErr)
  1605. TRACE_ERROR(MultiByteToWideCharErr)
  1606. TRACE_ERROR(InvalidArgError)
  1607. }
  1608. HRESULT CSCrdEnr::_getStrCertTemplateCSPList(
  1609. IN DWORD dwIndex,
  1610. IN DWORD dwFlag,
  1611. OUT WCHAR **ppwszSupportedCSP)
  1612. {
  1613. HRESULT hr;
  1614. DWORD i;
  1615. WCHAR **ppwsz;
  1616. WCHAR *pwszOut = NULL;
  1617. EnterCriticalSection(&m_cSection);
  1618. //init
  1619. *ppwszSupportedCSP = NULL;
  1620. if (SCARD_CTINFO_CSPLIST_FIRST == dwFlag)
  1621. {
  1622. //reset to first
  1623. m_rgCTInfo[dwIndex].dwCurrentCSP = 0;
  1624. }
  1625. //get it
  1626. ppwsz = m_rgCTInfo[dwIndex].rgpwszSupportedCSPs;
  1627. for (i = 0; i < m_rgCTInfo[dwIndex].dwCurrentCSP && NULL != *ppwsz; ++i)
  1628. {
  1629. ++ppwsz;
  1630. }
  1631. if (NULL == *ppwsz)
  1632. {
  1633. //hit the end
  1634. hr = HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS);
  1635. goto NoMoreItemsErr;
  1636. }
  1637. // allocate buffer
  1638. pwszOut = (WCHAR*)LocalAlloc(LMEM_FIXED, (wcslen(*ppwsz) + 1) * sizeof(WCHAR));
  1639. if (NULL == pwszOut)
  1640. {
  1641. hr = E_OUTOFMEMORY;
  1642. goto MemoryErr;
  1643. }
  1644. //copy string
  1645. wcscpy(pwszOut, *ppwsz);
  1646. *ppwszSupportedCSP = pwszOut;
  1647. pwszOut = NULL;
  1648. ++m_rgCTInfo[dwIndex].dwCurrentCSP;
  1649. hr = S_OK;
  1650. ErrorReturn:
  1651. LeaveCriticalSection(&m_cSection);
  1652. if (NULL != pwszOut)
  1653. {
  1654. LocalFree(pwszOut);
  1655. }
  1656. return hr;
  1657. TRACE_ERROR(MemoryErr)
  1658. TRACE_ERROR(NoMoreItemsErr)
  1659. }
  1660. STDMETHODIMP CSCrdEnr::getCertTemplateInfo(
  1661. /* [in] */ BSTR bstrCertTemplateName,
  1662. /* [in] */ LONG lType,
  1663. /* [retval][out] */ VARIANT *pvarCertTemplateInfo)
  1664. {
  1665. HRESULT hr;
  1666. DWORD dwIndex;
  1667. WCHAR *pwszInfo = NULL;
  1668. BOOL fFound = FALSE;
  1669. DWORD dwCSPFlag = SCARD_CTINFO_CSPLIST_NEXT;
  1670. LONG lInfo;
  1671. BOOL fStr = FALSE; //default to long
  1672. BOOL fFree = TRUE;
  1673. VARIANT varInfo;
  1674. ZeroMemory(&varInfo, sizeof(varInfo));
  1675. EnterCriticalSection(&m_cSection);
  1676. if (NULL == bstrCertTemplateName ||
  1677. 0 == m_dwCTCount ||
  1678. NULL == m_rgCTInfo)
  1679. {
  1680. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1681. goto InvalidParamErr;
  1682. }
  1683. //get the CT information
  1684. for (dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
  1685. {
  1686. if (0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
  1687. {
  1688. // found it
  1689. fFound = TRUE;
  1690. break;
  1691. }
  1692. }
  1693. if (!fFound)
  1694. {
  1695. //likely pass incorrect template name
  1696. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  1697. goto NotFoundErr;
  1698. }
  1699. switch (lType)
  1700. {
  1701. case SCARD_CTINFO_KEYSPEC:
  1702. lInfo = m_rgCTInfo[dwIndex].dwKeySpec;
  1703. break;
  1704. case SCARD_CTINFO_KEYFLAGS:
  1705. lInfo = m_rgCTInfo[dwIndex].dwGenKeyFlags;
  1706. break;
  1707. case SCARD_CTINFO_EXT_OID:
  1708. hr = _getCertTemplateExtensionInfo(
  1709. m_rgCTInfo[dwIndex].pCertTypeExtensions,
  1710. lType,
  1711. &pwszInfo);
  1712. if (S_OK != hr)
  1713. {
  1714. goto _getCertTemplateExtensionInfoErr;
  1715. }
  1716. fStr = TRUE;
  1717. fFree = FALSE; //don't free cache
  1718. break;
  1719. case SCARD_CTINFO_EXT_MAJOR:
  1720. case SCARD_CTINFO_EXT_MINOR:
  1721. case SCARD_CTINFO_EXT_MINOR_FLAG:
  1722. hr = _getCertTemplateExtensionInfo(
  1723. m_rgCTInfo[dwIndex].pCertTypeExtensions,
  1724. lType,
  1725. &lInfo);
  1726. if (S_OK != hr)
  1727. {
  1728. goto _getCertTemplateExtensionInfoErr;
  1729. }
  1730. break;
  1731. case SCARD_CTINFO_CSPLIST_FIRST:
  1732. dwCSPFlag = SCARD_CTINFO_CSPLIST_FIRST;
  1733. //fall through
  1734. case SCARD_CTINFO_CSPLIST_NEXT:
  1735. hr = _getStrCertTemplateCSPList(dwIndex, dwCSPFlag, &pwszInfo);
  1736. if (S_OK != hr)
  1737. {
  1738. goto _getStrCertTemplateCSPListErr;
  1739. }
  1740. fStr = TRUE;
  1741. break;
  1742. case SCARD_CTINFO_SUBJECTFLAG:
  1743. lInfo = m_rgCTInfo[dwIndex].dwSubjectNameFlags;
  1744. break;
  1745. case SCARD_CTINFO_GENERALFLAGS:
  1746. lInfo = m_rgCTInfo[dwIndex].dwGeneralFlags;
  1747. break;
  1748. case SCARD_CTINFO_ENROLLMENTFLAGS:
  1749. lInfo = m_rgCTInfo[dwIndex].dwEnrollmentFlags;
  1750. break;
  1751. case SCARD_CTINFO_PRIVATEKEYFLAGS:
  1752. lInfo = m_rgCTInfo[dwIndex].dwPrivateKeyFlags;
  1753. break;
  1754. case SCARD_CTINFO_RA_SIGNATURES:
  1755. lInfo = m_rgCTInfo[dwIndex].dwRASignature;
  1756. break;
  1757. default:
  1758. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1759. goto InvalidParamErr;
  1760. }
  1761. if (fStr)
  1762. {
  1763. varInfo.vt = VT_BSTR;
  1764. varInfo.bstrVal = SysAllocString(pwszInfo);
  1765. if (NULL == varInfo.bstrVal)
  1766. {
  1767. hr = E_OUTOFMEMORY;
  1768. goto MemoryErr;
  1769. }
  1770. }
  1771. else
  1772. {
  1773. varInfo.vt = VT_I4;
  1774. varInfo.lVal = lInfo;
  1775. }
  1776. //return
  1777. *pvarCertTemplateInfo = varInfo;
  1778. hr = S_OK;
  1779. ErrorReturn:
  1780. LeaveCriticalSection(&m_cSection);
  1781. if (fFree && NULL != pwszInfo)
  1782. {
  1783. LocalFree(pwszInfo);
  1784. }
  1785. return hr;
  1786. TRACE_ERROR(InvalidParamErr)
  1787. TRACE_ERROR(NotFoundErr)
  1788. TRACE_ERROR(MemoryErr)
  1789. TRACE_ERROR(_getCertTemplateExtensionInfoErr)
  1790. TRACE_ERROR(_getStrCertTemplateCSPListErr)
  1791. }
  1792. STDMETHODIMP CSCrdEnr::getCACount
  1793. (/* [in] */ BSTR bstrCertTemplateName,
  1794. /* [retval][out] */ long *pdwCACount)
  1795. {
  1796. HRESULT hr= E_FAIL;
  1797. DWORD errBefore= GetLastError();
  1798. DWORD dwIndex=0;
  1799. EnterCriticalSection(&m_cSection);
  1800. if(NULL == bstrCertTemplateName || NULL == pdwCACount)
  1801. goto InvalidArgErr;
  1802. *pdwCACount=0;
  1803. if(0 == m_dwCTCount || NULL == m_rgCTInfo)
  1804. goto InvalidArgErr;
  1805. //get the CT information
  1806. for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
  1807. {
  1808. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
  1809. break;
  1810. }
  1811. if(dwIndex == m_dwCTCount)
  1812. goto InvalidArgErr;
  1813. //we need to get the CA information for the newly selected cert type
  1814. if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
  1815. {
  1816. GetCAInfoFromCertType(NULL,
  1817. m_rgCTInfo[dwIndex].pwszCTName,
  1818. &(m_rgCTInfo[dwIndex].dwCACount),
  1819. &(m_rgCTInfo[dwIndex].rgCAInfo));
  1820. m_rgCTInfo[dwIndex].dwCAIndex=0;
  1821. m_rgCTInfo[dwIndex].fCAInfo=TRUE;
  1822. }
  1823. *pdwCACount = (long)m_rgCTInfo[dwIndex].dwCACount;
  1824. hr=S_OK;
  1825. CommonReturn:
  1826. LeaveCriticalSection(&m_cSection);
  1827. SetLastError(errBefore);
  1828. return hr;
  1829. ErrorReturn:
  1830. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1831. errBefore=E_UNEXPECTED;
  1832. hr = CodeToHR(errBefore);
  1833. goto CommonReturn;
  1834. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1835. }
  1836. STDMETHODIMP CSCrdEnr::getCAName
  1837. (/* [in] */ DWORD dwFlags,
  1838. /* [in] */ BSTR bstrCertTemplateName,
  1839. /* [retval][out] */ BSTR *pbstrCAName)
  1840. {
  1841. HRESULT hr= E_FAIL;
  1842. DWORD errBefore= GetLastError();
  1843. DWORD dwIndex=0;
  1844. LPWSTR pwszName=NULL;
  1845. SCrdEnroll_CT_INFO *pCTInfo=NULL;
  1846. EnterCriticalSection(&m_cSection);
  1847. if(NULL == bstrCertTemplateName || NULL == pbstrCAName)
  1848. goto InvalidArgErr;
  1849. *pbstrCAName=NULL;
  1850. if(0 == m_dwCTCount || NULL == m_rgCTInfo)
  1851. goto InvalidArgErr;
  1852. //get the CT information
  1853. for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
  1854. {
  1855. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
  1856. break;
  1857. }
  1858. if(dwIndex == m_dwCTCount)
  1859. goto InvalidArgErr;
  1860. //we need to get the CA information for the newly selected cert type
  1861. if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
  1862. {
  1863. GetCAInfoFromCertType(NULL,
  1864. m_rgCTInfo[dwIndex].pwszCTName,
  1865. &(m_rgCTInfo[dwIndex].dwCACount),
  1866. &(m_rgCTInfo[dwIndex].rgCAInfo));
  1867. m_rgCTInfo[dwIndex].dwCAIndex=0;
  1868. m_rgCTInfo[dwIndex].fCAInfo=TRUE;
  1869. }
  1870. pCTInfo=&(m_rgCTInfo[dwIndex]);
  1871. if(NULL == pCTInfo->rgCAInfo)
  1872. goto InvalidArgErr;
  1873. if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[pCTInfo->dwCAIndex]), &pwszName))
  1874. goto TraceErr;
  1875. if(NULL == (*pbstrCAName = SysAllocString(pwszName)))
  1876. goto MemoryErr;
  1877. hr=S_OK;
  1878. CommonReturn:
  1879. LeaveCriticalSection(&m_cSection);
  1880. if(pwszName)
  1881. SCrdEnrollFree(pwszName);
  1882. SetLastError(errBefore);
  1883. return hr;
  1884. ErrorReturn:
  1885. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1886. errBefore=E_UNEXPECTED;
  1887. hr = CodeToHR(errBefore);
  1888. goto CommonReturn;
  1889. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1890. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  1891. TRACE_ERROR(TraceErr);
  1892. }
  1893. STDMETHODIMP CSCrdEnr::setCAName
  1894. (/* [in] */ DWORD dwFlags,
  1895. /* [in] */ BSTR bstrCertTemplateName,
  1896. /* [in] */ BSTR bstrCAName)
  1897. {
  1898. HRESULT hr= E_FAIL;
  1899. DWORD errBefore= GetLastError();
  1900. DWORD dwIndex=0;
  1901. DWORD dwCAIndex=0;
  1902. LPWSTR pwszName=NULL;
  1903. SCrdEnroll_CT_INFO *pCTInfo=NULL;
  1904. EnterCriticalSection(&m_cSection);
  1905. if(NULL == bstrCertTemplateName || NULL == bstrCAName)
  1906. goto InvalidArgErr;
  1907. if(0 == m_dwCTCount || NULL == m_rgCTInfo)
  1908. goto InvalidArgErr;
  1909. //get the CT information
  1910. for(dwIndex=0; dwIndex < m_dwCTCount; dwIndex++)
  1911. {
  1912. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwIndex].pwszCTName))
  1913. break;
  1914. }
  1915. if(dwIndex == m_dwCTCount)
  1916. goto InvalidArgErr;
  1917. //we need to get the CA information for the newly selected cert type
  1918. if(FALSE == m_rgCTInfo[dwIndex].fCAInfo)
  1919. {
  1920. GetCAInfoFromCertType(NULL,
  1921. m_rgCTInfo[dwIndex].pwszCTName,
  1922. &(m_rgCTInfo[dwIndex].dwCACount),
  1923. &(m_rgCTInfo[dwIndex].rgCAInfo));
  1924. m_rgCTInfo[dwIndex].dwCAIndex=0;
  1925. m_rgCTInfo[dwIndex].fCAInfo=TRUE;
  1926. }
  1927. pCTInfo=&(m_rgCTInfo[dwIndex]);
  1928. if(NULL == pCTInfo->rgCAInfo)
  1929. goto InvalidArgErr;
  1930. //search for the CA specified in the input
  1931. for(dwCAIndex=0; dwCAIndex < pCTInfo->dwCACount; dwCAIndex++)
  1932. {
  1933. if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[dwCAIndex]), &pwszName))
  1934. continue;
  1935. if(0 == _wcsicmp(pwszName, bstrCAName))
  1936. break;
  1937. SCrdEnrollFree(pwszName);
  1938. pwszName=NULL;
  1939. }
  1940. if(dwCAIndex == pCTInfo->dwCACount)
  1941. goto InvalidArgErr;
  1942. //remember the selected CA by its index
  1943. pCTInfo->dwCAIndex = dwCAIndex;
  1944. hr=S_OK;
  1945. CommonReturn:
  1946. LeaveCriticalSection(&m_cSection);
  1947. if(pwszName)
  1948. SCrdEnrollFree(pwszName);
  1949. SetLastError(errBefore);
  1950. return hr;
  1951. ErrorReturn:
  1952. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  1953. errBefore=E_UNEXPECTED;
  1954. hr = CodeToHR(errBefore);
  1955. goto CommonReturn;
  1956. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  1957. }
  1958. STDMETHODIMP CSCrdEnr::enumCAName
  1959. (/* [in] */ DWORD dwIndex,
  1960. /* [in] */ DWORD dwFlags,
  1961. /* [in] */ BSTR bstrCertTemplateName,
  1962. /* [retval][out] */ BSTR *pbstrCAName)
  1963. {
  1964. HRESULT hr= E_FAIL;
  1965. DWORD errBefore= GetLastError();
  1966. DWORD dwCTIndex=0;
  1967. LPWSTR pwszName=NULL;
  1968. SCrdEnroll_CT_INFO *pCTInfo=NULL;
  1969. EnterCriticalSection(&m_cSection);
  1970. if(NULL == bstrCertTemplateName || NULL == pbstrCAName)
  1971. goto InvalidArgErr;
  1972. *pbstrCAName=NULL;
  1973. if(0 == m_dwCTCount || NULL == m_rgCTInfo)
  1974. goto InvalidArgErr;
  1975. //get the CT information
  1976. for(dwCTIndex=0; dwCTIndex < m_dwCTCount; dwCTIndex++)
  1977. {
  1978. if(0 == _wcsicmp(bstrCertTemplateName, m_rgCTInfo[dwCTIndex].pwszCTName))
  1979. break;
  1980. }
  1981. if(dwCTIndex == m_dwCTCount)
  1982. goto InvalidArgErr;
  1983. //we need to get the CA information for the newly selected cert type
  1984. if(FALSE == m_rgCTInfo[dwCTIndex].fCAInfo)
  1985. {
  1986. GetCAInfoFromCertType(NULL,
  1987. m_rgCTInfo[dwCTIndex].pwszCTName,
  1988. &(m_rgCTInfo[dwCTIndex].dwCACount),
  1989. &(m_rgCTInfo[dwCTIndex].rgCAInfo));
  1990. m_rgCTInfo[dwCTIndex].dwCAIndex=0;
  1991. m_rgCTInfo[dwCTIndex].fCAInfo=TRUE;
  1992. }
  1993. pCTInfo=&(m_rgCTInfo[dwCTIndex]);
  1994. //search for the CA specified in the input
  1995. if(dwIndex >= pCTInfo->dwCACount)
  1996. goto InvalidArgErr;
  1997. if(!RetrieveCAName(dwFlags, &(pCTInfo->rgCAInfo[dwIndex]), &pwszName))
  1998. goto TraceErr;
  1999. if(NULL == (*pbstrCAName = SysAllocString(pwszName)))
  2000. goto MemoryErr;
  2001. hr=S_OK;
  2002. CommonReturn:
  2003. LeaveCriticalSection(&m_cSection);
  2004. if(pwszName)
  2005. SCrdEnrollFree(pwszName);
  2006. SetLastError(errBefore);
  2007. return hr;
  2008. ErrorReturn:
  2009. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  2010. errBefore=E_UNEXPECTED;
  2011. hr = CodeToHR(errBefore);
  2012. goto CommonReturn;
  2013. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2014. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2015. TRACE_ERROR(TraceErr);
  2016. }
  2017. STDMETHODIMP CSCrdEnr::getSigningCertificateName
  2018. (/* [in] */ DWORD dwFlags,
  2019. /* [retval][out] */ BSTR *pbstrSigningCertName)
  2020. {
  2021. HRESULT hr= E_FAIL;
  2022. DWORD errBefore= GetLastError();
  2023. DWORD dwChar=0;
  2024. LPWSTR pwsz=NULL;
  2025. CRYPTUI_VIEWCERTIFICATE_STRUCT CertViewStruct;
  2026. *pbstrSigningCertName=NULL;
  2027. EnterCriticalSection(&m_cSection);
  2028. if(NULL == m_pSigningCert)
  2029. goto InvalidArgErr;
  2030. if(0 == (SCARD_ENROLL_NO_DISPLAY_CERT & dwFlags))
  2031. {
  2032. //view the certificate
  2033. memset(&CertViewStruct, 0, sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT));
  2034. CertViewStruct.dwSize=sizeof(CRYPTUI_VIEWCERTIFICATE_STRUCT);
  2035. CertViewStruct.pCertContext=m_pSigningCert;
  2036. CertViewStruct.dwFlags=CRYPTUI_DISABLE_EDITPROPERTIES | CRYPTUI_DISABLE_ADDTOSTORE;
  2037. CryptUIDlgViewCertificate(&CertViewStruct, NULL);
  2038. }
  2039. dwChar=CertGetNameStringW(
  2040. m_pSigningCert,
  2041. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2042. 0,
  2043. NULL,
  2044. NULL,
  2045. 0);
  2046. if ((dwChar != 0) && (NULL != (pwsz = (LPWSTR)SCrdEnrollAlloc(dwChar * sizeof(WCHAR)))))
  2047. {
  2048. CertGetNameStringW(
  2049. m_pSigningCert,
  2050. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2051. 0,
  2052. NULL,
  2053. pwsz,
  2054. dwChar);
  2055. if( NULL == (*pbstrSigningCertName = SysAllocString(pwsz)))
  2056. goto MemoryErr;
  2057. }
  2058. hr= S_OK;
  2059. CommonReturn:
  2060. LeaveCriticalSection(&m_cSection);
  2061. if(pwsz)
  2062. SCrdEnrollFree(pwsz);
  2063. SetLastError(errBefore);
  2064. return hr;
  2065. ErrorReturn:
  2066. if(ERROR_SUCCESS == (errBefore = GetLastError()))
  2067. errBefore=E_UNEXPECTED;
  2068. hr = CodeToHR(errBefore);
  2069. goto CommonReturn;
  2070. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  2071. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  2072. }