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.

12798 lines
368 KiB

  1. //depot/Lab03_DEV/Ds/security/cryptoapi/pki/activex/xenroll/cenroll.cpp#4 - edit change 19979 (text)
  2. //+-------------------------------------------------------------------------
  3. //
  4. // Microsoft Windows
  5. //
  6. // Copyright (C) Microsoft Corporation, 1997 - 1999
  7. //
  8. // File: cenroll.cpp
  9. //
  10. //--------------------------------------------------------------------------
  11. // CEnroll.cpp : Implementation of CCEnroll
  12. #include "stdafx.h"
  13. #include <windows.h>
  14. #include <wincrypt.h>
  15. #include <unicode.h>
  16. #define SECURITY_WIN32
  17. #include <security.h>
  18. #include <aclapi.h>
  19. #include <pvk.h>
  20. #include <wintrust.h>
  21. #include <xasn.h>
  22. #include <autoenr.h>
  23. #include <sddl.h>
  24. #include "xenroll.h"
  25. #include "cenroll.h"
  26. #include "xelib.h"
  27. #include "sfscript.h"
  28. #define NO_OSS_DEBUG
  29. #include <dbgdef.h>
  30. #include <string.h>
  31. #include <assert.h>
  32. static LPVOID (* MyCoTaskMemAlloc)(ULONG) = NULL;
  33. static LPVOID (* MyCoTaskMemRealloc)(LPVOID, ULONG) = NULL;
  34. static void (* MyCoTaskMemFree)(LPVOID) = NULL;
  35. #define MY_HRESULT_FROM_WIN32(a) ((a >= 0x80000000) ? a : HRESULT_FROM_WIN32(a))
  36. #ifndef NTE_TOKEN_KEYSET_STORAGE_FULL
  37. #define NTE_TOKEN_KEYSET_STORAGE_FULL _HRESULT_TYPEDEF_(0x80090023L)
  38. #endif
  39. #define CEnrollLocalScope(ScopeName) struct ScopeName##TheLocalScope { public
  40. #define CEnrollEndLocalScope } local
  41. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  42. #pragma warning(disable:4213) // nonstandard extension used : cast on l-value
  43. static LPSTR MBFromWide(LPCWSTR wsz) {
  44. LPSTR sz = NULL;
  45. DWORD cb = 0;
  46. assert(wsz != NULL);
  47. if(wsz == NULL) {
  48. SetLastError(ERROR_INVALID_PARAMETER);
  49. return(NULL);
  50. }
  51. if( (cb = WideCharToMultiByte(0, 0, wsz, -1, NULL, 0, NULL, NULL)) == 0 ||
  52. (sz = (char *) MyCoTaskMemAlloc(cb)) == NULL ||
  53. (cb = WideCharToMultiByte(0, 0, wsz, -1, sz, cb, NULL, NULL)) == 0 ) {
  54. if(GetLastError() == ERROR_SUCCESS)
  55. SetLastError(ERROR_OUTOFMEMORY);
  56. return(NULL);
  57. }
  58. return(sz);
  59. }
  60. static LPWSTR WideFromMB(LPCSTR sz) {
  61. DWORD cch = 0;
  62. LPWSTR wsz = NULL;
  63. assert(sz != NULL);
  64. if(sz == NULL) {
  65. SetLastError(ERROR_INVALID_PARAMETER);
  66. return(NULL);
  67. }
  68. if( (cch = MultiByteToWideChar(0, 0, sz, -1, NULL, 0)) == 0 ||
  69. (wsz = (WCHAR *) MyCoTaskMemAlloc(cch * sizeof(WCHAR))) == NULL ||
  70. (cch = MultiByteToWideChar(0, 0, sz, -1, wsz, cch)) == 0) {
  71. if(GetLastError() == ERROR_SUCCESS)
  72. SetLastError(ERROR_OUTOFMEMORY);
  73. return(NULL);
  74. }
  75. return(wsz);
  76. }
  77. static BSTR
  78. BSTRFromMB(LPCSTR sz)
  79. {
  80. BSTR bstr = NULL;
  81. DWORD cch = 0;
  82. WCHAR *pwsz = NULL;
  83. BOOL fFail = FALSE;
  84. assert(sz != NULL);
  85. if(sz == NULL) {
  86. SetLastError(ERROR_INVALID_PARAMETER);
  87. return(NULL);
  88. }
  89. while (TRUE)
  90. {
  91. if(0 == (cch = MultiByteToWideChar(0, 0, sz, -1, pwsz, cch)))
  92. {
  93. //error
  94. fFail = TRUE;
  95. break;
  96. }
  97. if (NULL != pwsz)
  98. {
  99. //done
  100. break;
  101. }
  102. pwsz = (WCHAR *)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR));
  103. if (NULL == pwsz)
  104. {
  105. //error
  106. if(GetLastError() == ERROR_SUCCESS)
  107. SetLastError(ERROR_OUTOFMEMORY);
  108. break;
  109. }
  110. }
  111. if (!fFail && NULL != pwsz)
  112. {
  113. bstr = SysAllocString(pwsz);
  114. if (NULL == bstr)
  115. {
  116. if(GetLastError() == ERROR_SUCCESS)
  117. SetLastError(ERROR_OUTOFMEMORY);
  118. }
  119. }
  120. if (NULL != pwsz)
  121. {
  122. LocalFree(pwsz);
  123. }
  124. return(bstr);
  125. }
  126. static LPWSTR CopyWideString(LPCWSTR wsz) {
  127. size_t cch = 0;
  128. LPWSTR wszOut = NULL;
  129. // shouldn't send in a NULL
  130. assert(wsz != NULL);
  131. if(wsz == NULL) {
  132. SetLastError(ERROR_INVALID_PARAMETER);
  133. return(NULL);
  134. }
  135. cch = wcslen(wsz) + 1;
  136. if (cch*sizeof(WCHAR) > (ULONG)-1) {
  137. // prevent errors caused by conversion from size_t --> ULONG
  138. SetLastError(ERROR_INVALID_PARAMETER);
  139. return(NULL);
  140. }
  141. if( (wszOut = (LPWSTR) MyCoTaskMemAlloc((ULONG)(sizeof(WCHAR) * cch))) == NULL ) {
  142. SetLastError(ERROR_OUTOFMEMORY);
  143. return(NULL);
  144. }
  145. wcscpy(wszOut, wsz);
  146. return(wszOut);
  147. }
  148. static LPSTR CopyAsciiString(LPCSTR sz) {
  149. size_t cch = 0;
  150. LPSTR szOut = NULL;
  151. // shouldn't send in a NULL
  152. assert(sz != NULL);
  153. if(sz == NULL) {
  154. SetLastError(ERROR_INVALID_PARAMETER);
  155. return(NULL);
  156. }
  157. cch = strlen(sz) + 1;
  158. if (cch > (ULONG)-1) {
  159. // prevent errors caused by conversion from size_t --> ULONG
  160. SetLastError(ERROR_INVALID_PARAMETER);
  161. return(NULL);
  162. }
  163. if( (szOut = (LPSTR) MyCoTaskMemAlloc((ULONG)cch)) == NULL ) {
  164. SetLastError(ERROR_OUTOFMEMORY);
  165. return(NULL);
  166. }
  167. strcpy(szOut, sz);
  168. return(szOut);
  169. }
  170. static DWORD KeyLocationFromStoreLocation(DWORD dwStoreFlags) {
  171. if(
  172. ((CERT_SYSTEM_STORE_LOCATION_MASK & dwStoreFlags) == CERT_SYSTEM_STORE_CURRENT_USER) ||
  173. ((CERT_SYSTEM_STORE_LOCATION_MASK & dwStoreFlags) == CERT_SYSTEM_STORE_USERS) ||
  174. ((CERT_SYSTEM_STORE_LOCATION_MASK & dwStoreFlags) == CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY)
  175. ) {
  176. return(0);
  177. }
  178. // CERT_SYSTEM_STORE_LOCAL_MACHINE
  179. // CERT_SYSTEM_STORE_DOMAIN_POLICY
  180. // CERT_SYSTEM_STORE_CURRENT_SERVICE
  181. // CERT_SYSTEM_STORE_SERVICES
  182. // CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY
  183. return(CRYPT_MACHINE_KEYSET);
  184. }
  185. //modified from myLoadRCString from ca
  186. HRESULT
  187. xeLoadRCString(
  188. IN HINSTANCE hInstance,
  189. IN int iRCId,
  190. OUT WCHAR **ppwsz)
  191. {
  192. #define REALLOCATEBLOCK 512
  193. HRESULT hr;
  194. WCHAR *pwszTemp = NULL;
  195. int sizeTemp;
  196. int size = 0;
  197. int cBlocks = 1;
  198. *ppwsz = NULL;
  199. while (NULL == pwszTemp)
  200. {
  201. sizeTemp = cBlocks * REALLOCATEBLOCK;
  202. pwszTemp = (WCHAR*)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
  203. sizeTemp * sizeof(WCHAR));
  204. if (NULL == pwszTemp)
  205. {
  206. hr = E_OUTOFMEMORY;
  207. goto LocalAllocError;
  208. }
  209. size = LoadStringU(
  210. hInstance,
  211. iRCId,
  212. pwszTemp,
  213. sizeTemp);
  214. if (0 == size)
  215. {
  216. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  217. goto LoadStringError;
  218. }
  219. if (size < sizeTemp - 1)
  220. {
  221. // ok, size is big enough
  222. break;
  223. }
  224. ++cBlocks;
  225. LocalFree(pwszTemp);
  226. pwszTemp = NULL;
  227. }
  228. *ppwsz = (WCHAR*) LocalAlloc(LPTR, (size+1) * sizeof(WCHAR));
  229. if (NULL == *ppwsz)
  230. {
  231. hr = E_OUTOFMEMORY;
  232. goto LocalAllocError;
  233. }
  234. // copy it
  235. wcscpy(*ppwsz, pwszTemp);
  236. hr = S_OK;
  237. ErrorReturn:
  238. if (NULL != pwszTemp)
  239. {
  240. LocalFree(pwszTemp);
  241. }
  242. return hr;
  243. TRACE_ERROR(LocalAllocError)
  244. TRACE_ERROR(LoadStringError)
  245. }
  246. HANDLE CCEnroll::CreateOpenFileSafely2(
  247. LPCWSTR pwszFileName,
  248. DWORD idsCreate,
  249. DWORD idsOverwrite)
  250. {
  251. HANDLE hFile = NULL;
  252. WCHAR *pwszMsg = NULL;
  253. WCHAR *pwszFormat = NULL;
  254. WCHAR *pwszTitle = NULL;
  255. WCHAR *pwszSafety = NULL;
  256. DWORD dwAttribs = 0;
  257. BOOL fNotProperFile;
  258. LPCWSTR apwszInsertArray[2];
  259. BOOL fNo;
  260. BOOL fMsgBox;
  261. int idPrefix = IDS_NOTSAFE_WRITE_PREFIX; //default to write prefix
  262. BOOL fCreate = (0xFFFFFFFF != idsCreate) &&
  263. (0xFFFFFFFF != idsOverwrite);
  264. HRESULT hr;
  265. EnterCriticalSection(&m_csXEnroll);
  266. fMsgBox = (m_dwEnabledSafteyOptions != 0);
  267. dwAttribs = GetFileAttributesU(pwszFileName);
  268. if(0xFFFFFFFF == dwAttribs)
  269. {
  270. //file doesn't exist
  271. if (!fCreate)
  272. {
  273. //try to read a non-existing file
  274. //for safety reasons, don't return system error
  275. SetLastError(ERROR_ACCESS_DENIED);
  276. goto InvalidFileError;
  277. }
  278. //if got here, write a new file
  279. if (fMsgBox)
  280. {
  281. hr = xeLoadRCString(hInstanceXEnroll, idsCreate, &pwszFormat);
  282. if (S_OK != hr)
  283. {
  284. goto xeLoadRCStringError;
  285. }
  286. }
  287. }
  288. else
  289. {
  290. //file exists, check if a proper file to write or read
  291. //in either write or read, the following file attrib not proper
  292. fNotProperFile =
  293. (dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ||
  294. (dwAttribs & FILE_ATTRIBUTE_HIDDEN) ||
  295. (dwAttribs & FILE_ATTRIBUTE_SYSTEM);
  296. if (!fNotProperFile)
  297. {
  298. //so far so good
  299. if (fCreate)
  300. {
  301. //write a file
  302. if (0x0 != (dwAttribs & FILE_ATTRIBUTE_READONLY))
  303. {
  304. //don't take read-only and archive
  305. fNotProperFile = TRUE;
  306. }
  307. else
  308. {
  309. //try to overwrite existing file
  310. hr = xeLoadRCString(hInstanceXEnroll, idsOverwrite, &pwszFormat);
  311. if (S_OK != hr)
  312. {
  313. goto xeLoadRCStringError;
  314. }
  315. //enforce popup if overwrite
  316. fMsgBox = TRUE;
  317. }
  318. }
  319. else
  320. {
  321. //read an existing file always violate scripting safety
  322. //it allows detecting file existence
  323. //put out a warning
  324. fMsgBox = TRUE;
  325. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFE_OPEN, &pwszFormat);
  326. if (S_OK != hr)
  327. {
  328. goto xeLoadRCStringError;
  329. }
  330. idPrefix = IDS_NOTSAFE_OPEN_PREFIX;
  331. }
  332. }
  333. if (fNotProperFile)
  334. {
  335. //for safety reasons, don't return system error
  336. SetLastError(ERROR_ACCESS_DENIED);
  337. goto InvalidFileError;
  338. }
  339. }
  340. if (fMsgBox)
  341. {
  342. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFEACTION, &pwszTitle);
  343. if (S_OK != hr)
  344. {
  345. goto xeLoadRCStringError;
  346. }
  347. hr = xeLoadRCString(hInstanceXEnroll, idPrefix, &pwszSafety);
  348. if (S_OK != hr)
  349. {
  350. goto xeLoadRCStringError;
  351. }
  352. apwszInsertArray[0] = pwszSafety;
  353. apwszInsertArray[1] = pwszFileName;
  354. if (!FormatMessageU(
  355. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  356. FORMAT_MESSAGE_FROM_STRING |
  357. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  358. pwszFormat,
  359. 0,
  360. 0,
  361. (LPWSTR) &pwszMsg,
  362. 0,
  363. (va_list *)apwszInsertArray))
  364. {
  365. goto FormatMessageError;
  366. }
  367. fNo = (MessageBoxU(
  368. NULL,
  369. pwszMsg,
  370. pwszTitle,
  371. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES);
  372. if(fNo)
  373. {
  374. SetLastError(ERROR_CANCELLED);
  375. goto CancelError;
  376. }
  377. }
  378. hFile = CreateFileU(
  379. pwszFileName,
  380. fCreate ? GENERIC_WRITE : GENERIC_READ,
  381. FILE_SHARE_READ,
  382. NULL,
  383. fCreate ? CREATE_ALWAYS : OPEN_EXISTING,
  384. FILE_ATTRIBUTE_NORMAL,
  385. NULL);
  386. if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
  387. {
  388. //don't return system error so keep xenroll relative safe for scripting
  389. SetLastError(ERROR_ACCESS_DENIED);
  390. hFile = NULL;
  391. goto CreateFileUError;
  392. }
  393. ErrorReturn:
  394. LeaveCriticalSection(&m_csXEnroll);
  395. if(NULL != pwszMsg)
  396. {
  397. LocalFree(pwszMsg);
  398. }
  399. if(NULL != pwszFormat)
  400. {
  401. LocalFree(pwszFormat);
  402. }
  403. if(NULL != pwszTitle)
  404. {
  405. LocalFree(pwszTitle);
  406. }
  407. if(NULL != pwszSafety)
  408. {
  409. LocalFree(pwszSafety);
  410. }
  411. return(hFile);
  412. TRACE_ERROR(CreateFileUError)
  413. TRACE_ERROR(FormatMessageError);
  414. TRACE_ERROR(CancelError)
  415. TRACE_ERROR(InvalidFileError)
  416. TRACE_ERROR(xeLoadRCStringError)
  417. }
  418. HANDLE CCEnroll::CreateOpenFileSafely(
  419. LPCWSTR pwszFileName,
  420. BOOL fCreate)
  421. {
  422. HANDLE hFile = NULL;
  423. WCHAR *pwszMsg = NULL;
  424. DWORD dwAttribs = 0;
  425. BOOL fNotProperFile;
  426. WCHAR *pwszFormat = NULL;
  427. WCHAR *pwszTitle = NULL;
  428. LPCWSTR apwszInsertArray[] = {pwszFileName};
  429. BOOL fNo;
  430. BOOL fMsgBox = 0 != m_dwEnabledSafteyOptions;
  431. BOOL fOverWrite = FALSE;
  432. HRESULT hr;
  433. EnterCriticalSection(&m_csXEnroll);
  434. dwAttribs = GetFileAttributesU(pwszFileName);
  435. if(0xFFFFFFFF == dwAttribs)
  436. {
  437. //file doesn't exist
  438. if (!fCreate)
  439. {
  440. //try to read a non-existing file
  441. //for safety reasons, don't return system error
  442. SetLastError(ERROR_ACCESS_DENIED);
  443. goto InvalidFileError;
  444. }
  445. }
  446. else
  447. {
  448. //file exists, check if a proper file to write or read
  449. //in either write or read, the following file attrib not proper
  450. fNotProperFile =
  451. (dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ||
  452. (dwAttribs & FILE_ATTRIBUTE_HIDDEN) ||
  453. (dwAttribs & FILE_ATTRIBUTE_SYSTEM);
  454. if (!fNotProperFile)
  455. {
  456. //so far so good
  457. if (fCreate)
  458. {
  459. //write a file
  460. if (0x0 != (dwAttribs & FILE_ATTRIBUTE_READONLY))
  461. {
  462. //don't take read-only and archive
  463. fNotProperFile = TRUE;
  464. }
  465. else
  466. {
  467. //try to overwrite existing file
  468. fOverWrite = TRUE;
  469. }
  470. }
  471. }
  472. if (fNotProperFile)
  473. {
  474. //for safety reasons, don't return system error
  475. SetLastError(ERROR_ACCESS_DENIED);
  476. goto InvalidFileError;
  477. }
  478. }
  479. if (fMsgBox)
  480. {
  481. hr = xeLoadRCString(hInstanceXEnroll, IDS_CERTENROLL, &pwszTitle);
  482. if (S_OK != hr)
  483. {
  484. goto xeLoadRCStringError;
  485. }
  486. hr = xeLoadRCString(
  487. hInstanceXEnroll,
  488. fCreate ? IDS_NOTSAFE_WRITE_FORMAT : IDS_NOTSAFE_OPEN_FORMAT,
  489. &pwszFormat);
  490. if (S_OK != hr)
  491. {
  492. goto xeLoadRCStringError;
  493. }
  494. if (!FormatMessageU(
  495. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  496. FORMAT_MESSAGE_FROM_STRING |
  497. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  498. pwszFormat,
  499. 0,
  500. 0,
  501. (LPWSTR) &pwszMsg,
  502. 0,
  503. (va_list *)apwszInsertArray))
  504. {
  505. goto FormatMessageUError;
  506. }
  507. fNo = (MessageBoxU(
  508. NULL,
  509. pwszMsg,
  510. pwszTitle,
  511. MB_DEFBUTTON2 | MB_YESNO | MB_ICONWARNING) == IDNO);
  512. if(fNo)
  513. {
  514. SetLastError(ERROR_CANCELLED);
  515. goto CancelError;
  516. }
  517. }
  518. if (fCreate && fOverWrite)
  519. {
  520. if (!fMsgBox)
  521. {
  522. hr = xeLoadRCString(hInstanceXEnroll, IDS_CERTENROLL, &pwszTitle);
  523. if (S_OK != hr)
  524. {
  525. goto xeLoadRCStringError;
  526. }
  527. }
  528. //popup overwrite confirmation
  529. hr = xeLoadRCString(hInstanceXEnroll, IDS_OVERWRITE_FORMAT, &pwszFormat);
  530. if (S_OK != hr)
  531. {
  532. goto xeLoadRCStringError;
  533. }
  534. //make sure free before alloc again
  535. if (NULL != pwszMsg)
  536. {
  537. LocalFree(pwszMsg);
  538. pwszMsg = NULL;
  539. }
  540. FormatMessageU(
  541. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  542. FORMAT_MESSAGE_FROM_STRING |
  543. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  544. pwszFormat,
  545. 0,
  546. 0,
  547. (LPWSTR) &pwszMsg,
  548. 0,
  549. (va_list *)apwszInsertArray);
  550. fNo = (MessageBoxU(
  551. NULL,
  552. pwszMsg,
  553. pwszTitle,
  554. MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) != IDYES);
  555. if(fNo)
  556. {
  557. SetLastError(ERROR_CANCELLED);
  558. goto CancelError;
  559. }
  560. }
  561. hFile = CreateFileU(
  562. pwszFileName,
  563. fCreate ? GENERIC_WRITE : GENERIC_READ,
  564. FILE_SHARE_READ,
  565. NULL,
  566. fCreate ? CREATE_ALWAYS : OPEN_EXISTING,
  567. FILE_ATTRIBUTE_NORMAL,
  568. NULL);
  569. if (hFile == INVALID_HANDLE_VALUE || hFile == NULL)
  570. {
  571. //don't return system error so keep xenroll relative safe for scripting
  572. SetLastError(ERROR_ACCESS_DENIED);
  573. hFile = NULL;
  574. goto CreateFileUError;
  575. }
  576. ErrorReturn:
  577. if(NULL != pwszMsg)
  578. {
  579. LocalFree(pwszMsg);
  580. }
  581. if(NULL != pwszTitle)
  582. {
  583. LocalFree(pwszTitle);
  584. }
  585. if(NULL != pwszFormat)
  586. {
  587. LocalFree(pwszFormat);
  588. }
  589. LeaveCriticalSection(&m_csXEnroll);
  590. return(hFile);
  591. TRACE_ERROR(CreateFileUError)
  592. TRACE_ERROR(CancelError)
  593. TRACE_ERROR(FormatMessageUError);
  594. TRACE_ERROR(InvalidFileError)
  595. TRACE_ERROR(xeLoadRCStringError)
  596. }
  597. HANDLE CCEnroll::CreateFileSafely(
  598. LPCWSTR pwszFileName)
  599. {
  600. return CreateOpenFileSafely(pwszFileName, TRUE); //write
  601. }
  602. HANDLE CCEnroll::OpenFileSafely(
  603. LPCWSTR pwszFileName)
  604. {
  605. return CreateOpenFileSafely(pwszFileName, FALSE); //open
  606. }
  607. void DwordToWide(DWORD dw, LPWSTR lpwstr) {
  608. DWORD i = 0;
  609. DWORD j;
  610. WCHAR wch;
  611. while(dw > 0) {
  612. j = dw % 10;
  613. dw /= 10;
  614. lpwstr[i++] = (WCHAR) (j + L'\0');
  615. }
  616. if( i == 0 )
  617. lpwstr[i++] = L'\0';
  618. lpwstr[i] = 0;
  619. for(j=0, i--; i > j; i--, j++) {
  620. wch = lpwstr[i];
  621. lpwstr[i] = lpwstr[j];
  622. lpwstr[j] = wch;
  623. }
  624. }
  625. //take a name value pair info and return encoded value
  626. HRESULT
  627. xeEncodeNameValuePair(
  628. IN PCRYPT_ENROLLMENT_NAME_VALUE_PAIR pNameValuePair,
  629. OUT BYTE **ppbData,
  630. OUT DWORD *pcbData)
  631. {
  632. HRESULT hr = S_OK;
  633. //init
  634. *ppbData = NULL;
  635. *pcbData = 0;
  636. while (TRUE)
  637. {
  638. if(!CryptEncodeObject(
  639. CRYPT_ASN_ENCODING,
  640. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  641. pNameValuePair,
  642. *ppbData,
  643. pcbData))
  644. {
  645. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  646. goto error;
  647. }
  648. if (NULL != *ppbData)
  649. {
  650. break;
  651. }
  652. *ppbData = (BYTE*)MyCoTaskMemAlloc(*pcbData);
  653. if (NULL == *ppbData)
  654. {
  655. hr = E_OUTOFMEMORY;
  656. goto error;
  657. }
  658. }
  659. error:
  660. if (S_OK != hr && NULL != *ppbData)
  661. {
  662. MyCoTaskMemFree(*ppbData);
  663. *ppbData = NULL;
  664. }
  665. return hr;
  666. }
  667. //convert wsz to sz and allocate mem
  668. HRESULT
  669. xeWSZToSZ(
  670. IN LPCWSTR pwsz,
  671. OUT LPSTR *ppsz)
  672. {
  673. HRESULT hr = S_OK;
  674. LONG cc = 0;
  675. //init
  676. *ppsz = NULL;
  677. while (TRUE)
  678. {
  679. cc = WideCharToMultiByte(
  680. GetACP(),
  681. 0,
  682. pwsz,
  683. -1,
  684. *ppsz,
  685. cc,
  686. NULL,
  687. NULL);
  688. if (0 >= cc)
  689. {
  690. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  691. goto error;
  692. }
  693. if (NULL != *ppsz)
  694. {
  695. break;
  696. }
  697. *ppsz= (CHAR*)MyCoTaskMemAlloc(cc);
  698. if (NULL == *ppsz)
  699. {
  700. hr = E_OUTOFMEMORY;
  701. goto error;
  702. }
  703. }
  704. error:
  705. if (S_OK != hr && NULL != *ppsz)
  706. {
  707. MyCoTaskMemFree(*ppsz);
  708. *ppsz = NULL;
  709. }
  710. return hr;
  711. }
  712. //modified from DecodeFile on certsrv
  713. HRESULT
  714. CCEnroll::xeStringToBinaryFromFile(
  715. IN WCHAR const *pwszfn,
  716. OUT BYTE **ppbOut,
  717. OUT DWORD *pcbOut,
  718. IN DWORD Flags)
  719. {
  720. HANDLE hFile;
  721. HRESULT hr;
  722. CHAR *pchFile = NULL;
  723. BYTE *pbOut = NULL;
  724. DWORD cchFile;
  725. DWORD cbRead;
  726. DWORD cbOut = 0;
  727. hFile = OpenFileSafely(pwszfn);
  728. if (NULL == hFile)
  729. {
  730. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  731. goto OpenFileSafelyError;
  732. }
  733. cchFile = GetFileSize(hFile, NULL);
  734. if ((DWORD) -1 == cchFile)
  735. {
  736. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  737. goto GetFileSizeError;
  738. }
  739. pchFile = (CHAR *) LocalAlloc(LMEM_FIXED, cchFile);
  740. if (NULL == pchFile)
  741. {
  742. hr = E_OUTOFMEMORY;
  743. goto LocalAllocError;
  744. }
  745. if (!ReadFile(hFile, pchFile, cchFile, &cbRead, NULL))
  746. {
  747. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  748. goto ReadFileError;
  749. }
  750. assert(cbRead <= cchFile);
  751. if (cbRead != cchFile)
  752. {
  753. hr = MY_HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
  754. goto ReadFileError;
  755. }
  756. if (CRYPT_STRING_BINARY == Flags)
  757. {
  758. pbOut = (BYTE *) pchFile;
  759. cbOut = cchFile;
  760. pchFile = NULL;
  761. }
  762. else
  763. {
  764. // Decode file contents.
  765. while (TRUE)
  766. {
  767. if (!MyCryptStringToBinaryA(
  768. pchFile,
  769. cchFile,
  770. Flags,
  771. pbOut,
  772. &cbOut,
  773. NULL,
  774. NULL))
  775. {
  776. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  777. goto CyrptStringToBinaryError;
  778. }
  779. if (NULL != pbOut)
  780. {
  781. //done
  782. break;
  783. }
  784. pbOut = (BYTE*)LocalAlloc(LMEM_FIXED, cbOut);
  785. if (NULL == pbOut)
  786. {
  787. hr = E_OUTOFMEMORY;
  788. goto LocalAllocError;
  789. }
  790. }
  791. }
  792. *pcbOut = cbOut;
  793. *ppbOut = pbOut;
  794. pbOut = NULL;
  795. hr = S_OK;
  796. error:
  797. if (INVALID_HANDLE_VALUE != hFile)
  798. {
  799. CloseHandle(hFile);
  800. }
  801. if (NULL != pchFile)
  802. {
  803. LocalFree(pchFile);
  804. }
  805. if (NULL != pbOut)
  806. {
  807. LocalFree(pbOut);
  808. }
  809. return(hr);
  810. ErrorReturn:
  811. goto error;
  812. TRACE_ERROR(CyrptStringToBinaryError)
  813. TRACE_ERROR(ReadFileError)
  814. TRACE_ERROR(LocalAllocError)
  815. TRACE_ERROR(GetFileSizeError)
  816. TRACE_ERROR(OpenFileSafelyError)
  817. }
  818. //following two functions handle some APIs not available
  819. //in downlevel client crypt32.dll
  820. typedef VOID
  821. (WINAPI * PFNCertFreeCertificateChain)
  822. (IN PCCERT_CHAIN_CONTEXT pChainContext);
  823. typedef BOOL
  824. (WINAPI * PFNCertGetCertificateChain)
  825. (IN OPTIONAL HCERTCHAINENGINE hChainEngine,
  826. IN PCCERT_CONTEXT pCertContext,
  827. IN OPTIONAL LPFILETIME pTime,
  828. IN OPTIONAL HCERTSTORE hAdditionalStore,
  829. IN PCERT_CHAIN_PARA pChainPara,
  830. IN DWORD dwFlags,
  831. IN LPVOID pvReserved,
  832. OUT PCCERT_CHAIN_CONTEXT* ppChainContext);
  833. typedef BOOL (WINAPI *PFNCertVerifyCertificateChainPolicy) (
  834. LPCSTR pszPolicyOID,
  835. PCCERT_CHAIN_CONTEXT pChainContext,
  836. PCERT_CHAIN_POLICY_PARA pPolicyPara,
  837. PCERT_CHAIN_POLICY_STATUS pPolicyStatus
  838. );
  839. typedef BOOL (*PFNCheckTokenMembership) (
  840. HANDLE TokenHandle, // handle to access token
  841. PSID SidToCheck, // SID
  842. PBOOL IsMember // result
  843. );
  844. typedef BOOL (*PFNSetSecurityDescriptorControl) (
  845. PSECURITY_DESCRIPTOR pSecurityDescriptor, // SD
  846. SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, // control bits
  847. SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet // new control bits
  848. );
  849. VOID
  850. MyCertFreeCertificateChain (
  851. IN PCCERT_CHAIN_CONTEXT pChainContext
  852. )
  853. {
  854. PFNCertFreeCertificateChain pfnCertFreeCertificateChain = NULL;
  855. HMODULE hModule = NULL;
  856. hModule = GetModuleHandle("crypt32.dll");
  857. if (NULL != hModule)
  858. {
  859. pfnCertFreeCertificateChain = (PFNCertFreeCertificateChain)
  860. GetProcAddress(hModule,
  861. "CertFreeCertificateChain");
  862. if (NULL != pfnCertFreeCertificateChain)
  863. {
  864. pfnCertFreeCertificateChain(pChainContext);
  865. }
  866. }
  867. }
  868. BOOL
  869. MyCertGetCertificateChain (
  870. IN OPTIONAL HCERTCHAINENGINE hChainEngine,
  871. IN PCCERT_CONTEXT pCertContext,
  872. IN OPTIONAL LPFILETIME pTime,
  873. IN OPTIONAL HCERTSTORE hAdditionalStore,
  874. IN PCERT_CHAIN_PARA pChainPara,
  875. IN DWORD dwFlags,
  876. IN LPVOID pvReserved,
  877. OUT PCCERT_CHAIN_CONTEXT* ppChainContext
  878. )
  879. {
  880. PFNCertGetCertificateChain pfnCertGetCertificateChain = NULL;
  881. HMODULE hModule = NULL;
  882. hModule = GetModuleHandle("crypt32.dll");
  883. if (NULL != hModule)
  884. {
  885. pfnCertGetCertificateChain = (PFNCertGetCertificateChain)
  886. GetProcAddress(hModule,
  887. "CertGetCertificateChain");
  888. if (NULL != pfnCertGetCertificateChain)
  889. {
  890. return pfnCertGetCertificateChain(
  891. hChainEngine,
  892. pCertContext,
  893. pTime,
  894. hAdditionalStore,
  895. pChainPara,
  896. dwFlags,
  897. pvReserved,
  898. ppChainContext);
  899. }
  900. }
  901. return FALSE;
  902. }
  903. BOOL
  904. MyCertVerifyCertificateChainPolicy(
  905. LPCSTR pszPolicyOID,
  906. PCCERT_CHAIN_CONTEXT pChainContext,
  907. PCERT_CHAIN_POLICY_PARA pPolicyPara,
  908. PCERT_CHAIN_POLICY_STATUS pPolicyStatus
  909. )
  910. {
  911. PFNCertVerifyCertificateChainPolicy pfnCertVerifyCertificateChainPolicy = NULL;
  912. HMODULE hModule = NULL;
  913. hModule = GetModuleHandle("crypt32.dll");
  914. if (NULL != hModule)
  915. {
  916. pfnCertVerifyCertificateChainPolicy = (PFNCertVerifyCertificateChainPolicy)
  917. GetProcAddress(hModule,
  918. "CertVerifyCertificateChainPolicy");
  919. if (NULL != pfnCertVerifyCertificateChainPolicy)
  920. {
  921. return pfnCertVerifyCertificateChainPolicy(
  922. pszPolicyOID,
  923. pChainContext,
  924. pPolicyPara,
  925. pPolicyStatus);
  926. }
  927. }
  928. return FALSE;
  929. }
  930. BOOL
  931. MyCheckTokenMembership(
  932. HANDLE TokenHandle, // handle to access token
  933. PSID SidToCheck, // SID
  934. PBOOL IsMember // result
  935. )
  936. {
  937. PFNCheckTokenMembership pfnCheckTokenMembership = NULL;
  938. HMODULE hModule = NULL;
  939. hModule = GetModuleHandle("advapi32.dll");
  940. if (NULL != hModule)
  941. {
  942. pfnCheckTokenMembership = (PFNCheckTokenMembership)
  943. GetProcAddress(hModule,
  944. "CheckTokenMembership");
  945. if (NULL != pfnCheckTokenMembership)
  946. {
  947. return pfnCheckTokenMembership(
  948. TokenHandle,
  949. SidToCheck,
  950. IsMember);
  951. }
  952. }
  953. return FALSE;
  954. }
  955. BOOL
  956. MySetSecurityDescriptorControl(
  957. PSECURITY_DESCRIPTOR pSecurityDescriptor, // SD
  958. SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, // control bits
  959. SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet // new control bits
  960. )
  961. {
  962. PFNSetSecurityDescriptorControl pfnSetSecurityDescriptorControl = NULL;
  963. HMODULE hModule = NULL;
  964. hModule = GetModuleHandle("advapi32.dll");
  965. if (NULL != hModule)
  966. {
  967. pfnSetSecurityDescriptorControl = (PFNSetSecurityDescriptorControl)
  968. GetProcAddress(hModule,
  969. "SetSecurityDescriptorControl");
  970. if (NULL != pfnSetSecurityDescriptorControl)
  971. {
  972. return pfnSetSecurityDescriptorControl(
  973. pSecurityDescriptor,
  974. ControlBitsOfInterest,
  975. ControlBitsToSet);
  976. }
  977. }
  978. return FALSE;
  979. }
  980. HRESULT __stdcall CCEnroll::GetInterfaceSafetyOptions(
  981. /* [in] */ REFIID riid,
  982. /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
  983. /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions) {
  984. RPC_STATUS rpcStatus;
  985. if(0 != UuidCompare((GUID *) &riid, (GUID *) &IID_IDispatch, &rpcStatus) )
  986. return(E_NOINTERFACE);
  987. *pdwEnabledOptions = m_dwEnabledSafteyOptions;
  988. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
  989. return(S_OK);
  990. }
  991. HRESULT __stdcall CCEnroll::SetInterfaceSafetyOptions(
  992. /* [in] */ REFIID riid,
  993. /* [in] */ DWORD dwOptionSetMask,
  994. /* [in] */ DWORD dwEnabledOptions) {
  995. RPC_STATUS rpcStatus;
  996. DWORD dwSupport = 0;
  997. if(0 != UuidCompare((GUID *) &riid, (GUID *) &IID_IDispatch, &rpcStatus) )
  998. return(E_NOINTERFACE);
  999. dwSupport = dwOptionSetMask & ~(INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA);
  1000. if(dwSupport != 0)
  1001. return(E_FAIL);
  1002. (DWORD)m_dwEnabledSafteyOptions &= ~dwOptionSetMask;
  1003. (DWORD)m_dwEnabledSafteyOptions |= dwEnabledOptions;
  1004. return(S_OK);
  1005. }
  1006. HRESULT
  1007. CCEnroll::GetVerifyProv()
  1008. {
  1009. HRESULT hr;
  1010. EnterCriticalSection(&m_csXEnroll);
  1011. if (NULL == m_hVerifyProv)
  1012. {
  1013. if (!CryptAcquireContextU(
  1014. &m_hVerifyProv,
  1015. NULL,
  1016. m_keyProvInfo.pwszProvName,
  1017. m_keyProvInfo.dwProvType,
  1018. CRYPT_VERIFYCONTEXT))
  1019. {
  1020. #if DBG
  1021. assert(NULL == m_hVerifyProv);
  1022. #endif //DBG
  1023. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1024. goto CryptAcquireContextUError;
  1025. }
  1026. }
  1027. hr = S_OK;
  1028. ErrorReturn:
  1029. LeaveCriticalSection(&m_csXEnroll);
  1030. return hr;
  1031. TRACE_ERROR(CryptAcquireContextUError)
  1032. }
  1033. BOOL CCEnroll::GetCapiHashAndSigAlgId(ALG_ID rgAlg[2]) {
  1034. DWORD iHashBest = 0;
  1035. ALG_ID arDefaultHash[] = {m_HashAlgId, CALG_SHA1, CALG_MD5};
  1036. DWORD cDefaultHash = sizeof(arDefaultHash) / sizeof(DWORD);
  1037. HCRYPTPROV hProvU = NULL;
  1038. DWORD dwFlags = CRYPT_FIRST;
  1039. DWORD i;
  1040. PROV_ENUMALGS enumAlgs;
  1041. DWORD cb = sizeof(enumAlgs);
  1042. BOOL fRet = TRUE;
  1043. rgAlg[0] = 0;
  1044. rgAlg[1] = 0;
  1045. EnterCriticalSection(&m_csXEnroll);
  1046. // only get a prov if one wasn't passed in.
  1047. if(m_hProv == NULL)
  1048. {
  1049. HRESULT hr;
  1050. hr = GetVerifyProv();
  1051. if (S_OK != hr)
  1052. {
  1053. goto GetVerifyProvError;
  1054. }
  1055. hProvU = m_hVerifyProv;
  1056. }
  1057. else
  1058. {
  1059. // otherwise use the current m_hProv, SCard only likes on
  1060. // CryptAcquireContext to be used.
  1061. hProvU = m_hProv;
  1062. }
  1063. cb = sizeof(enumAlgs);
  1064. while( CryptGetProvParam(
  1065. hProvU,
  1066. PP_ENUMALGS,
  1067. (BYTE *) &enumAlgs,
  1068. &cb,
  1069. dwFlags
  1070. ) ) {
  1071. cb = sizeof(enumAlgs);
  1072. // not first pass anymore
  1073. dwFlags = 0;
  1074. // see if this is a hash alg
  1075. if( ALG_CLASS_HASH == GET_ALG_CLASS(enumAlgs.aiAlgid) ) {
  1076. // get things init with the first hash alg
  1077. if(rgAlg[0] == 0) {
  1078. rgAlg[0] = enumAlgs.aiAlgid;
  1079. iHashBest = cDefaultHash;
  1080. }
  1081. // pick the best one
  1082. for(i=0; i<iHashBest; i++) {
  1083. if(arDefaultHash[i] == enumAlgs.aiAlgid) {
  1084. rgAlg[0] = enumAlgs.aiAlgid;
  1085. iHashBest = i;
  1086. break;
  1087. }
  1088. }
  1089. }
  1090. // we will only pick up the first signature type
  1091. // in general there is only 1 per csp (Ref: JeffSpel)
  1092. else if( ALG_CLASS_SIGNATURE == GET_ALG_CLASS(enumAlgs.aiAlgid) ) {
  1093. if(rgAlg[1] == 0)
  1094. rgAlg[1] = enumAlgs.aiAlgid;
  1095. }
  1096. }
  1097. ErrorReturn:
  1098. LeaveCriticalSection(&m_csXEnroll);
  1099. // some CSPs say they can't sign, but they really can
  1100. // so if we have not hashalg or sigalg we will put a default
  1101. // in and if the CSP really can't do it, it will error
  1102. // this is for backwards compatibility
  1103. // default hash to sha1
  1104. if(rgAlg[0] == 0)
  1105. rgAlg[0] = CALG_SHA1;
  1106. // default sig to RSA
  1107. if(rgAlg[1] == 0)
  1108. rgAlg[1] = CALG_RSA_SIGN;
  1109. #if 0
  1110. if(rgAlg[0] == 0 || rgAlg[1] == 0) {
  1111. SetLastError((DWORD)NTE_BAD_ALGID);
  1112. fRet = FALSE;
  1113. }
  1114. #endif
  1115. return(fRet);
  1116. TRACE_ERROR(GetVerifyProvError)
  1117. }
  1118. BOOL CreatePvkProperty(
  1119. CRYPT_KEY_PROV_INFO *pKeyProvInfo,
  1120. PCRYPT_DATA_BLOB pBlob)
  1121. {
  1122. WCHAR wszKeySpec[11];
  1123. WCHAR wszProvType[11];
  1124. DWORD cbContainer;
  1125. DWORD cbKeySpec;
  1126. DWORD cbProvType;
  1127. DWORD cbProvName;
  1128. assert(pBlob != NULL);
  1129. assert(pKeyProvInfo != NULL);
  1130. // convert dwords to strings
  1131. DwordToWide(pKeyProvInfo->dwKeySpec, wszKeySpec);
  1132. DwordToWide(pKeyProvInfo->dwProvType, wszProvType);
  1133. // get total length of string
  1134. cbContainer = (DWORD)(wcslen(pKeyProvInfo->pwszContainerName) + 1) * sizeof(WCHAR);
  1135. cbKeySpec = (DWORD)(wcslen(wszKeySpec) + 1) * sizeof(WCHAR);
  1136. cbProvType = (DWORD)(wcslen(wszProvType) + 1) * sizeof(WCHAR);
  1137. cbProvName = (DWORD)(wcslen(pKeyProvInfo->pwszProvName) + 1) * sizeof(WCHAR);
  1138. pBlob->cbData =
  1139. cbContainer +
  1140. cbKeySpec +
  1141. cbProvType +
  1142. cbProvName +
  1143. sizeof(WCHAR);
  1144. // allocate the string
  1145. if( (pBlob->pbData = (BYTE *) MyCoTaskMemAlloc(pBlob->cbData)) == NULL) {
  1146. SetLastError(ERROR_OUTOFMEMORY);
  1147. return(FALSE);
  1148. }
  1149. // copy the strings
  1150. memset(pBlob->pbData, 0, pBlob->cbData);
  1151. memcpy(pBlob->pbData, pKeyProvInfo->pwszContainerName, cbContainer);
  1152. memcpy(&pBlob->pbData[cbContainer], wszKeySpec, cbKeySpec);
  1153. memcpy(&pBlob->pbData[cbContainer + cbKeySpec], wszProvType, cbProvType);
  1154. memcpy(&pBlob->pbData[cbContainer + cbKeySpec + cbProvType], pKeyProvInfo->pwszProvName, cbProvName);
  1155. return(TRUE);
  1156. }
  1157. static LPWSTR wszEmpty = L"";
  1158. static LPWSTR wszMY = L"MY";
  1159. static LPWSTR wszCA = L"CA";
  1160. static LPWSTR wszROOT = L"ROOT";
  1161. static LPWSTR wszREQUEST = L"REQUEST";
  1162. static LPSTR szSystemStore = sz_CERT_STORE_PROV_SYSTEM;
  1163. // static LPSTR szSystemStore = sz_CERT_STORE_PROV_SYSTEM_REGISTRY;
  1164. /////////////////////////////////////////////////////////////////////////////
  1165. // CCEnroll
  1166. CCEnroll::~CCEnroll(void) {
  1167. Destruct();
  1168. DeleteCriticalSection(&m_csXEnroll);
  1169. }
  1170. void CCEnroll::Destruct(void) {
  1171. if(NULL != m_PrivateKeyArchiveCertificate)
  1172. {
  1173. CertFreeCertificateContext(m_PrivateKeyArchiveCertificate);
  1174. }
  1175. if(NULL != m_pCertContextSigner)
  1176. {
  1177. CertFreeCertificateContext(m_pCertContextSigner);
  1178. }
  1179. if(m_pCertContextRenewal != NULL)
  1180. CertFreeCertificateContext(m_pCertContextRenewal);
  1181. if(m_pCertContextStatic != NULL)
  1182. CertFreeCertificateContext(m_pCertContextStatic);
  1183. if(m_keyProvInfo.pwszContainerName != wszEmpty)
  1184. MyCoTaskMemFree(m_keyProvInfo.pwszContainerName);
  1185. if(m_keyProvInfo.pwszProvName != wszEmpty)
  1186. MyCoTaskMemFree(m_keyProvInfo.pwszProvName);
  1187. if(m_MyStore.wszName != wszMY)
  1188. MyCoTaskMemFree(m_MyStore.wszName);
  1189. if(m_CAStore.wszName != wszCA)
  1190. MyCoTaskMemFree(m_CAStore.wszName);
  1191. if(m_RootStore.wszName != wszROOT && m_RootStore.wszName != wszCA)
  1192. MyCoTaskMemFree(m_RootStore.wszName);
  1193. if(m_RequestStore.wszName != wszREQUEST)
  1194. MyCoTaskMemFree(m_RequestStore.wszName);
  1195. if(m_MyStore.szType != szSystemStore)
  1196. MyCoTaskMemFree(m_MyStore.szType);
  1197. if(m_CAStore.szType != szSystemStore)
  1198. MyCoTaskMemFree(m_CAStore.szType);
  1199. if(m_RootStore.szType != szSystemStore)
  1200. MyCoTaskMemFree(m_RootStore.szType);
  1201. if(m_RequestStore.szType != szSystemStore)
  1202. MyCoTaskMemFree(m_RequestStore.szType);
  1203. if(m_wszSPCFileName != wszEmpty)
  1204. MyCoTaskMemFree(m_wszSPCFileName);
  1205. if(m_wszPVKFileName != wszEmpty)
  1206. MyCoTaskMemFree(m_wszPVKFileName);
  1207. if (NULL != m_pCertContextPendingRequest)
  1208. CertFreeCertificateContext(m_pCertContextPendingRequest);
  1209. if (NULL != m_pPendingRequestTable)
  1210. delete m_pPendingRequestTable;
  1211. // store handles
  1212. if(m_RootStore.hStore != NULL)
  1213. CertCloseStore(m_RootStore.hStore, 0);
  1214. m_RootStore.hStore = NULL;
  1215. if(m_CAStore.hStore != NULL)
  1216. CertCloseStore(m_CAStore.hStore, 0);
  1217. m_CAStore.hStore = NULL;
  1218. if(m_MyStore.hStore != NULL)
  1219. CertCloseStore(m_MyStore.hStore, 0);
  1220. m_MyStore.hStore = NULL;
  1221. if(m_RequestStore.hStore != NULL)
  1222. CertCloseStore(m_RequestStore.hStore, 0);
  1223. m_RequestStore.hStore = NULL;
  1224. // remove provider handles
  1225. if(m_hProv != NULL)
  1226. CryptReleaseContext(m_hProv, 0);
  1227. m_hProv = NULL;
  1228. if(m_hVerifyProv != NULL)
  1229. CryptReleaseContext(m_hVerifyProv, 0);
  1230. m_hVerifyProv = NULL;
  1231. if (NULL != m_hCachedKey)
  1232. {
  1233. //this should be destroyed early but just in case
  1234. CryptDestroyKey(m_hCachedKey);
  1235. }
  1236. if (NULL != m_pPublicKeyInfo)
  1237. {
  1238. LocalFree(m_pPublicKeyInfo);
  1239. m_pPublicKeyInfo = NULL;
  1240. }
  1241. FreeAllStackExtension();
  1242. FreeAllStackAttribute();
  1243. resetBlobProperties();
  1244. }
  1245. static LPVOID CoTaskMemAllocTrap(ULONG cb) {
  1246. __try {
  1247. return(CoTaskMemAlloc(cb));
  1248. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1249. SetLastError(ERROR_DLL_NOT_FOUND);
  1250. return(NULL);
  1251. }
  1252. }
  1253. static LPVOID CoTaskMemReallocTrap(LPVOID ptr, ULONG cb) {
  1254. __try {
  1255. return(CoTaskMemRealloc(ptr, cb));
  1256. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1257. SetLastError(ERROR_DLL_NOT_FOUND);
  1258. return(NULL);
  1259. }
  1260. }
  1261. static void CoTaskMemFreeTrap(LPVOID ptr) {
  1262. __try {
  1263. CoTaskMemFree(ptr);
  1264. } __except(EXCEPTION_EXECUTE_HANDLER) {
  1265. SetLastError(ERROR_DLL_NOT_FOUND);
  1266. }
  1267. return;
  1268. }
  1269. // Initialize the safety options in the constructor, so they won't
  1270. // be clobbered when we do a reset().
  1271. CCEnroll::CCEnroll(void) : m_dwEnabledSafteyOptions(0) {
  1272. __try
  1273. {
  1274. InitializeCriticalSection(&m_csXEnroll);
  1275. }
  1276. __except(EXCEPTION_EXECUTE_HANDLER)
  1277. {
  1278. }
  1279. Init();
  1280. }
  1281. HRESULT
  1282. CCEnroll::Init(void)
  1283. {
  1284. HRESULT hr;
  1285. GUID guidContainerName;
  1286. char * sz = NULL;
  1287. RPC_STATUS rpc_status;
  1288. // set default mem allocators
  1289. if(MyCoTaskMemAlloc == NULL)
  1290. {
  1291. MyCoTaskMemAlloc = CoTaskMemAllocTrap;
  1292. MyCoTaskMemRealloc = CoTaskMemReallocTrap;
  1293. MyCoTaskMemFree = CoTaskMemFreeTrap;
  1294. }
  1295. // get a container based on a guid
  1296. rpc_status = UuidCreate(&guidContainerName);
  1297. if (RPC_S_OK != rpc_status && RPC_S_UUID_LOCAL_ONLY != rpc_status)
  1298. {
  1299. hr = rpc_status;
  1300. goto UuidCreateError;
  1301. }
  1302. rpc_status = UuidToStringA(&guidContainerName, (unsigned char **) &sz);
  1303. if (RPC_S_OK != rpc_status)
  1304. {
  1305. hr = rpc_status;
  1306. goto UuidToStringAError;
  1307. }
  1308. assert(sz != NULL);
  1309. m_keyProvInfo.pwszContainerName = WideFromMB(sz);
  1310. RpcStringFree((unsigned char **) &sz);
  1311. m_keyProvInfo.pwszProvName = wszEmpty;
  1312. m_keyProvInfo.dwProvType = PROV_RSA_FULL;
  1313. m_keyProvInfo.dwFlags = 0;
  1314. m_keyProvInfo.cProvParam = 0;
  1315. m_keyProvInfo.rgProvParam = NULL;
  1316. m_keyProvInfo.dwKeySpec = AT_SIGNATURE;
  1317. m_fEnableSMIMECapabilities =
  1318. (m_keyProvInfo.dwKeySpec == AT_KEYEXCHANGE);
  1319. m_fSMIMESetByClient = FALSE;
  1320. m_fKeySpecSetByClient = FALSE;
  1321. m_hProv = NULL;
  1322. m_hVerifyProv = NULL;
  1323. m_fDeleteRequestCert = TRUE;
  1324. m_fUseExistingKey = FALSE;
  1325. m_fWriteCertToCSPModified = FALSE;
  1326. m_fWriteCertToCSP = TRUE; // always want to try
  1327. m_fWriteCertToUserDSModified = FALSE;
  1328. m_fWriteCertToUserDS = FALSE;
  1329. m_fReuseHardwareKeyIfUnableToGenNew = TRUE;
  1330. m_fLimitExchangeKeyToEncipherment = FALSE;
  1331. m_dwT61DNEncoding = 0; // or CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG
  1332. m_dwGenKeyFlags = 0;
  1333. m_wszSPCFileName = wszEmpty;
  1334. m_wszPVKFileName = wszEmpty;
  1335. m_HashAlgId = 0;
  1336. m_fMyStoreOpenFlagsModified = FALSE;
  1337. m_MyStore.wszName = wszMY;
  1338. m_MyStore.szType = szSystemStore;
  1339. m_MyStore.dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  1340. m_MyStore.hStore = NULL;
  1341. m_fCAStoreOpenFlagsModified = FALSE;
  1342. m_CAStore.wszName = wszCA;
  1343. m_CAStore.szType = szSystemStore;
  1344. m_CAStore.dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  1345. m_CAStore.hStore = NULL;
  1346. m_fRootStoreOpenFlagsModified = FALSE;
  1347. m_RootStore.wszName = wszROOT;
  1348. m_RootStore.szType = szSystemStore;
  1349. m_RootStore.dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  1350. m_RootStore.hStore = NULL;
  1351. m_fRequestStoreOpenFlagsModified = FALSE;
  1352. m_RequestStore.wszName = wszREQUEST ;
  1353. m_RequestStore.szType = szSystemStore;
  1354. m_RequestStore.dwFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  1355. m_RequestStore.hStore = NULL;
  1356. m_PrivateKeyArchiveCertificate= NULL;
  1357. m_pCertContextRenewal = NULL;
  1358. m_pCertContextSigner = NULL;
  1359. m_pCertContextStatic = NULL;
  1360. memset(m_arHashBytesNewCert, 0, sizeof(m_arHashBytesNewCert));
  1361. memset(m_arHashBytesOldCert, 0, sizeof(m_arHashBytesOldCert));
  1362. m_fArchiveOldCert = FALSE;
  1363. m_pExtStack = NULL;
  1364. m_cExtStack = 0;
  1365. m_pAttrStack = NULL;
  1366. m_cAttrStack = 0;
  1367. m_pExtStackNew = NULL;
  1368. m_cExtStackNew = 0;
  1369. m_pAttrStackNew = NULL;
  1370. m_cAttrStackNew = 0;
  1371. m_pPropStack = NULL;
  1372. m_cPropStack = 0;
  1373. m_fNewRequestMethod = FALSE;
  1374. m_fCMCFormat = FALSE;
  1375. m_fHonorRenew = TRUE; //critical, if passing XECR_PKCS10*
  1376. m_fOID_V2 = FALSE; //critical
  1377. m_hCachedKey = NULL;
  1378. m_fUseClientKeyUsage = FALSE;
  1379. m_lClientId = XECI_XENROLL;
  1380. m_dwLastAlgIndex = MAXDWORD;
  1381. m_fIncludeSubjectKeyID = TRUE;
  1382. m_fHonorIncludeSubjectKeyID = FALSE;
  1383. m_pPublicKeyInfo = NULL;
  1384. m_dwSigKeyLenMax = 0;
  1385. m_dwSigKeyLenMin = 0;
  1386. m_dwSigKeyLenDef = 0;
  1387. m_dwSigKeyLenInc = 0;
  1388. m_dwXhgKeyLenMax = 0;
  1389. m_dwXhgKeyLenMin = 0;
  1390. m_dwXhgKeyLenDef = 0;
  1391. m_dwXhgKeyLenInc = 0;
  1392. // Initialize pending info data:
  1393. m_pCertContextPendingRequest = NULL;
  1394. m_pCertContextLastEnumerated = NULL;
  1395. m_dwCurrentPendingRequestIndex = 0;
  1396. m_pPendingRequestTable = NULL;
  1397. memset(&m_hashBlobPendingRequest, 0, sizeof(CRYPT_DATA_BLOB));
  1398. ZeroMemory(&m_blobResponseKAHash, sizeof(m_blobResponseKAHash));
  1399. hr = S_OK;
  1400. ErrorReturn:
  1401. return hr;
  1402. TRACE_ERROR(UuidToStringAError)
  1403. TRACE_ERROR(UuidCreateError)
  1404. }
  1405. void CCEnroll::FlushStore(StoreType storeType) {
  1406. PSTOREINFO pStoreInfo = NULL;
  1407. // get store struct
  1408. switch(storeType) {
  1409. case StoreMY:
  1410. pStoreInfo = &m_MyStore;
  1411. break;
  1412. case StoreCA:
  1413. pStoreInfo = &m_CAStore;
  1414. break;
  1415. case StoreROOT:
  1416. pStoreInfo = &m_RootStore;
  1417. break;
  1418. case StoreREQUEST:
  1419. pStoreInfo = &m_RequestStore;
  1420. break;
  1421. }
  1422. EnterCriticalSection(&m_csXEnroll);
  1423. // if store already open, return it
  1424. if(pStoreInfo->hStore != NULL) {
  1425. CertCloseStore(pStoreInfo->hStore, 0);
  1426. pStoreInfo->hStore = NULL;
  1427. }
  1428. // we may have something or not, but return it
  1429. // the errors will be correct.
  1430. LeaveCriticalSection(&m_csXEnroll);
  1431. }
  1432. HCERTSTORE CCEnroll::GetStore(StoreType storeType) {
  1433. PSTOREINFO pStoreInfo = NULL;
  1434. HCERTSTORE hStore = NULL;
  1435. // get store struct
  1436. switch(storeType) {
  1437. case StoreMY:
  1438. pStoreInfo = &m_MyStore;
  1439. break;
  1440. case StoreCA:
  1441. pStoreInfo = &m_CAStore;
  1442. break;
  1443. case StoreROOT:
  1444. pStoreInfo = &m_RootStore;
  1445. break;
  1446. case StoreREQUEST:
  1447. pStoreInfo = &m_RequestStore;
  1448. break;
  1449. default:
  1450. SetLastError(ERROR_BAD_ARGUMENTS);
  1451. return(NULL);
  1452. break;
  1453. }
  1454. EnterCriticalSection(&m_csXEnroll);
  1455. // if store already open, return it
  1456. if(pStoreInfo->hStore == NULL) {
  1457. // otherwise attempt to open the store
  1458. pStoreInfo->hStore = CertOpenStore(
  1459. pStoreInfo->szType,
  1460. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
  1461. NULL,
  1462. pStoreInfo->dwFlags,
  1463. pStoreInfo->wszName);
  1464. }
  1465. // we may have something or not, but return it
  1466. // the errors will be correct.
  1467. hStore = pStoreInfo->hStore;
  1468. LeaveCriticalSection(&m_csXEnroll);
  1469. return(hStore);
  1470. }
  1471. HCRYPTPROV CCEnroll::GetProv(DWORD dwFlags) {
  1472. HCRYPTPROV hProvT = NULL;
  1473. DWORD cb = 0;
  1474. char * pszProvName = NULL;
  1475. char * pszContainerName = NULL;
  1476. EnterCriticalSection(&m_csXEnroll);
  1477. DWORD dwProvType = m_keyProvInfo.dwProvType;
  1478. switch(dwFlags) {
  1479. case CRYPT_NEWKEYSET:
  1480. dwFlags = dwFlags | m_keyProvInfo.dwFlags;
  1481. break;
  1482. case CRYPT_DELETEKEYSET:
  1483. if( m_hProv != NULL ) {
  1484. CryptReleaseContext(m_hProv, 0);
  1485. m_hProv = NULL;
  1486. CryptAcquireContextU(&m_hProv,
  1487. m_keyProvInfo.pwszContainerName,
  1488. m_keyProvInfo.pwszProvName,
  1489. m_keyProvInfo.dwProvType,
  1490. CRYPT_DELETEKEYSET);
  1491. }
  1492. m_hProv = NULL;
  1493. goto CommonReturn;
  1494. break;
  1495. default:
  1496. dwFlags = m_keyProvInfo.dwFlags;
  1497. break;
  1498. }
  1499. if(m_hProv == NULL) {
  1500. if( CryptAcquireContextU(&m_hProv,
  1501. m_keyProvInfo.pwszContainerName,
  1502. m_keyProvInfo.pwszProvName,
  1503. m_keyProvInfo.dwProvType,
  1504. dwFlags) ) {
  1505. // we have the m_hProv, now set the provider name
  1506. // Since this is secondary to the task, don't do error checking
  1507. // nothing here should really fail anyway
  1508. pszProvName = NULL;
  1509. while (TRUE)
  1510. {
  1511. if(!CryptGetProvParam( m_hProv,
  1512. PP_NAME,
  1513. (BYTE*)pszProvName,
  1514. &cb,
  1515. 0))
  1516. {
  1517. break;
  1518. }
  1519. if (NULL != pszProvName)
  1520. {
  1521. if(m_keyProvInfo.pwszProvName != wszEmpty)
  1522. MyCoTaskMemFree(m_keyProvInfo.pwszProvName);
  1523. m_keyProvInfo.pwszProvName = WideFromMB(pszProvName);
  1524. break;
  1525. }
  1526. pszProvName = (char *)LocalAlloc(LMEM_FIXED, cb);
  1527. if (NULL == pszProvName)
  1528. {
  1529. goto CommonReturn;
  1530. }
  1531. }
  1532. // Here we just try and get the unique container name
  1533. // If not, just go on
  1534. BOOL fTryAnother = FALSE;
  1535. cb = 0;
  1536. pszContainerName = NULL;
  1537. while (TRUE)
  1538. {
  1539. if(!CryptGetProvParam( m_hProv,
  1540. PP_UNIQUE_CONTAINER,
  1541. (BYTE*)pszContainerName,
  1542. &cb,
  1543. 0))
  1544. {
  1545. if (NULL == pszContainerName)
  1546. {
  1547. fTryAnother = TRUE;
  1548. }
  1549. else
  1550. {
  1551. LocalFree(pszContainerName);
  1552. pszContainerName = NULL;
  1553. }
  1554. break;
  1555. }
  1556. else
  1557. {
  1558. if (NULL != pszContainerName)
  1559. {
  1560. //got it, done
  1561. break;
  1562. }
  1563. }
  1564. pszContainerName = (char *)LocalAlloc(LMEM_FIXED, cb);
  1565. if (NULL == pszContainerName)
  1566. {
  1567. goto CommonReturn;
  1568. }
  1569. }
  1570. if (fTryAnother)
  1571. {
  1572. // so we can't get the unique container name,
  1573. // lets just go for the container name (may not be unique).
  1574. cb = 0;
  1575. pszContainerName = NULL;
  1576. while (TRUE)
  1577. {
  1578. if(!CryptGetProvParam(m_hProv,
  1579. PP_CONTAINER,
  1580. (BYTE*)pszContainerName,
  1581. &cb,
  1582. 0))
  1583. {
  1584. if (NULL != pszContainerName)
  1585. {
  1586. LocalFree(pszContainerName);
  1587. pszContainerName = NULL;
  1588. }
  1589. break;
  1590. }
  1591. else
  1592. {
  1593. if (NULL != pszContainerName)
  1594. {
  1595. //got it, done
  1596. break;
  1597. }
  1598. pszContainerName = (char *)LocalAlloc(LMEM_FIXED, cb);
  1599. if (NULL == pszContainerName)
  1600. {
  1601. goto CommonReturn;
  1602. }
  1603. }
  1604. }
  1605. }
  1606. // set the container, otherwise use what was there
  1607. if(pszContainerName != NULL) {
  1608. if( m_keyProvInfo.pwszContainerName != wszEmpty )
  1609. MyCoTaskMemFree(m_keyProvInfo.pwszContainerName);
  1610. m_keyProvInfo.pwszContainerName = WideFromMB(pszContainerName);
  1611. }
  1612. // now because some providers double duty for provider types
  1613. // get what the the provider thinks its type is
  1614. cb = sizeof(DWORD);
  1615. if(CryptGetProvParam( m_hProv,
  1616. PP_PROVTYPE,
  1617. (BYTE *) &dwProvType,
  1618. &cb,
  1619. 0) ) {
  1620. m_keyProvInfo.dwProvType = dwProvType;
  1621. }
  1622. } else {
  1623. m_hProv = NULL;
  1624. }
  1625. }
  1626. CommonReturn:
  1627. hProvT = m_hProv;
  1628. LeaveCriticalSection(&m_csXEnroll);
  1629. if (NULL != pszProvName)
  1630. {
  1631. LocalFree(pszProvName);
  1632. }
  1633. if (NULL != pszContainerName)
  1634. {
  1635. LocalFree(pszContainerName);
  1636. }
  1637. return(hProvT);
  1638. }
  1639. BOOL CCEnroll::SetKeyParams(
  1640. PCRYPT_KEY_PROV_INFO pKeyProvInfo
  1641. ) {
  1642. EnterCriticalSection(&m_csXEnroll);
  1643. // remove provider handles
  1644. if(m_hProv != NULL)
  1645. CryptReleaseContext(m_hProv, 0);
  1646. m_hProv = NULL;
  1647. if(m_hVerifyProv != NULL)
  1648. CryptReleaseContext(m_hVerifyProv, 0);
  1649. m_hVerifyProv = NULL;
  1650. put_ContainerNameWStr(pKeyProvInfo->pwszContainerName);
  1651. put_ProviderNameWStr(pKeyProvInfo->pwszProvName);
  1652. put_ProviderFlags(pKeyProvInfo->dwFlags);
  1653. put_KeySpec(pKeyProvInfo->dwKeySpec);
  1654. put_ProviderType(pKeyProvInfo->dwProvType);
  1655. // someday we will have to pay attention to this too.
  1656. m_keyProvInfo.cProvParam = 0;
  1657. m_keyProvInfo.rgProvParam = NULL;
  1658. LeaveCriticalSection(&m_csXEnroll);
  1659. return(TRUE);
  1660. }
  1661. HRESULT STDMETHODCALLTYPE CCEnroll::createPKCS10(
  1662. /* [in] */ BSTR DNName,
  1663. /* [in] */ BSTR wszPurpose,
  1664. /* [retval][out] */ BSTR __RPC_FAR *pPKCS10) {
  1665. return(createPKCS10WStrBStr(DNName, wszPurpose, pPKCS10));
  1666. }
  1667. HRESULT CCEnroll::createPKCS10WStrBStr(
  1668. LPCWSTR DNName,
  1669. LPCWSTR wszPurpose,
  1670. BSTR __RPC_FAR *pPKCS10) {
  1671. HRESULT hr = S_OK;
  1672. CRYPT_DATA_BLOB blobPKCS10;
  1673. memset(&blobPKCS10, 0, sizeof(CRYPT_DATA_BLOB));
  1674. hr = createPKCS10WStr(DNName, wszPurpose, &blobPKCS10);
  1675. if(S_OK != hr)
  1676. {
  1677. goto createPKCS10Error;
  1678. }
  1679. // BASE64 encode pkcs 10, no header for backward compatible
  1680. hr = BlobToBstring(&blobPKCS10, CRYPT_STRING_BASE64, pPKCS10);
  1681. if (S_OK != hr)
  1682. {
  1683. goto BlobToBstringError;
  1684. }
  1685. CommonReturn:
  1686. if(NULL != blobPKCS10.pbData)
  1687. {
  1688. MyCoTaskMemFree(blobPKCS10.pbData);
  1689. }
  1690. return(hr);
  1691. ErrorReturn:
  1692. if(*pPKCS10 != NULL)
  1693. SysFreeString(*pPKCS10);
  1694. *pPKCS10 = NULL;
  1695. goto CommonReturn;
  1696. TRACE_ERROR(createPKCS10Error);
  1697. TRACE_ERROR(BlobToBstringError);
  1698. }
  1699. HRESULT CCEnroll::AddCertsToStores(
  1700. HCERTSTORE hStoreMsg,
  1701. LONG *plCertInstalled
  1702. ) {
  1703. HCERTSTORE hStoreRoot = NULL;
  1704. HCERTSTORE hStoreCA = NULL;
  1705. PCCERT_CONTEXT pCertContext = NULL;
  1706. PCCERT_CONTEXT pCertContextLast = NULL;
  1707. LONG lCertInstalled = 0;
  1708. HRESULT hr = S_OK;
  1709. //init
  1710. if (NULL != plCertInstalled)
  1711. {
  1712. *plCertInstalled = 0;
  1713. }
  1714. EnterCriticalSection(&m_csXEnroll);
  1715. if( (hStoreCA = GetStore(StoreCA)) == NULL )
  1716. goto ErrorCertOpenCAStore;
  1717. if( (hStoreRoot = GetStore(StoreROOT)) == NULL )
  1718. goto ErrorCertOpenRootStore;
  1719. // now just place the rest of the cert in either the ROOT or CA store
  1720. // we know we removed the end-entity cert from the msg store already
  1721. // put all certs that came in the message into the appropriate store
  1722. while( (pCertContext = CertEnumCertificatesInStore(
  1723. hStoreMsg,
  1724. pCertContextLast)) != NULL ) {
  1725. // if it is a self sign, it is a ROOT
  1726. if( CertCompareCertificateName(
  1727. CRYPT_ASN_ENCODING,
  1728. &pCertContext->pCertInfo->Subject,
  1729. &pCertContext->pCertInfo->Issuer) ) {
  1730. // to root store could invoke a pop up, check cancel button
  1731. // but don't error out from any fail
  1732. if (MySafeCertAddCertificateContextToStore(
  1733. hStoreRoot,
  1734. pCertContext,
  1735. CERT_STORE_ADD_USE_EXISTING,
  1736. NULL,
  1737. m_dwEnabledSafteyOptions))
  1738. {
  1739. ++lCertInstalled;
  1740. }
  1741. else
  1742. {
  1743. if (S_OK == hr)
  1744. {
  1745. //save the 1st error as return
  1746. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1747. if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr)
  1748. {
  1749. //map generic access deny to xenroll error
  1750. hr = XENROLL_E_CANNOT_ADD_ROOT_CERT;
  1751. }
  1752. }
  1753. //don't goto error here and finish the loop
  1754. }
  1755. }
  1756. // if it is not the MY cert, it must go in the CA store
  1757. // do nothing with the MY cert as we already handled it
  1758. else {
  1759. // likewise we don't care if these get added to the
  1760. // CA store
  1761. if (MySafeCertAddCertificateContextToStore(
  1762. hStoreCA,
  1763. pCertContext,
  1764. CERT_STORE_ADD_USE_EXISTING,
  1765. NULL,
  1766. m_dwEnabledSafteyOptions))
  1767. {
  1768. //no error code check
  1769. ++lCertInstalled;
  1770. }
  1771. }
  1772. pCertContextLast = pCertContext;
  1773. }
  1774. pCertContextLast = NULL;
  1775. if (NULL != plCertInstalled)
  1776. {
  1777. *plCertInstalled = lCertInstalled;
  1778. }
  1779. CommonReturn:
  1780. LeaveCriticalSection(&m_csXEnroll);
  1781. return(hr);
  1782. ErrorReturn:
  1783. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1784. if(GetLastError() == ERROR_SUCCESS)
  1785. SetLastError((DWORD)E_UNEXPECTED);
  1786. goto CommonReturn;
  1787. TRACE_ERROR(ErrorCertOpenCAStore);
  1788. TRACE_ERROR(ErrorCertOpenRootStore);
  1789. }
  1790. BOOL
  1791. IsDesiredProperty(DWORD dwPropertyId)
  1792. {
  1793. DWORD DesiredIds[] = {
  1794. CERT_PVK_FILE_PROP_ID,
  1795. CERT_FRIENDLY_NAME_PROP_ID,
  1796. CERT_DESCRIPTION_PROP_ID,
  1797. CERT_RENEWAL_PROP_ID,
  1798. };
  1799. DWORD i;
  1800. for (i = 0; i < ARRAYSIZE(DesiredIds); ++i)
  1801. {
  1802. if (dwPropertyId == DesiredIds[i])
  1803. {
  1804. return TRUE;
  1805. }
  1806. }
  1807. return FALSE;
  1808. }
  1809. BOOL
  1810. IsFilteredOutProperty(DWORD dwPropertyId)
  1811. {
  1812. DWORD FilteredIds[] = {
  1813. XENROLL_RENEWAL_CERTIFICATE_PROP_ID,
  1814. XENROLL_PASS_THRU_PROP_ID,
  1815. CERT_KEY_PROV_INFO_PROP_ID,
  1816. CERT_ENROLLMENT_PROP_ID, //pending property
  1817. };
  1818. DWORD i;
  1819. for (i = 0; i < ARRAYSIZE(FilteredIds); ++i)
  1820. {
  1821. if (dwPropertyId == FilteredIds[i])
  1822. {
  1823. return TRUE;
  1824. }
  1825. }
  1826. return FALSE;
  1827. }
  1828. HRESULT CCEnroll::GetEndEntityCert(
  1829. PCRYPT_DATA_BLOB pBlobPKCS7,
  1830. BOOL fSaveToStores,
  1831. PCCERT_CONTEXT *ppCert
  1832. )
  1833. {
  1834. HRESULT hr = S_OK;
  1835. HCERTSTORE hStoreMsg = NULL;
  1836. HCERTSTORE hStoreMy = NULL;
  1837. HCERTSTORE hStoreRequest = NULL;
  1838. PCCERT_CONTEXT pCertContextLast = NULL;
  1839. PCCERT_CONTEXT pCertContextRequest = NULL;
  1840. PCCERT_CONTEXT pCertContextMsg = NULL;
  1841. PCCERT_CONTEXT pCertContextArchive = NULL;
  1842. PCRYPT_KEY_PROV_INFO pKeyProvInfo = NULL;
  1843. DWORD cb = 0;
  1844. CRYPT_DATA_BLOB blobData;
  1845. CRYPT_HASH_BLOB blobHash = {sizeof(m_arHashBytesNewCert), m_arHashBytesNewCert};
  1846. CRYPT_HASH_BLOB blobHashRenew = {sizeof(m_arHashBytesOldCert), m_arHashBytesOldCert};
  1847. RequestFlags requestFlags;
  1848. CRYPT_HASH_BLOB requestFlagsBlob;
  1849. CRYPT_HASH_BLOB renewalCertBlob;
  1850. //Bug #202557 for IE3.02 upd clients (xiaohs)
  1851. HCRYPTPROV hProv=NULL;
  1852. BOOL fSetting;
  1853. DWORD dwPropertyId;
  1854. CRYPT_DATA_BLOB blobProp;
  1855. BYTE *pbArchivedKeyHash = NULL;
  1856. DWORD cbArchivedKeyHash = 0;
  1857. EnterCriticalSection(&m_csXEnroll);
  1858. memset(&requestFlags, 0, sizeof(RequestFlags));
  1859. memset(&blobData, 0, sizeof(CRYPT_DATA_BLOB));
  1860. memset(&requestFlagsBlob, 0, sizeof(CRYPT_DATA_BLOB));
  1861. memset(&renewalCertBlob, 0, sizeof(CRYPT_DATA_BLOB));
  1862. ZeroMemory(&blobProp, sizeof(blobProp));
  1863. if (NULL == ppCert)
  1864. {
  1865. hr = MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  1866. goto InvalidParameterError;
  1867. }
  1868. //init return
  1869. *ppCert = NULL;
  1870. if(!MyCryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  1871. pBlobPKCS7,
  1872. (CERT_QUERY_CONTENT_FLAG_CERT |
  1873. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  1874. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  1875. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  1876. CERT_QUERY_FORMAT_FLAG_ALL,
  1877. 0,
  1878. NULL,
  1879. NULL,
  1880. NULL,
  1881. &hStoreMsg,
  1882. NULL,
  1883. NULL))
  1884. {
  1885. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1886. goto ErrorCryptQueryObject;
  1887. }
  1888. // check to see if this hash is in the message
  1889. if (m_pCertContextStatic == NULL ||
  1890. (NULL == (pCertContextMsg = CertFindCertificateInStore(
  1891. hStoreMsg,
  1892. X509_ASN_ENCODING,
  1893. 0,
  1894. CERT_FIND_HASH,
  1895. &blobHash,
  1896. NULL))))
  1897. {
  1898. // open the request store
  1899. if (NULL == (hStoreRequest = GetStore(StoreREQUEST)))
  1900. {
  1901. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1902. goto ErrorCertOpenRequestStore;
  1903. }
  1904. // find cert in request store that matches cert
  1905. // in message, by public key
  1906. while (NULL != (pCertContextMsg = CertEnumCertificatesInStore(
  1907. hStoreMsg,
  1908. pCertContextLast)))
  1909. {
  1910. // check to see if this is in the request store
  1911. if (NULL != (pCertContextRequest = CertFindCertificateInStore(
  1912. hStoreRequest,
  1913. CRYPT_ASN_ENCODING,
  1914. 0,
  1915. CERT_FIND_PUBLIC_KEY,
  1916. (void *) &pCertContextMsg->pCertInfo->SubjectPublicKeyInfo,
  1917. NULL)))
  1918. {
  1919. // found a match, get out
  1920. break;
  1921. }
  1922. pCertContextLast = pCertContextMsg;
  1923. }
  1924. pCertContextLast = NULL;
  1925. // if we didn't find one, then GetLastError was set either
  1926. // by CertEnumCerificatesInStore or CertEnumCerificatesInStore
  1927. if (NULL == pCertContextRequest)
  1928. {
  1929. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1930. goto ErrorNoCertFound;
  1931. }
  1932. if (fSaveToStores)
  1933. {
  1934. // check archived key hash property first
  1935. // if the property exists, means key archival was in the request
  1936. cb = 0;
  1937. while (TRUE)
  1938. {
  1939. if(!CertGetCertificateContextProperty(
  1940. pCertContextRequest,
  1941. CERT_ARCHIVED_KEY_HASH_PROP_ID,
  1942. pbArchivedKeyHash,
  1943. &cbArchivedKeyHash))
  1944. {
  1945. if (NULL == pbArchivedKeyHash)
  1946. {
  1947. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1948. if (MY_HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND) == hr)
  1949. {
  1950. //no such property, so we are done
  1951. break;
  1952. }
  1953. // some other error
  1954. goto ErrorCertGetCertificateContextProperty;
  1955. }
  1956. else
  1957. {
  1958. //if pbArchivedKeyHash non-null, error
  1959. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  1960. goto ErrorCertGetCertificateContextProperty;
  1961. }
  1962. }
  1963. if (NULL != pbArchivedKeyHash)
  1964. {
  1965. //got it, done
  1966. break;
  1967. }
  1968. pbArchivedKeyHash = (BYTE*)LocalAlloc(
  1969. LMEM_FIXED, cbArchivedKeyHash);
  1970. if (NULL == pbArchivedKeyHash)
  1971. {
  1972. hr = E_OUTOFMEMORY;
  1973. goto OutOfMemoryError;
  1974. }
  1975. }
  1976. if (NULL != pbArchivedKeyHash && NULL == m_blobResponseKAHash.pbData)
  1977. {
  1978. //request cert has archived key hash but response
  1979. //doesn't contain key hash for verification. maybe
  1980. //a spoofing response?
  1981. hr = XENROLL_E_RESPONSE_KA_HASH_NOT_FOUND;
  1982. goto ResponseKAHashNotFoundError;
  1983. }
  1984. if (NULL == pbArchivedKeyHash && NULL != m_blobResponseKAHash.pbData)
  1985. {
  1986. //request cert doesn't have archived key hash but
  1987. //response does. confliciting. seems no security harm
  1988. hr = XENROLL_E_RESPONSE_UNEXPECTED_KA_HASH;
  1989. goto ResponseUnexpectedKAHashError;
  1990. }
  1991. if (NULL != pbArchivedKeyHash && NULL != m_blobResponseKAHash.pbData)
  1992. {
  1993. //now we should check if they match
  1994. //compare size and hash
  1995. if (cbArchivedKeyHash != m_blobResponseKAHash.cbData ||
  1996. 0 != memcmp(pbArchivedKeyHash,
  1997. m_blobResponseKAHash.pbData,
  1998. cbArchivedKeyHash))
  1999. {
  2000. //oh, potential attack
  2001. hr = XENROLL_E_RESPONSE_KA_HASH_MISMATCH;
  2002. //should remove the request cert?
  2003. goto ResponseKAMismatchError;
  2004. }
  2005. }
  2006. }
  2007. // get those request cert properties that are,
  2008. // either the property not blob property
  2009. // or blob property needs special handling
  2010. // Important: remember to add these Ids in IsFilteredOutProperty
  2011. fSetting = TRUE;
  2012. cb = 0;
  2013. while (TRUE)
  2014. {
  2015. if(!CertGetCertificateContextProperty(
  2016. pCertContextRequest,
  2017. CERT_KEY_PROV_INFO_PROP_ID,
  2018. pKeyProvInfo,
  2019. &cb))
  2020. {
  2021. if (NULL == pKeyProvInfo)
  2022. {
  2023. //skip setting
  2024. fSetting = FALSE;
  2025. break;
  2026. }
  2027. else
  2028. {
  2029. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2030. goto ErrorCertGetCertificateContextProperty;
  2031. }
  2032. }
  2033. if (NULL != pKeyProvInfo)
  2034. {
  2035. //got it, done
  2036. break;
  2037. }
  2038. pKeyProvInfo = (PCRYPT_KEY_PROV_INFO)LocalAlloc(LMEM_FIXED, cb);
  2039. if (NULL == pKeyProvInfo)
  2040. {
  2041. hr = E_OUTOFMEMORY;
  2042. goto OutOfMemoryError;
  2043. }
  2044. }
  2045. if (fSetting)
  2046. {
  2047. // put the property on the returned cert
  2048. if( !CertSetCertificateContextProperty(
  2049. pCertContextMsg,
  2050. CERT_KEY_PROV_INFO_PROP_ID,
  2051. 0,
  2052. pKeyProvInfo) )
  2053. {
  2054. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2055. goto ErrorSetMyCertPropError;
  2056. }
  2057. // Set the provider info
  2058. SetKeyParams(pKeyProvInfo);
  2059. }
  2060. fSetting = TRUE;
  2061. while (TRUE)
  2062. {
  2063. if(!CertGetCertificateContextProperty(
  2064. pCertContextRequest,
  2065. XENROLL_PASS_THRU_PROP_ID,
  2066. requestFlagsBlob.pbData,
  2067. &requestFlagsBlob.cbData) )
  2068. {
  2069. if (NULL == requestFlagsBlob.pbData)
  2070. {
  2071. //do nothing
  2072. fSetting = FALSE;
  2073. break;
  2074. }
  2075. else
  2076. {
  2077. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2078. goto ErrorDecodeRequestFlags;
  2079. }
  2080. }
  2081. if (NULL != requestFlagsBlob.pbData)
  2082. {
  2083. //got it, done
  2084. break;
  2085. }
  2086. requestFlagsBlob.pbData = (BYTE *)LocalAlloc(LMEM_FIXED,
  2087. requestFlagsBlob.cbData);
  2088. if (NULL == requestFlagsBlob.pbData)
  2089. {
  2090. hr = E_OUTOFMEMORY;
  2091. goto OutOfMemoryError;
  2092. }
  2093. }
  2094. if (fSetting)
  2095. {
  2096. // get the encoded blob
  2097. cb = sizeof(requestFlags);
  2098. // since this is a private data structure, its size should be
  2099. // known and this should aways pass
  2100. if (!CryptDecodeObject(
  2101. CRYPT_ASN_ENCODING,
  2102. XENROLL_REQUEST_INFO,
  2103. requestFlagsBlob.pbData,
  2104. requestFlagsBlob.cbData,
  2105. 0,
  2106. &requestFlags,
  2107. &cb))
  2108. {
  2109. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2110. goto ErrorDecodeRequestFlags;
  2111. }
  2112. // now set the flags
  2113. if(!m_fWriteCertToCSPModified)
  2114. m_fWriteCertToCSP = requestFlags.fWriteToCSP;
  2115. if(!m_fWriteCertToUserDSModified)
  2116. m_fWriteCertToUserDS = requestFlags.fWriteToDS;
  2117. if(!m_fRequestStoreOpenFlagsModified)
  2118. m_RequestStore.dwFlags = requestFlags.openFlags;
  2119. if(!m_fMyStoreOpenFlagsModified)
  2120. m_MyStore.dwFlags = (m_MyStore.dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK) |
  2121. (requestFlags.openFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
  2122. if(!m_fCAStoreOpenFlagsModified)
  2123. m_CAStore.dwFlags = (m_CAStore.dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK) |
  2124. (requestFlags.openFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
  2125. if(!m_fRootStoreOpenFlagsModified) {
  2126. //
  2127. // POTENTIAL SCRIPTING VIOLATION: we're mapping request store flags directly to root store flags.
  2128. // If they have set request store flags to local machine, propagate this setting to the root store flags,
  2129. // but set the root store name to "CA".
  2130. //
  2131. if (0 != m_dwEnabledSafteyOptions) {
  2132. if (requestFlags.openFlags & CERT_SYSTEM_STORE_LOCAL_MACHINE) {
  2133. m_RootStore.wszName = wszCA;
  2134. }
  2135. }
  2136. m_RootStore.dwFlags = (m_RootStore.dwFlags & ~CERT_SYSTEM_STORE_LOCATION_MASK) |
  2137. (requestFlags.openFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
  2138. }
  2139. }
  2140. // see if this is a renewal request
  2141. m_fArchiveOldCert = FALSE;
  2142. fSetting = TRUE;
  2143. while (TRUE)
  2144. {
  2145. // get the encoded blob
  2146. if (!CertGetCertificateContextProperty(
  2147. pCertContextRequest,
  2148. XENROLL_RENEWAL_CERTIFICATE_PROP_ID,
  2149. renewalCertBlob.pbData,
  2150. &renewalCertBlob.cbData))
  2151. {
  2152. if (NULL == renewalCertBlob.pbData)
  2153. {
  2154. fSetting = FALSE;
  2155. break;
  2156. }
  2157. else
  2158. {
  2159. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2160. goto ErrorCertGetCertificateContextProperty;
  2161. }
  2162. }
  2163. if (NULL != renewalCertBlob.pbData)
  2164. {
  2165. //got it, done
  2166. break;
  2167. }
  2168. renewalCertBlob.pbData = (BYTE *)LocalAlloc(LMEM_FIXED,
  2169. renewalCertBlob.cbData);
  2170. if (NULL == renewalCertBlob.pbData)
  2171. {
  2172. hr = E_OUTOFMEMORY;
  2173. goto OutOfMemoryError;
  2174. }
  2175. }
  2176. if (fSetting)
  2177. {
  2178. //Bug #202557 for IE3.02 upd clients (xiaohs)
  2179. if (NULL==hProv)
  2180. {
  2181. if(!CryptAcquireContext(
  2182. &hProv,
  2183. NULL,
  2184. MS_DEF_PROV,
  2185. PROV_RSA_FULL,
  2186. CRYPT_VERIFYCONTEXT))
  2187. {
  2188. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2189. goto ErrorAcquireContext;
  2190. }
  2191. }
  2192. if (!CryptHashCertificate(
  2193. hProv, //NULL, Bug #202557 for IE3.02 upd clients (xiaohs)
  2194. 0, //alg
  2195. X509_ASN_ENCODING, //0 dwFlags
  2196. renewalCertBlob.pbData,
  2197. renewalCertBlob.cbData,
  2198. blobHashRenew.pbData,
  2199. &blobHashRenew.cbData))
  2200. {
  2201. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2202. goto ErrorCryptHashCertificate;
  2203. }
  2204. m_fArchiveOldCert = TRUE;
  2205. }
  2206. //get rest of blob properties from request store and set to the cert
  2207. dwPropertyId = CertEnumCertificateContextProperties(
  2208. pCertContextRequest, 0); //enum from 1st
  2209. while (0 != dwPropertyId)
  2210. {
  2211. // if (!IsFilteredOutProperty(dwPropertyId))
  2212. //because iis cert install doesn't like to copy all properties from
  2213. //request cert to install cert we just copy selected properties for now
  2214. if (IsDesiredProperty(dwPropertyId))
  2215. {
  2216. fSetting = TRUE;
  2217. while (TRUE)
  2218. {
  2219. if (!CertGetCertificateContextProperty(
  2220. pCertContextRequest,
  2221. dwPropertyId,
  2222. blobProp.pbData,
  2223. &blobProp.cbData))
  2224. {
  2225. //no get, no set, go on
  2226. fSetting = FALSE;
  2227. break;
  2228. }
  2229. if (NULL != blobProp.pbData)
  2230. {
  2231. //done
  2232. break;
  2233. }
  2234. blobProp.pbData = (BYTE*)LocalAlloc(LMEM_FIXED,
  2235. blobProp.cbData);
  2236. if (NULL == blobProp.pbData)
  2237. {
  2238. goto OutOfMemoryError;
  2239. }
  2240. }
  2241. if (fSetting)
  2242. {
  2243. //should get the property from the request cert
  2244. if (!CertSetCertificateContextProperty(
  2245. pCertContextMsg,
  2246. dwPropertyId,
  2247. 0,
  2248. &blobProp))
  2249. {
  2250. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2251. goto ErrorSetMyCertPropError;
  2252. }
  2253. }
  2254. if (NULL != blobProp.pbData)
  2255. {
  2256. //set for the next enum
  2257. LocalFree(blobProp.pbData);
  2258. blobProp.pbData = NULL;
  2259. }
  2260. }
  2261. dwPropertyId = CertEnumCertificateContextProperties(
  2262. pCertContextRequest,
  2263. dwPropertyId);
  2264. }
  2265. // save this away in the cache
  2266. if(m_pCertContextStatic != NULL)
  2267. CertFreeCertificateContext(m_pCertContextStatic);
  2268. m_pCertContextStatic = CertDuplicateCertificateContext(pCertContextMsg);
  2269. //Bug #202557 for IE3.02 upd clients (xiaohs)
  2270. if(NULL==hProv)
  2271. {
  2272. if(!CryptAcquireContext(
  2273. &hProv,
  2274. NULL,
  2275. MS_DEF_PROV,
  2276. PROV_RSA_FULL,
  2277. CRYPT_VERIFYCONTEXT))
  2278. {
  2279. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2280. goto ErrorAcquireContext;
  2281. }
  2282. }
  2283. if( !CryptHashCertificate(
  2284. hProv, //NULL Bug #202557 for IE3.02 upd clients (xiaohs)
  2285. 0,
  2286. X509_ASN_ENCODING,
  2287. pCertContextMsg->pbCertEncoded,
  2288. pCertContextMsg->cbCertEncoded,
  2289. blobHash.pbData,
  2290. &blobHash.cbData) )
  2291. {
  2292. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2293. goto ErrorCryptHashCertificate;
  2294. }
  2295. }
  2296. // at this point we have 2 context m_pCertContextStatic which we want to return to the user
  2297. // and pCertContextMsg which we want to delete from the Msg store
  2298. assert(pCertContextMsg != NULL);
  2299. CertDeleteCertificateFromStore(pCertContextMsg);
  2300. pCertContextMsg = NULL; // freed by the delete
  2301. // we want to return our static, so make a dup and this is what we will return
  2302. assert(m_pCertContextStatic != NULL);
  2303. pCertContextMsg = CertDuplicateCertificateContext(m_pCertContextStatic);
  2304. // put these in the stores if asked
  2305. if(fSaveToStores) {
  2306. // open the stores
  2307. if( (hStoreMy = GetStore(StoreMY)) == NULL)
  2308. {
  2309. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2310. goto ErrorCertOpenMYStore;
  2311. }
  2312. // we know that the pCertContextMsg is a dup of the end-entity cert in m_pCertContextStatic
  2313. // and we want to put this in the MY store
  2314. assert(pCertContextMsg != NULL);
  2315. if( !MySafeCertAddCertificateContextToStore(
  2316. hStoreMy,
  2317. pCertContextMsg,
  2318. CERT_STORE_ADD_USE_EXISTING,
  2319. NULL,
  2320. m_dwEnabledSafteyOptions) )
  2321. {
  2322. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2323. goto ErrorCertAddToMyStore;
  2324. }
  2325. // If we have renewal, then mark the old cert as an archive
  2326. if(m_fArchiveOldCert &&
  2327. ((pCertContextArchive = CertFindCertificateInStore(
  2328. hStoreMy,
  2329. X509_ASN_ENCODING,
  2330. 0,
  2331. CERT_FIND_HASH,
  2332. &blobHashRenew,
  2333. NULL)) != NULL) ) {
  2334. // Set the Archive property on the cert.
  2335. // crypt32 in IE3.02upd does not support this prop, so don't fail on error
  2336. CertSetCertificateContextProperty(
  2337. pCertContextArchive,
  2338. CERT_ARCHIVED_PROP_ID,
  2339. 0,
  2340. &blobData);
  2341. //set new cert hash on old archived cert
  2342. //ignore error if it fails
  2343. CertSetCertificateContextProperty(
  2344. pCertContextArchive,
  2345. CERT_RENEWAL_PROP_ID,
  2346. 0,
  2347. &blobHash);
  2348. }
  2349. // add the rest of the certs to the stores
  2350. hr = AddCertsToStores(hStoreMsg, NULL);
  2351. //ignore cancel error since it from root cert install
  2352. //ignore XENROLL_E_CANNOT_ADD_ROOT_CERT also
  2353. if (S_OK != hr &&
  2354. MY_HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr &&
  2355. XENROLL_E_CANNOT_ADD_ROOT_CERT != hr)
  2356. {
  2357. goto ErrorAddCertsToStores;
  2358. }
  2359. }
  2360. *ppCert = pCertContextMsg;
  2361. CommonReturn:
  2362. //Bug #202557 for IE3.02 upd clients (xiaohs)
  2363. if(hProv)
  2364. CryptReleaseContext(hProv, 0);
  2365. if(pCertContextRequest != NULL)
  2366. CertFreeCertificateContext(pCertContextRequest);
  2367. if(pCertContextArchive != NULL)
  2368. CertFreeCertificateContext(pCertContextArchive);
  2369. // it really should be NULL
  2370. assert(pCertContextLast == NULL);
  2371. if(hStoreMsg != NULL)
  2372. CertCloseStore(hStoreMsg, 0);
  2373. // we need to do this because the store that may be opened is the systemstore, but
  2374. // the store we may need is the local machine store, but we don't know that until the
  2375. // system store finds the request cert in the local machine physical store.
  2376. // Later when we do the delete, we want the local machine store open.
  2377. FlushStore(StoreREQUEST);
  2378. if (NULL != requestFlagsBlob.pbData)
  2379. {
  2380. LocalFree(requestFlagsBlob.pbData);
  2381. }
  2382. if (NULL != renewalCertBlob.pbData)
  2383. {
  2384. LocalFree(renewalCertBlob.pbData);
  2385. }
  2386. if (NULL != blobProp.pbData)
  2387. {
  2388. LocalFree(blobProp.pbData);
  2389. }
  2390. if (NULL != pKeyProvInfo)
  2391. {
  2392. LocalFree(pKeyProvInfo);
  2393. }
  2394. if (NULL != pbArchivedKeyHash)
  2395. {
  2396. LocalFree(pbArchivedKeyHash);
  2397. }
  2398. LeaveCriticalSection(&m_csXEnroll);
  2399. return (hr);
  2400. ErrorReturn:
  2401. if(NULL != pCertContextMsg)
  2402. {
  2403. CertFreeCertificateContext(pCertContextMsg);
  2404. }
  2405. goto CommonReturn;
  2406. TRACE_ERROR(ErrorCryptHashCertificate);
  2407. TRACE_ERROR(ErrorCertOpenMYStore);
  2408. TRACE_ERROR(ErrorCertAddToMyStore);
  2409. TRACE_ERROR(ErrorCryptQueryObject);
  2410. TRACE_ERROR(ErrorCertOpenRequestStore);
  2411. TRACE_ERROR(ErrorNoCertFound);
  2412. TRACE_ERROR(ErrorCertGetCertificateContextProperty);
  2413. TRACE_ERROR(ErrorSetMyCertPropError);
  2414. TRACE_ERROR(ErrorDecodeRequestFlags);
  2415. TRACE_ERROR(ErrorAcquireContext); //Bug #202557 for IE3.02 upd clients (xiaohs)
  2416. TRACE_ERROR(ErrorAddCertsToStores);
  2417. TRACE_ERROR(OutOfMemoryError);
  2418. TRACE_ERROR(InvalidParameterError);
  2419. TRACE_ERROR(ResponseKAMismatchError)
  2420. TRACE_ERROR(ResponseUnexpectedKAHashError)
  2421. TRACE_ERROR(ResponseKAHashNotFoundError)
  2422. }
  2423. HRESULT STDMETHODCALLTYPE CCEnroll::getCertFromPKCS7(
  2424. /* [in] */ BSTR wszPKCS7,
  2425. /* [retval][out] */ BSTR __RPC_FAR *pbstrCert
  2426. ) {
  2427. HRESULT hr;
  2428. CRYPT_DATA_BLOB blobPKCS7;
  2429. CRYPT_DATA_BLOB blobX509;
  2430. PCCERT_CONTEXT pCertContextMy = NULL;
  2431. assert(wszPKCS7 != NULL && pbstrCert != NULL);
  2432. if (NULL == wszPKCS7 || NULL == pbstrCert)
  2433. goto PointerError;
  2434. // just put into a blob
  2435. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  2436. blobPKCS7.cbData = SysStringByteLen(wszPKCS7);
  2437. blobPKCS7.pbData = (PBYTE) wszPKCS7;
  2438. // Get a Cert Context for the end-entity
  2439. if( (pCertContextMy = getCertContextFromPKCS7(&blobPKCS7)) == NULL)
  2440. {
  2441. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2442. goto getCertContextFromPKCS7Error;
  2443. }
  2444. blobX509.pbData = pCertContextMy->pbCertEncoded;
  2445. blobX509.cbData = pCertContextMy->cbCertEncoded;
  2446. //base64 with no header for backward compatible
  2447. hr = BlobToBstring(&blobX509, CRYPT_STRING_BASE64, pbstrCert);
  2448. if (S_OK != hr)
  2449. {
  2450. goto BlobToBstringError;
  2451. }
  2452. hr = S_OK;
  2453. ErrorReturn:
  2454. if(pCertContextMy != NULL)
  2455. CertFreeCertificateContext(pCertContextMy);
  2456. return(hr);
  2457. SET_HRESULT(PointerError, E_POINTER);
  2458. TRACE_ERROR(getCertContextFromPKCS7Error);
  2459. TRACE_ERROR(BlobToBstringError);
  2460. }
  2461. HRESULT STDMETHODCALLTYPE CCEnroll::acceptPKCS7(
  2462. /* [in] */ BSTR wszPKCS7) {
  2463. CRYPT_DATA_BLOB blobPKCS7;
  2464. HRESULT hr;
  2465. assert(wszPKCS7 != NULL);
  2466. if (NULL == wszPKCS7)
  2467. goto PointerError;
  2468. // just put into a blob
  2469. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  2470. blobPKCS7.cbData = SysStringByteLen(wszPKCS7);
  2471. blobPKCS7.pbData = (PBYTE) wszPKCS7;
  2472. // accept the blob
  2473. hr = acceptPKCS7Blob(&blobPKCS7);
  2474. ErrorReturn:
  2475. return hr;
  2476. SET_HRESULT(PointerError, E_POINTER);
  2477. }
  2478. HRESULT STDMETHODCALLTYPE CCEnroll::createFilePKCS10(
  2479. /* [in] */ BSTR DNName,
  2480. /* [in] */ BSTR Usage,
  2481. /* [in] */ BSTR wszPKCS10FileName) {
  2482. return(createFilePKCS10WStr(DNName, Usage, wszPKCS10FileName));
  2483. }
  2484. HRESULT STDMETHODCALLTYPE CCEnroll::addCertTypeToRequest(
  2485. /* [in] */ BSTR CertType) {
  2486. return(AddCertTypeToRequestWStr(CertType));
  2487. }
  2488. HRESULT STDMETHODCALLTYPE CCEnroll::addCertTypeToRequestEx(
  2489. IN LONG lType,
  2490. IN BSTR bstrOIDOrName,
  2491. IN LONG lMajorVersion,
  2492. IN BOOL fMinorVersion,
  2493. IN LONG lMinorVersion)
  2494. {
  2495. return AddCertTypeToRequestWStrEx(
  2496. lType,
  2497. bstrOIDOrName,
  2498. lMajorVersion,
  2499. fMinorVersion,
  2500. lMinorVersion);
  2501. }
  2502. HRESULT STDMETHODCALLTYPE CCEnroll::getProviderType(
  2503. IN BSTR strProvName,
  2504. OUT LONG *plProvType)
  2505. {
  2506. return getProviderTypeWStr(strProvName, plProvType);
  2507. }
  2508. HRESULT STDMETHODCALLTYPE CCEnroll::addNameValuePairToSignature(
  2509. /* [in] */ BSTR Name,
  2510. /* [in] */ BSTR Value) {
  2511. return(AddNameValuePairToSignatureWStr(Name, Value));
  2512. }
  2513. HRESULT STDMETHODCALLTYPE CCEnroll::acceptFilePKCS7(
  2514. /* [in] */ BSTR wszPKCS7FileName) {
  2515. return(acceptFilePKCS7WStr(wszPKCS7FileName));
  2516. }
  2517. HRESULT STDMETHODCALLTYPE CCEnroll::freeRequestInfo(
  2518. /* [in] */ BSTR bstrPKCS7OrPKCS10)
  2519. {
  2520. HRESULT hr;
  2521. CRYPT_DATA_BLOB blob;
  2522. BYTE *pbData = NULL;
  2523. DWORD cbData = 0;
  2524. // could be base64
  2525. while (TRUE)
  2526. {
  2527. if (!MyCryptStringToBinaryW(
  2528. (WCHAR*)bstrPKCS7OrPKCS10,
  2529. SysStringLen(bstrPKCS7OrPKCS10),
  2530. CRYPT_STRING_ANY,
  2531. pbData,
  2532. &cbData,
  2533. NULL,
  2534. NULL))
  2535. {
  2536. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2537. goto MyCryptStringToBinaryWError;
  2538. }
  2539. if (NULL != pbData)
  2540. {
  2541. break; //done
  2542. }
  2543. pbData = (BYTE*)LocalAlloc(LMEM_FIXED, cbData);
  2544. if (NULL == pbData)
  2545. {
  2546. hr = E_OUTOFMEMORY;
  2547. goto OutOfMemoryError;
  2548. }
  2549. }
  2550. blob.cbData = cbData;
  2551. blob.pbData = pbData;
  2552. hr = freeRequestInfoBlob(blob);
  2553. if (S_OK != hr)
  2554. {
  2555. goto freeRequestInfoBlobError;
  2556. }
  2557. hr = S_OK;
  2558. ErrorReturn:
  2559. if (NULL != pbData)
  2560. {
  2561. LocalFree(pbData);
  2562. }
  2563. return hr;
  2564. TRACE_ERROR(MyCryptStringToBinaryWError)
  2565. TRACE_ERROR(OutOfMemoryError)
  2566. TRACE_ERROR(freeRequestInfoBlobError)
  2567. }
  2568. //
  2569. // MY STORE
  2570. //
  2571. HCERTSTORE STDMETHODCALLTYPE CCEnroll::getMyStore( void)
  2572. {
  2573. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2574. return NULL;
  2575. }
  2576. HRESULT STDMETHODCALLTYPE CCEnroll::get_MyStoreName(
  2577. /* [retval][out] */ BSTR __RPC_FAR *pbstrName) {
  2578. HRESULT hr = S_OK;
  2579. EnterCriticalSection(&m_csXEnroll);
  2580. if(m_MyStore.wszName == NULL)
  2581. return(ERROR_UNKNOWN_PROPERTY);
  2582. if( (*pbstrName = SysAllocString(m_MyStore.wszName)) == NULL )
  2583. hr = E_OUTOFMEMORY;
  2584. LeaveCriticalSection(&m_csXEnroll);
  2585. return(hr);
  2586. }
  2587. HRESULT STDMETHODCALLTYPE CCEnroll::put_MyStoreName(
  2588. /* [in] */ BSTR bstrName) {
  2589. return(put_MyStoreNameWStr(bstrName));
  2590. }
  2591. HRESULT STDMETHODCALLTYPE CCEnroll::get_MyStoreType(
  2592. /* [retval][out] */ BSTR __RPC_FAR *pbstrType) {
  2593. HRESULT hr = S_OK;
  2594. EnterCriticalSection(&m_csXEnroll);
  2595. if( (*pbstrType = BSTRFromMB(m_MyStore.szType)) == NULL )
  2596. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2597. LeaveCriticalSection(&m_csXEnroll);
  2598. return(hr);
  2599. }
  2600. HRESULT STDMETHODCALLTYPE CCEnroll::put_MyStoreType(
  2601. /* [in] */ BSTR bstrType) {
  2602. return(put_MyStoreTypeWStr(bstrType));
  2603. }
  2604. HRESULT STDMETHODCALLTYPE CCEnroll::get_MyStoreFlags(
  2605. /* [retval][out] */ LONG __RPC_FAR *pdwFlags) {
  2606. EnterCriticalSection(&m_csXEnroll);
  2607. *pdwFlags = m_MyStore.dwFlags;
  2608. LeaveCriticalSection(&m_csXEnroll);
  2609. return(S_OK);
  2610. }
  2611. //--------------------------------------------------------------------------------
  2612. //
  2613. // This method is only safe for scripting if it's parameter is safe.
  2614. // See VerifyStoreFlagsSafeForScripting().
  2615. //
  2616. //--------------------------------------------------------------------------------
  2617. HRESULT STDMETHODCALLTYPE CCEnroll::put_MyStoreFlags(
  2618. /* [in] */ LONG dwFlags) {
  2619. HRESULT hr = S_OK;
  2620. EnterCriticalSection(&m_csXEnroll);
  2621. // If we're marked as safe for scripting, see if the flags passed in are safe:
  2622. if (0 != m_dwEnabledSafteyOptions && !VerifyStoreFlagsSafeForScripting(dwFlags))
  2623. goto AccessDeniedError;
  2624. if(m_MyStore.hStore != NULL)
  2625. hr = E_ACCESSDENIED;
  2626. else {
  2627. // set the my store flags
  2628. m_MyStore.dwFlags = dwFlags;
  2629. m_fMyStoreOpenFlagsModified = TRUE;
  2630. m_keyProvInfo.dwFlags |= KeyLocationFromStoreLocation(dwFlags);
  2631. // track the request store location to the my store, only if the request store has not been modified
  2632. // do NOT set the modify bit for the request store, this is a default
  2633. if(!m_fRequestStoreOpenFlagsModified) {
  2634. m_RequestStore.dwFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
  2635. m_RequestStore.dwFlags |= (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
  2636. }
  2637. }
  2638. ErrorReturn:
  2639. LeaveCriticalSection(&m_csXEnroll);
  2640. return(hr);
  2641. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2642. }
  2643. HRESULT STDMETHODCALLTYPE CCEnroll::get_MyStoreNameWStr(
  2644. /* [out] */ LPWSTR __RPC_FAR *szwName) {
  2645. HRESULT hr = S_OK;
  2646. EnterCriticalSection(&m_csXEnroll);
  2647. if(m_MyStore.wszName == NULL)
  2648. return(ERROR_UNKNOWN_PROPERTY);
  2649. if( (*szwName = CopyWideString(m_MyStore.wszName)) == NULL )
  2650. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2651. LeaveCriticalSection(&m_csXEnroll);
  2652. return(hr);
  2653. }
  2654. //--------------------------------------------------------------------------------
  2655. //
  2656. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2657. //
  2658. //--------------------------------------------------------------------------------
  2659. HRESULT STDMETHODCALLTYPE CCEnroll::put_MyStoreNameWStr(
  2660. /* [in] */ LPWSTR szwName) {
  2661. HRESULT hr = S_OK;
  2662. EnterCriticalSection(&m_csXEnroll);
  2663. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2664. goto AccessDeniedError;
  2665. if(m_MyStore.hStore != NULL)
  2666. hr = E_ACCESSDENIED;
  2667. else {
  2668. if(m_MyStore.wszName != wszMY)
  2669. MyCoTaskMemFree(m_MyStore.wszName);
  2670. if( (m_MyStore.wszName = CopyWideString(szwName)) == NULL )
  2671. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2672. }
  2673. ErrorReturn:
  2674. LeaveCriticalSection(&m_csXEnroll);
  2675. return(hr);
  2676. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2677. }
  2678. HRESULT STDMETHODCALLTYPE CCEnroll::get_MyStoreTypeWStr(
  2679. /* [out] */ LPWSTR __RPC_FAR *szwType) {
  2680. HRESULT hr = S_OK;
  2681. EnterCriticalSection(&m_csXEnroll);
  2682. if( (*szwType = WideFromMB(m_MyStore.szType)) == NULL )
  2683. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2684. LeaveCriticalSection(&m_csXEnroll);
  2685. return(hr);
  2686. }
  2687. //--------------------------------------------------------------------------------
  2688. //
  2689. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2690. //
  2691. //--------------------------------------------------------------------------------
  2692. HRESULT STDMETHODCALLTYPE CCEnroll::put_MyStoreTypeWStr(
  2693. /* [in] */ LPWSTR szwType) {
  2694. HRESULT hr = S_OK;
  2695. EnterCriticalSection(&m_csXEnroll);
  2696. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2697. goto AccessDeniedError;
  2698. if(m_MyStore.hStore != NULL)
  2699. hr = E_ACCESSDENIED;
  2700. else {
  2701. if(m_MyStore.szType != szSystemStore)
  2702. MyCoTaskMemFree(m_MyStore.szType);
  2703. if( (m_MyStore.szType = MBFromWide(szwType)) == NULL )
  2704. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2705. }
  2706. ErrorReturn:
  2707. LeaveCriticalSection(&m_csXEnroll);
  2708. return(hr);
  2709. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2710. }
  2711. //
  2712. // CA STORE
  2713. //
  2714. HCERTSTORE STDMETHODCALLTYPE CCEnroll::getCAStore( void)
  2715. {
  2716. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2717. return NULL;
  2718. }
  2719. HRESULT STDMETHODCALLTYPE CCEnroll::get_CAStoreName(
  2720. /* [retval][out] */ BSTR __RPC_FAR *pbstrName) {
  2721. HRESULT hr = S_OK;
  2722. EnterCriticalSection(&m_csXEnroll);
  2723. if(m_CAStore.wszName == NULL)
  2724. return(ERROR_UNKNOWN_PROPERTY);
  2725. if( (*pbstrName = SysAllocString(m_CAStore.wszName)) == NULL )
  2726. hr = E_OUTOFMEMORY;
  2727. LeaveCriticalSection(&m_csXEnroll);
  2728. return(hr);
  2729. }
  2730. HRESULT STDMETHODCALLTYPE CCEnroll::put_CAStoreName(
  2731. /* [in] */ BSTR bstrName) {
  2732. return(put_CAStoreNameWStr(bstrName));
  2733. }
  2734. HRESULT STDMETHODCALLTYPE CCEnroll::get_CAStoreType(
  2735. /* [retval][out] */ BSTR __RPC_FAR *pbstrType) {
  2736. HRESULT hr = S_OK;
  2737. EnterCriticalSection(&m_csXEnroll);
  2738. if( (*pbstrType = BSTRFromMB(m_CAStore.szType)) == NULL )
  2739. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2740. LeaveCriticalSection(&m_csXEnroll);
  2741. return(hr);
  2742. }
  2743. HRESULT STDMETHODCALLTYPE CCEnroll::put_CAStoreType(
  2744. /* [in] */ BSTR bstrType) {
  2745. return(put_CAStoreTypeWStr(bstrType));
  2746. }
  2747. HRESULT STDMETHODCALLTYPE CCEnroll::get_CAStoreFlags(
  2748. /* [retval][out] */ LONG __RPC_FAR *pdwFlags) {
  2749. EnterCriticalSection(&m_csXEnroll);
  2750. *pdwFlags = m_CAStore.dwFlags;
  2751. LeaveCriticalSection(&m_csXEnroll);
  2752. return(S_OK);
  2753. }
  2754. //--------------------------------------------------------------------------------
  2755. //
  2756. // This method is only safe for scripting if it's parameter is safe.
  2757. // See VerifyStoreFlagsSafeForScripting().
  2758. //
  2759. //--------------------------------------------------------------------------------
  2760. HRESULT STDMETHODCALLTYPE CCEnroll::put_CAStoreFlags(
  2761. /* [in] */ LONG dwFlags) {
  2762. HRESULT hr = S_OK;
  2763. EnterCriticalSection(&m_csXEnroll);
  2764. // If we're marked as safe for scripting, see if the flags passed in are safe:
  2765. if (0 != m_dwEnabledSafteyOptions && !VerifyStoreFlagsSafeForScripting(dwFlags))
  2766. goto AccessDeniedError;
  2767. if(m_CAStore.hStore != NULL)
  2768. hr = E_ACCESSDENIED;
  2769. else {
  2770. m_fCAStoreOpenFlagsModified = TRUE;
  2771. m_CAStore.dwFlags = dwFlags;
  2772. }
  2773. ErrorReturn:
  2774. LeaveCriticalSection(&m_csXEnroll);
  2775. return(hr);
  2776. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2777. }
  2778. HRESULT STDMETHODCALLTYPE CCEnroll::get_CAStoreNameWStr(
  2779. /* [out] */ LPWSTR __RPC_FAR *szwName) {
  2780. HRESULT hr = S_OK;
  2781. EnterCriticalSection(&m_csXEnroll);
  2782. if(m_CAStore.wszName == NULL)
  2783. return(ERROR_UNKNOWN_PROPERTY);
  2784. if( (*szwName = CopyWideString(m_CAStore.wszName)) == NULL )
  2785. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2786. LeaveCriticalSection(&m_csXEnroll);
  2787. return(hr);
  2788. }
  2789. //--------------------------------------------------------------------------------
  2790. //
  2791. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2792. //
  2793. //--------------------------------------------------------------------------------
  2794. HRESULT STDMETHODCALLTYPE CCEnroll::put_CAStoreNameWStr(
  2795. /* [in] */ LPWSTR szwName) {
  2796. HRESULT hr = S_OK;
  2797. EnterCriticalSection(&m_csXEnroll);
  2798. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2799. goto AccessDeniedError;
  2800. if(m_CAStore.hStore != NULL)
  2801. hr = E_ACCESSDENIED;
  2802. else {
  2803. if(m_CAStore.wszName != wszCA)
  2804. MyCoTaskMemFree(m_CAStore.wszName);
  2805. if( (m_CAStore.wszName = CopyWideString(szwName)) == NULL )
  2806. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2807. }
  2808. ErrorReturn:
  2809. LeaveCriticalSection(&m_csXEnroll);
  2810. return(hr);
  2811. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2812. }
  2813. HRESULT STDMETHODCALLTYPE CCEnroll::get_CAStoreTypeWStr(
  2814. /* [out] */ LPWSTR __RPC_FAR *szwType) {
  2815. HRESULT hr = S_OK;
  2816. EnterCriticalSection(&m_csXEnroll);
  2817. if( (*szwType = WideFromMB(m_CAStore.szType)) == NULL )
  2818. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2819. LeaveCriticalSection(&m_csXEnroll);
  2820. return(hr);
  2821. }
  2822. //--------------------------------------------------------------------------------
  2823. //
  2824. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2825. //
  2826. //--------------------------------------------------------------------------------
  2827. HRESULT STDMETHODCALLTYPE CCEnroll::put_CAStoreTypeWStr(
  2828. /* [in] */ LPWSTR szwType) {
  2829. HRESULT hr = S_OK;
  2830. EnterCriticalSection(&m_csXEnroll);
  2831. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2832. goto AccessDeniedError;
  2833. if(m_CAStore.hStore != NULL)
  2834. hr = E_ACCESSDENIED;
  2835. else {
  2836. if(m_CAStore.szType != szSystemStore)
  2837. MyCoTaskMemFree(m_CAStore.szType);
  2838. if( (m_CAStore.szType = MBFromWide(szwType)) == NULL )
  2839. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2840. }
  2841. ErrorReturn:
  2842. LeaveCriticalSection(&m_csXEnroll);
  2843. return(hr);
  2844. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2845. }
  2846. //
  2847. // ROOT STORE
  2848. //
  2849. HCERTSTORE STDMETHODCALLTYPE CCEnroll::getROOTHStore( void)
  2850. {
  2851. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2852. return NULL;
  2853. }
  2854. HRESULT STDMETHODCALLTYPE CCEnroll::get_RootStoreName(
  2855. /* [retval][out] */ BSTR __RPC_FAR *pbstrName) {
  2856. HRESULT hr = S_OK;
  2857. EnterCriticalSection(&m_csXEnroll);
  2858. if(m_RootStore.wszName == NULL)
  2859. return(ERROR_UNKNOWN_PROPERTY);
  2860. if( (*pbstrName = SysAllocString(m_RootStore.wszName)) == NULL )
  2861. hr = E_OUTOFMEMORY;
  2862. LeaveCriticalSection(&m_csXEnroll);
  2863. return(hr);
  2864. }
  2865. HRESULT STDMETHODCALLTYPE CCEnroll::put_RootStoreName(
  2866. /* [in] */ BSTR bstrName) {
  2867. return(put_RootStoreNameWStr(bstrName));
  2868. }
  2869. HRESULT STDMETHODCALLTYPE CCEnroll::get_RootStoreType(
  2870. /* [retval][out] */ BSTR __RPC_FAR *pbstrType) {
  2871. HRESULT hr = S_OK;
  2872. EnterCriticalSection(&m_csXEnroll);
  2873. if( (*pbstrType = BSTRFromMB(m_RootStore.szType)) == NULL )
  2874. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2875. LeaveCriticalSection(&m_csXEnroll);
  2876. return(hr);
  2877. }
  2878. HRESULT STDMETHODCALLTYPE CCEnroll::put_RootStoreType(
  2879. /* [in] */ BSTR bstrType) {
  2880. return(put_RootStoreTypeWStr(bstrType));
  2881. }
  2882. HRESULT STDMETHODCALLTYPE CCEnroll::get_RootStoreFlags(
  2883. /* [retval][out] */ LONG __RPC_FAR *pdwFlags) {
  2884. EnterCriticalSection(&m_csXEnroll);
  2885. *pdwFlags = m_RootStore.dwFlags;
  2886. LeaveCriticalSection(&m_csXEnroll);
  2887. return(S_OK);
  2888. }
  2889. //--------------------------------------------------------------------------------
  2890. //
  2891. // This method is only safe for scripting if it's parameter is safe.
  2892. // See VerifyStoreFlagsSafeForScripting().
  2893. //
  2894. //--------------------------------------------------------------------------------
  2895. HRESULT STDMETHODCALLTYPE CCEnroll::put_RootStoreFlags(
  2896. /* [in] */ LONG dwFlags) {
  2897. HRESULT hr = S_OK;
  2898. EnterCriticalSection(&m_csXEnroll);
  2899. // If we're marked as safe for scripting, see if the flags passed in are safe:
  2900. if (0 != m_dwEnabledSafteyOptions) {
  2901. // see if the caller passed safe flags:
  2902. if (!VerifyStoreFlagsSafeForScripting(dwFlags))
  2903. goto AccessDeniedError;
  2904. // extra check for root store: don't allow CERT_SYSTEM_STORE_LOCAL_MACHINE for the root store.
  2905. // if they want to install a machine cert through script, it'll go to the CA store:
  2906. // NOTE: we don't modify the store name if m_RootStore.hStore is NULL, as we'll return E_ACCESSDENIED
  2907. // anyway, and we shouldn't modify this on error.
  2908. if (NULL == m_RootStore.hStore) {
  2909. if (dwFlags & CERT_SYSTEM_STORE_LOCAL_MACHINE) {
  2910. m_RootStore.wszName = wszCA;
  2911. } else {
  2912. m_RootStore.wszName = wszROOT;
  2913. }
  2914. }
  2915. }
  2916. if(m_RootStore.hStore != NULL)
  2917. hr = E_ACCESSDENIED;
  2918. else {
  2919. m_fRootStoreOpenFlagsModified = TRUE;
  2920. m_RootStore.dwFlags = dwFlags;
  2921. }
  2922. ErrorReturn:
  2923. LeaveCriticalSection(&m_csXEnroll);
  2924. return(hr);
  2925. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2926. }
  2927. HRESULT STDMETHODCALLTYPE CCEnroll::get_RootStoreNameWStr(
  2928. /* [out] */ LPWSTR __RPC_FAR *szwName) {
  2929. HRESULT hr = S_OK;
  2930. EnterCriticalSection(&m_csXEnroll);
  2931. if(m_RootStore.wszName == NULL)
  2932. return(ERROR_UNKNOWN_PROPERTY);
  2933. if( (*szwName = CopyWideString(m_RootStore.wszName)) == NULL )
  2934. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2935. LeaveCriticalSection(&m_csXEnroll);
  2936. return(hr);
  2937. }
  2938. //--------------------------------------------------------------------------------
  2939. //
  2940. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2941. //
  2942. //--------------------------------------------------------------------------------
  2943. HRESULT STDMETHODCALLTYPE CCEnroll::put_RootStoreNameWStr(
  2944. /* [in] */ LPWSTR szwName) {
  2945. HRESULT hr = S_OK;
  2946. EnterCriticalSection(&m_csXEnroll);
  2947. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2948. goto AccessDeniedError;
  2949. if(m_RootStore.hStore != NULL)
  2950. hr = E_ACCESSDENIED;
  2951. else {
  2952. if(m_RootStore.wszName != wszROOT && m_RootStore.wszName != wszCA)
  2953. MyCoTaskMemFree(m_RootStore.wszName);
  2954. if( (m_RootStore.wszName = CopyWideString(szwName)) == NULL )
  2955. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2956. }
  2957. ErrorReturn:
  2958. LeaveCriticalSection(&m_csXEnroll);
  2959. return(hr);
  2960. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2961. }
  2962. HRESULT STDMETHODCALLTYPE CCEnroll::get_RootStoreTypeWStr(
  2963. /* [out] */ LPWSTR __RPC_FAR *szwType) {
  2964. HRESULT hr = S_OK;
  2965. EnterCriticalSection(&m_csXEnroll);
  2966. if( (*szwType = WideFromMB(m_RootStore.szType)) == NULL )
  2967. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2968. LeaveCriticalSection(&m_csXEnroll);
  2969. return(hr);
  2970. }
  2971. //--------------------------------------------------------------------------------
  2972. //
  2973. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  2974. //
  2975. //--------------------------------------------------------------------------------
  2976. HRESULT STDMETHODCALLTYPE CCEnroll::put_RootStoreTypeWStr(
  2977. /* [in] */ LPWSTR szwType) {
  2978. HRESULT hr = S_OK;
  2979. EnterCriticalSection(&m_csXEnroll);
  2980. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  2981. goto AccessDeniedError;
  2982. if(m_RootStore.hStore != NULL)
  2983. hr = E_ACCESSDENIED;
  2984. else {
  2985. if(m_RootStore.szType != szSystemStore)
  2986. MyCoTaskMemFree(m_RootStore.szType);
  2987. if( (m_RootStore.szType = MBFromWide(szwType)) == NULL )
  2988. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  2989. }
  2990. ErrorReturn:
  2991. LeaveCriticalSection(&m_csXEnroll);
  2992. return(hr);
  2993. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  2994. }
  2995. //
  2996. // REQUEST STORE
  2997. //
  2998. HRESULT STDMETHODCALLTYPE CCEnroll::get_RequestStoreName(
  2999. /* [retval][out] */ BSTR __RPC_FAR *pbstrName) {
  3000. HRESULT hr = S_OK;
  3001. EnterCriticalSection(&m_csXEnroll);
  3002. if(m_RequestStore.wszName == NULL)
  3003. return(ERROR_UNKNOWN_PROPERTY);
  3004. if( (*pbstrName = SysAllocString(m_RequestStore.wszName)) == NULL )
  3005. hr = E_OUTOFMEMORY;
  3006. LeaveCriticalSection(&m_csXEnroll);
  3007. return(hr);
  3008. }
  3009. HRESULT STDMETHODCALLTYPE CCEnroll::put_RequestStoreName(
  3010. /* [in] */ BSTR bstrName) {
  3011. return(put_RequestStoreNameWStr(bstrName));
  3012. }
  3013. HRESULT STDMETHODCALLTYPE CCEnroll::get_RequestStoreType(
  3014. /* [retval][out] */ BSTR __RPC_FAR *pbstrType) {
  3015. HRESULT hr = S_OK;
  3016. EnterCriticalSection(&m_csXEnroll);
  3017. if( (*pbstrType = BSTRFromMB(m_RequestStore.szType)) == NULL )
  3018. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3019. LeaveCriticalSection(&m_csXEnroll);
  3020. return(hr);
  3021. }
  3022. HRESULT STDMETHODCALLTYPE CCEnroll::put_RequestStoreType(
  3023. /* [in] */ BSTR bstrType) {
  3024. return(put_RequestStoreTypeWStr(bstrType));
  3025. }
  3026. HRESULT STDMETHODCALLTYPE CCEnroll::get_RequestStoreFlags(
  3027. /* [retval][out] */ LONG __RPC_FAR *pdwFlags) {
  3028. EnterCriticalSection(&m_csXEnroll);
  3029. *pdwFlags = m_RequestStore.dwFlags;
  3030. LeaveCriticalSection(&m_csXEnroll);
  3031. return(S_OK);
  3032. }
  3033. //--------------------------------------------------------------------------------
  3034. //
  3035. // This method is only safe for scripting if it's parameter is safe.
  3036. // See VerifyStoreFlagsSafeForScripting().
  3037. //
  3038. //--------------------------------------------------------------------------------
  3039. HRESULT STDMETHODCALLTYPE CCEnroll::put_RequestStoreFlags(
  3040. /* [in] */ LONG dwFlags) {
  3041. HRESULT hr = S_OK;
  3042. EnterCriticalSection(&m_csXEnroll);
  3043. // If we're marked as safe for scripting, see if the flags passed in are safe:
  3044. if (0 != m_dwEnabledSafteyOptions && !VerifyStoreFlagsSafeForScripting(dwFlags))
  3045. goto AccessDeniedError;
  3046. if(m_RequestStore.hStore != NULL)
  3047. hr = E_ACCESSDENIED;
  3048. else {
  3049. // set the request store flags
  3050. m_RequestStore.dwFlags = dwFlags;
  3051. m_fRequestStoreOpenFlagsModified = TRUE;
  3052. // track the My store location to the request store, only if the my store has not been modified
  3053. // do NOT set the modify bit for the my store, this is a default
  3054. if(!m_fMyStoreOpenFlagsModified) {
  3055. m_MyStore.dwFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
  3056. m_MyStore.dwFlags |= (dwFlags & CERT_SYSTEM_STORE_LOCATION_MASK);
  3057. m_keyProvInfo.dwFlags |= KeyLocationFromStoreLocation(m_MyStore.dwFlags);
  3058. }
  3059. }
  3060. ErrorReturn:
  3061. LeaveCriticalSection(&m_csXEnroll);
  3062. return(hr);
  3063. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  3064. }
  3065. HRESULT STDMETHODCALLTYPE CCEnroll::get_RequestStoreNameWStr(
  3066. /* [out] */ LPWSTR __RPC_FAR *szwName) {
  3067. HRESULT hr = S_OK;
  3068. EnterCriticalSection(&m_csXEnroll);
  3069. if(m_RequestStore.wszName == NULL)
  3070. return(ERROR_UNKNOWN_PROPERTY);
  3071. if( (*szwName = CopyWideString(m_RequestStore.wszName)) == NULL )
  3072. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3073. LeaveCriticalSection(&m_csXEnroll);
  3074. return(hr);
  3075. }
  3076. //--------------------------------------------------------------------------------
  3077. //
  3078. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  3079. //
  3080. //--------------------------------------------------------------------------------
  3081. HRESULT STDMETHODCALLTYPE CCEnroll::put_RequestStoreNameWStr(
  3082. /* [in] */ LPWSTR szwType) {
  3083. HRESULT hr = S_OK;
  3084. EnterCriticalSection(&m_csXEnroll);
  3085. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  3086. goto AccessDeniedError;
  3087. if(m_RequestStore.hStore != NULL)
  3088. hr = E_ACCESSDENIED;
  3089. else {
  3090. if(m_RequestStore.wszName != wszREQUEST)
  3091. MyCoTaskMemFree(m_RequestStore.wszName);
  3092. if( (m_RequestStore.wszName = CopyWideString(szwType)) == NULL )
  3093. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3094. }
  3095. ErrorReturn:
  3096. LeaveCriticalSection(&m_csXEnroll);
  3097. return(hr);
  3098. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  3099. }
  3100. HRESULT STDMETHODCALLTYPE CCEnroll::get_RequestStoreTypeWStr(
  3101. /* [out] */ LPWSTR __RPC_FAR *szwType) {
  3102. HRESULT hr = S_OK;
  3103. EnterCriticalSection(&m_csXEnroll);
  3104. if( (*szwType = WideFromMB(m_RequestStore.szType)) == NULL )
  3105. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3106. LeaveCriticalSection(&m_csXEnroll);
  3107. return(hr);
  3108. }
  3109. //--------------------------------------------------------------------------------
  3110. //
  3111. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  3112. //
  3113. //--------------------------------------------------------------------------------
  3114. HRESULT STDMETHODCALLTYPE CCEnroll::put_RequestStoreTypeWStr(
  3115. /* [in] */ LPWSTR szwType) {
  3116. HRESULT hr = S_OK;
  3117. EnterCriticalSection(&m_csXEnroll);
  3118. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  3119. goto AccessDeniedError;
  3120. if(m_RequestStore.hStore != NULL)
  3121. hr = E_ACCESSDENIED;
  3122. else {
  3123. if(m_RequestStore.szType != szSystemStore)
  3124. MyCoTaskMemFree(m_RequestStore.szType);
  3125. if( (m_RequestStore.szType = MBFromWide(szwType)) == NULL )
  3126. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3127. }
  3128. ErrorReturn:
  3129. LeaveCriticalSection(&m_csXEnroll);
  3130. return(hr);
  3131. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  3132. }
  3133. //
  3134. // Provider Stuff
  3135. //
  3136. HRESULT STDMETHODCALLTYPE CCEnroll::get_ContainerName(
  3137. /* [retval][out] */ BSTR __RPC_FAR *pbstrContainer) {
  3138. HRESULT hr = S_OK;
  3139. EnterCriticalSection(&m_csXEnroll);
  3140. if( (*pbstrContainer = SysAllocString(m_keyProvInfo.pwszContainerName)) == NULL )
  3141. hr = E_OUTOFMEMORY;
  3142. LeaveCriticalSection(&m_csXEnroll);
  3143. return(hr);
  3144. }
  3145. HRESULT STDMETHODCALLTYPE CCEnroll::put_ContainerName(
  3146. /* [in] */ BSTR bstrContainer) {
  3147. return(put_ContainerNameWStr(bstrContainer));
  3148. }
  3149. HRESULT STDMETHODCALLTYPE CCEnroll::get_ProviderName(
  3150. /* [retval][out] */ BSTR __RPC_FAR *pbstrProvider) {
  3151. HRESULT hr = S_OK;
  3152. EnterCriticalSection(&m_csXEnroll);
  3153. if( (*pbstrProvider = SysAllocString(m_keyProvInfo.pwszProvName)) == NULL )
  3154. hr = E_OUTOFMEMORY;
  3155. LeaveCriticalSection(&m_csXEnroll);
  3156. return(hr);
  3157. }
  3158. HRESULT STDMETHODCALLTYPE CCEnroll::put_ProviderName(
  3159. /* [in] */ BSTR bstrProvider) {
  3160. return(put_ProviderNameWStr(bstrProvider));
  3161. }
  3162. HRESULT STDMETHODCALLTYPE CCEnroll::get_ProviderType(
  3163. /* [retval][out] */ LONG __RPC_FAR *pdwType) {
  3164. EnterCriticalSection(&m_csXEnroll);
  3165. *pdwType = m_keyProvInfo.dwProvType;
  3166. LeaveCriticalSection(&m_csXEnroll);
  3167. return(S_OK);
  3168. }
  3169. HRESULT STDMETHODCALLTYPE CCEnroll::put_ProviderType(
  3170. /* [in] */ LONG dwType) {
  3171. HRESULT hr = S_OK;
  3172. EnterCriticalSection(&m_csXEnroll);
  3173. if(m_hProv != NULL)
  3174. hr = E_ACCESSDENIED;
  3175. else
  3176. m_keyProvInfo.dwProvType = dwType;
  3177. LeaveCriticalSection(&m_csXEnroll);
  3178. return(hr);
  3179. }
  3180. HRESULT STDMETHODCALLTYPE CCEnroll::get_KeySpec(
  3181. /* [retval][out] */ LONG __RPC_FAR *pdw) {
  3182. EnterCriticalSection(&m_csXEnroll);
  3183. *pdw = m_keyProvInfo.dwKeySpec;
  3184. LeaveCriticalSection(&m_csXEnroll);
  3185. return(S_OK);
  3186. }
  3187. HRESULT STDMETHODCALLTYPE CCEnroll::put_KeySpec(
  3188. /* [in] */ LONG dwKeySpec) {
  3189. HRESULT hr;
  3190. EnterCriticalSection(&m_csXEnroll);
  3191. if(m_hProv != NULL)
  3192. {
  3193. hr = E_ACCESSDENIED;
  3194. goto NullProvError;
  3195. }
  3196. if (m_fSMIMESetByClient)
  3197. {
  3198. //SMIME is set by the client
  3199. if (m_fEnableSMIMECapabilities && AT_SIGNATURE == dwKeySpec)
  3200. {
  3201. //try to set signature key spec also SMIME
  3202. hr = XENROLL_E_KEYSPEC_SMIME_MISMATCH;
  3203. goto MismatchError;
  3204. }
  3205. }
  3206. else
  3207. {
  3208. //currently smime is not set by user
  3209. //turn on SMIME for according to key spec
  3210. m_fEnableSMIMECapabilities = (dwKeySpec == AT_KEYEXCHANGE);
  3211. }
  3212. m_keyProvInfo.dwKeySpec = dwKeySpec;
  3213. m_fKeySpecSetByClient = TRUE;
  3214. hr = S_OK;
  3215. ErrorReturn:
  3216. LeaveCriticalSection(&m_csXEnroll);
  3217. return(hr);
  3218. TRACE_ERROR(NullProvError)
  3219. TRACE_ERROR(MismatchError)
  3220. }
  3221. HRESULT STDMETHODCALLTYPE CCEnroll::get_ClientId(
  3222. /* [retval][out] */ LONG __RPC_FAR *pdw) {
  3223. EnterCriticalSection(&m_csXEnroll);
  3224. *pdw = m_lClientId;
  3225. LeaveCriticalSection(&m_csXEnroll);
  3226. return(S_OK);
  3227. }
  3228. HRESULT STDMETHODCALLTYPE CCEnroll::put_ClientId(
  3229. /* [in] */ LONG dw) {
  3230. HRESULT hr = S_OK;
  3231. EnterCriticalSection(&m_csXEnroll);
  3232. m_lClientId = dw;
  3233. LeaveCriticalSection(&m_csXEnroll);
  3234. return(hr);
  3235. }
  3236. HRESULT STDMETHODCALLTYPE CCEnroll::get_IncludeSubjectKeyID(
  3237. /* [retval][out] */ BOOL __RPC_FAR *pfInclude) {
  3238. EnterCriticalSection(&m_csXEnroll);
  3239. *pfInclude = m_fIncludeSubjectKeyID;
  3240. LeaveCriticalSection(&m_csXEnroll);
  3241. return(S_OK);
  3242. }
  3243. HRESULT STDMETHODCALLTYPE CCEnroll::put_IncludeSubjectKeyID(
  3244. /* [in] */ BOOL fInclude) {
  3245. HRESULT hr = S_OK;
  3246. EnterCriticalSection(&m_csXEnroll);
  3247. m_fIncludeSubjectKeyID = fInclude;
  3248. LeaveCriticalSection(&m_csXEnroll);
  3249. return(hr);
  3250. }
  3251. HRESULT STDMETHODCALLTYPE CCEnroll::get_ProviderFlags(
  3252. /* [retval][out] */ LONG __RPC_FAR *pdwFlags) {
  3253. EnterCriticalSection(&m_csXEnroll);
  3254. *pdwFlags = m_keyProvInfo.dwFlags;
  3255. LeaveCriticalSection(&m_csXEnroll);
  3256. return(S_OK);
  3257. }
  3258. //--------------------------------------------------------------------------------
  3259. //
  3260. // This method is only safe for scripting if it's parameter is safe.
  3261. // See VerifyProviderFlagsSafeForScripting().
  3262. //
  3263. //--------------------------------------------------------------------------------
  3264. HRESULT STDMETHODCALLTYPE CCEnroll::put_ProviderFlags(
  3265. /* [in] */ LONG dwFlags) {
  3266. HRESULT hr = S_OK;
  3267. EnterCriticalSection(&m_csXEnroll);
  3268. // If we're marked as safe for scripting, see if the flags passed in are safe:
  3269. if (0 != m_dwEnabledSafteyOptions && !VerifyProviderFlagsSafeForScripting(dwFlags))
  3270. goto AccessDeniedError;
  3271. if(m_hProv != NULL)
  3272. hr = E_ACCESSDENIED;
  3273. else
  3274. m_keyProvInfo.dwFlags = dwFlags;
  3275. ErrorReturn:
  3276. LeaveCriticalSection(&m_csXEnroll);
  3277. return(hr);
  3278. SET_HRESULT(AccessDeniedError, E_ACCESSDENIED);
  3279. }
  3280. HRESULT STDMETHODCALLTYPE CCEnroll::get_ContainerNameWStr(
  3281. /* [out] */ LPWSTR __RPC_FAR *szwContainer) {
  3282. HRESULT hr = S_OK;
  3283. EnterCriticalSection(&m_csXEnroll);
  3284. if( (*szwContainer = CopyWideString(m_keyProvInfo.pwszContainerName)) == NULL )
  3285. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3286. LeaveCriticalSection(&m_csXEnroll);
  3287. return(hr);
  3288. }
  3289. HRESULT STDMETHODCALLTYPE CCEnroll::put_ContainerNameWStr(
  3290. /* [in] */ LPWSTR szwContainer) {
  3291. HRESULT hr = S_OK;
  3292. if(szwContainer == NULL)
  3293. return(MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  3294. EnterCriticalSection(&m_csXEnroll);
  3295. if(m_hProv != NULL)
  3296. hr = E_ACCESSDENIED;
  3297. else {
  3298. if( m_keyProvInfo.pwszContainerName != wszEmpty)
  3299. MyCoTaskMemFree(m_keyProvInfo.pwszContainerName);
  3300. if( (m_keyProvInfo.pwszContainerName = CopyWideString(szwContainer)) == NULL )
  3301. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3302. }
  3303. LeaveCriticalSection(&m_csXEnroll);
  3304. return(hr);
  3305. }
  3306. HRESULT STDMETHODCALLTYPE CCEnroll::get_ProviderNameWStr(
  3307. /* [out] */ LPWSTR __RPC_FAR *szwProvider) {
  3308. HRESULT hr = S_OK;
  3309. EnterCriticalSection(&m_csXEnroll);
  3310. if( (*szwProvider = CopyWideString(m_keyProvInfo.pwszProvName)) == NULL )
  3311. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3312. LeaveCriticalSection(&m_csXEnroll);
  3313. return(hr);
  3314. }
  3315. HRESULT STDMETHODCALLTYPE CCEnroll::put_ProviderNameWStr(
  3316. /* [in] */ LPWSTR szwProvider) {
  3317. HRESULT hr = S_OK;
  3318. if(szwProvider == NULL)
  3319. return(MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  3320. EnterCriticalSection(&m_csXEnroll);
  3321. if(m_hProv != NULL)
  3322. hr = E_ACCESSDENIED;
  3323. else {
  3324. if (0 != wcscmp(m_keyProvInfo.pwszProvName, szwProvider))
  3325. {
  3326. if( m_keyProvInfo.pwszProvName != wszEmpty )
  3327. MyCoTaskMemFree(m_keyProvInfo.pwszProvName);
  3328. if( (m_keyProvInfo.pwszProvName = CopyWideString(szwProvider)) == NULL )
  3329. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3330. //one last thing, free/null cached prov handle
  3331. if (NULL != m_hVerifyProv)
  3332. {
  3333. CryptReleaseContext(m_hVerifyProv, 0);
  3334. m_hVerifyProv = NULL;
  3335. }
  3336. // csp is changed, reset key size cache
  3337. m_dwXhgKeyLenMax = 0;
  3338. m_dwXhgKeyLenMin = 0;
  3339. m_dwXhgKeyLenDef = 0;
  3340. m_dwXhgKeyLenInc = 0;
  3341. m_dwSigKeyLenMax = 0;
  3342. m_dwSigKeyLenMin = 0;
  3343. m_dwSigKeyLenDef = 0;
  3344. m_dwSigKeyLenInc = 0;
  3345. }
  3346. }
  3347. LeaveCriticalSection(&m_csXEnroll);
  3348. return(hr);
  3349. }
  3350. //
  3351. // Other Stuff
  3352. //
  3353. HRESULT STDMETHODCALLTYPE CCEnroll::get_UseExistingKeySet(
  3354. /* [retval][out] */ BOOL __RPC_FAR *fUseExistingKeys) {
  3355. EnterCriticalSection(&m_csXEnroll);
  3356. *fUseExistingKeys = m_fUseExistingKey;
  3357. LeaveCriticalSection(&m_csXEnroll);
  3358. return(S_OK);
  3359. }
  3360. HRESULT STDMETHODCALLTYPE CCEnroll::put_UseExistingKeySet(
  3361. /* [in] */ BOOL fUseExistingKeys) {
  3362. EnterCriticalSection(&m_csXEnroll);
  3363. m_fUseExistingKey = fUseExistingKeys;
  3364. LeaveCriticalSection(&m_csXEnroll);
  3365. return(S_OK);
  3366. }
  3367. HRESULT STDMETHODCALLTYPE CCEnroll::get_GenKeyFlags(
  3368. /* [retval][out] */ LONG __RPC_FAR * pdwFlags) {
  3369. EnterCriticalSection(&m_csXEnroll);
  3370. *pdwFlags = m_dwGenKeyFlags;
  3371. LeaveCriticalSection(&m_csXEnroll);
  3372. return(S_OK);
  3373. }
  3374. HRESULT STDMETHODCALLTYPE CCEnroll::put_GenKeyFlags(
  3375. /* [in] */ LONG dwFlags) {
  3376. EnterCriticalSection(&m_csXEnroll);
  3377. m_dwGenKeyFlags = dwFlags;
  3378. LeaveCriticalSection(&m_csXEnroll);
  3379. return(S_OK);
  3380. }
  3381. HRESULT STDMETHODCALLTYPE CCEnroll::get_DeleteRequestCert(
  3382. /* [retval][out] */ BOOL __RPC_FAR *fBool) {
  3383. EnterCriticalSection(&m_csXEnroll);
  3384. *fBool = m_fDeleteRequestCert;
  3385. LeaveCriticalSection(&m_csXEnroll);
  3386. return(S_OK);
  3387. }
  3388. HRESULT STDMETHODCALLTYPE CCEnroll::put_DeleteRequestCert(
  3389. /* [in] */ BOOL fBool) {
  3390. EnterCriticalSection(&m_csXEnroll);
  3391. m_fDeleteRequestCert = fBool;
  3392. LeaveCriticalSection(&m_csXEnroll);
  3393. return(S_OK);
  3394. }
  3395. HRESULT STDMETHODCALLTYPE CCEnroll::get_WriteCertToCSP(
  3396. /* [retval][out] */ BOOL __RPC_FAR *fBool) {
  3397. EnterCriticalSection(&m_csXEnroll);
  3398. *fBool = m_fWriteCertToCSP;
  3399. LeaveCriticalSection(&m_csXEnroll);
  3400. return(S_OK);
  3401. }
  3402. HRESULT STDMETHODCALLTYPE CCEnroll::put_WriteCertToCSP(
  3403. /* [in] */ BOOL fBool) {
  3404. EnterCriticalSection(&m_csXEnroll);
  3405. m_fWriteCertToCSP = fBool;
  3406. m_fWriteCertToCSPModified = TRUE;
  3407. LeaveCriticalSection(&m_csXEnroll);
  3408. return(S_OK);
  3409. }
  3410. HRESULT STDMETHODCALLTYPE CCEnroll::get_WriteCertToUserDS(
  3411. /* [retval][out] */ BOOL __RPC_FAR *fBool) {
  3412. EnterCriticalSection(&m_csXEnroll);
  3413. *fBool = m_fWriteCertToUserDS;
  3414. LeaveCriticalSection(&m_csXEnroll);
  3415. return(S_OK);
  3416. }
  3417. //--------------------------------------------------------------------------------
  3418. //
  3419. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  3420. //
  3421. //--------------------------------------------------------------------------------
  3422. HRESULT STDMETHODCALLTYPE CCEnroll::put_WriteCertToUserDS(
  3423. /* [in] */ BOOL fBool) {
  3424. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  3425. return E_ACCESSDENIED;
  3426. EnterCriticalSection(&m_csXEnroll);
  3427. m_fWriteCertToUserDS = fBool;
  3428. m_fWriteCertToUserDSModified = TRUE;
  3429. LeaveCriticalSection(&m_csXEnroll);
  3430. return(S_OK);
  3431. }
  3432. HRESULT STDMETHODCALLTYPE CCEnroll::get_EnableT61DNEncoding(
  3433. /* [retval][out] */ BOOL __RPC_FAR *fBool) {
  3434. EnterCriticalSection(&m_csXEnroll);
  3435. *fBool = (m_dwT61DNEncoding == CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG);
  3436. LeaveCriticalSection(&m_csXEnroll);
  3437. return(S_OK);
  3438. }
  3439. HRESULT STDMETHODCALLTYPE CCEnroll::put_EnableT61DNEncoding(
  3440. /* [in] */ BOOL fBool) {
  3441. EnterCriticalSection(&m_csXEnroll);
  3442. if(fBool)
  3443. m_dwT61DNEncoding = CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG;
  3444. else
  3445. m_dwT61DNEncoding = 0;
  3446. LeaveCriticalSection(&m_csXEnroll);
  3447. return(S_OK);
  3448. }
  3449. HRESULT STDMETHODCALLTYPE CCEnroll::get_SPCFileName(
  3450. /* [retval][out] */ BSTR __RPC_FAR *pbstr) {
  3451. HRESULT hr = S_OK;
  3452. EnterCriticalSection(&m_csXEnroll);
  3453. if( (*pbstr = SysAllocString(m_wszSPCFileName)) == NULL )
  3454. hr = E_OUTOFMEMORY;
  3455. LeaveCriticalSection(&m_csXEnroll);
  3456. return(hr);
  3457. }
  3458. HRESULT STDMETHODCALLTYPE CCEnroll::put_SPCFileName(
  3459. /* [in] */ BSTR bstr) {
  3460. return(put_SPCFileNameWStr(bstr));
  3461. }
  3462. HRESULT STDMETHODCALLTYPE CCEnroll::get_PVKFileName(
  3463. /* [retval][out] */ BSTR __RPC_FAR *pbstr) {
  3464. HRESULT hr = S_OK;
  3465. EnterCriticalSection(&m_csXEnroll);
  3466. if( (*pbstr = SysAllocString(m_wszPVKFileName)) == NULL )
  3467. hr = E_OUTOFMEMORY;
  3468. LeaveCriticalSection(&m_csXEnroll);
  3469. return(hr);
  3470. }
  3471. HRESULT STDMETHODCALLTYPE CCEnroll::put_PVKFileName(
  3472. /* [in] */ BSTR bstr) {
  3473. return(put_PVKFileNameWStr(bstr));
  3474. }
  3475. HRESULT STDMETHODCALLTYPE CCEnroll::get_HashAlgorithm(
  3476. /* [retval][out] */ BSTR __RPC_FAR *pbstr) {
  3477. LPWSTR wszAlg = NULL;
  3478. HRESULT hr = S_OK;
  3479. assert(pbstr != NULL);
  3480. *pbstr = NULL;
  3481. if( (hr = get_HashAlgorithmWStr(&wszAlg)) == S_OK ) {
  3482. if( (*pbstr = SysAllocString(wszAlg)) == NULL )
  3483. hr = E_OUTOFMEMORY;
  3484. }
  3485. if(wszAlg != NULL)
  3486. MyCoTaskMemFree(wszAlg);
  3487. return(hr);
  3488. }
  3489. HRESULT STDMETHODCALLTYPE CCEnroll::put_HashAlgorithm(
  3490. /* [in] */ BSTR bstr) {
  3491. return(put_HashAlgorithmWStr(bstr));
  3492. }
  3493. HRESULT STDMETHODCALLTYPE CCEnroll::enumContainers(
  3494. /* [in] */ LONG dwIndex,
  3495. /* [out][retval] */ BSTR __RPC_FAR *pbstr) {
  3496. LPWSTR pwsz = NULL;
  3497. HRESULT hr;
  3498. assert(pbstr != NULL);
  3499. if((hr = enumContainersWStr(dwIndex, &pwsz)) != S_OK)
  3500. goto EnumContainerError;
  3501. if( (*pbstr = SysAllocString(pwsz)) == NULL )
  3502. {
  3503. hr = E_OUTOFMEMORY;
  3504. goto ErrorSysAllocString;
  3505. }
  3506. hr = S_OK;
  3507. ErrorReturn:
  3508. if(pwsz != NULL)
  3509. MyCoTaskMemFree(pwsz);
  3510. return(hr);
  3511. TRACE_ERROR(EnumContainerError);
  3512. TRACE_ERROR(ErrorSysAllocString);
  3513. }
  3514. HRESULT STDMETHODCALLTYPE CCEnroll::enumProviders(
  3515. /* [in] */ LONG dwIndex,
  3516. /* [in] */ LONG dwFlags,
  3517. /* [out][retval] */ BSTR __RPC_FAR *pbstrProvName) {
  3518. HRESULT hr;
  3519. LPWSTR pwszProvName = NULL;
  3520. assert(pbstrProvName != NULL);
  3521. *pbstrProvName = NULL;
  3522. if( (hr = enumProvidersWStr(dwIndex, dwFlags, &pwszProvName)) != S_OK)
  3523. goto EnumProvidersError;
  3524. if( (*pbstrProvName = SysAllocString(pwszProvName)) == NULL )
  3525. {
  3526. hr = E_OUTOFMEMORY;
  3527. goto ErrorSysAllocString;
  3528. }
  3529. hr = S_OK;
  3530. ErrorReturn:
  3531. if(pwszProvName != NULL)
  3532. MyCoTaskMemFree(pwszProvName);
  3533. return(hr);
  3534. TRACE_ERROR(EnumProvidersError);
  3535. TRACE_ERROR(ErrorSysAllocString);
  3536. }
  3537. HRESULT STDMETHODCALLTYPE CCEnroll::createFilePKCS10WStr(
  3538. /* [in] */ LPCWSTR DNName,
  3539. /* [in] */ LPCWSTR Usage,
  3540. /* [in] */ LPCWSTR wszPKCS10FileName) {
  3541. HRESULT hr;
  3542. BSTR bstrPKCS10 = NULL;
  3543. // get the pkcs 10
  3544. if( (hr = createPKCS10WStrBStr(
  3545. DNName,
  3546. Usage,
  3547. &bstrPKCS10)) != S_OK)
  3548. {
  3549. goto ErrorCreatePKCS10;
  3550. }
  3551. // save it to file
  3552. hr = BStringToFile(bstrPKCS10, wszPKCS10FileName);
  3553. if (S_OK != hr)
  3554. {
  3555. goto ErrorBStringToFile;
  3556. }
  3557. hr = S_OK;
  3558. ErrorReturn:
  3559. if(bstrPKCS10 != NULL)
  3560. SysFreeString(bstrPKCS10);
  3561. return(hr);
  3562. TRACE_ERROR(ErrorBStringToFile);
  3563. TRACE_ERROR(ErrorCreatePKCS10);
  3564. }
  3565. HRESULT STDMETHODCALLTYPE CCEnroll::acceptFilePKCS7WStr(
  3566. /* [in] */ LPCWSTR wszPKCS7FileName)
  3567. {
  3568. HRESULT hr;
  3569. CRYPT_DATA_BLOB blob;
  3570. ZeroMemory(&blob, sizeof(blob));
  3571. hr = xeStringToBinaryFromFile(
  3572. wszPKCS7FileName,
  3573. &blob.pbData,
  3574. &blob.cbData,
  3575. CRYPT_STRING_ANY);
  3576. if (S_OK != hr)
  3577. {
  3578. goto xeStringToBinaryFromFileError;
  3579. }
  3580. // accept the blob
  3581. hr = acceptPKCS7Blob(&blob);
  3582. ErrorReturn:
  3583. if (NULL != blob.pbData)
  3584. {
  3585. MyCoTaskMemFree(blob.pbData);
  3586. }
  3587. return(hr);
  3588. TRACE_ERROR(xeStringToBinaryFromFileError)
  3589. }
  3590. BOOL GetAlgAndBitLen(
  3591. HCRYPTPROV hProv,
  3592. ALG_ID * pAlg,
  3593. DWORD * pdwBitLen,
  3594. DWORD dwFlags)
  3595. {
  3596. static BOOL fNew = TRUE;
  3597. PROV_ENUMALGS_EX enumAlgsEx;
  3598. PROV_ENUMALGS enumAlgs;
  3599. DWORD cb = 0;
  3600. *pAlg = 0;
  3601. *pdwBitLen = 0;
  3602. if(fNew) {
  3603. cb = sizeof(enumAlgsEx);
  3604. if(CryptGetProvParam(
  3605. hProv,
  3606. PP_ENUMALGS_EX,
  3607. (BYTE *) &enumAlgsEx,
  3608. &cb,
  3609. dwFlags)) {
  3610. *pAlg = enumAlgsEx.aiAlgid;
  3611. *pdwBitLen = enumAlgsEx.dwMaxLen;
  3612. return(TRUE);
  3613. } else if(dwFlags != 0)
  3614. fNew = FALSE;
  3615. else
  3616. return(FALSE);
  3617. }
  3618. // otherwise do the old stuff
  3619. cb = sizeof(PROV_ENUMALGS);
  3620. if(CryptGetProvParam(
  3621. hProv,
  3622. PP_ENUMALGS,
  3623. (BYTE *) &enumAlgs,
  3624. &cb,
  3625. dwFlags) ) {
  3626. *pAlg = enumAlgs.aiAlgid;
  3627. *pdwBitLen = enumAlgs.dwBitLen;
  3628. return(TRUE);
  3629. }
  3630. return(FALSE);
  3631. }
  3632. HRESULT
  3633. CreateSMimeExtension(
  3634. IN HCRYPTPROV hProv,
  3635. OUT BYTE **ppbSMime,
  3636. OUT DWORD *pcbSMime)
  3637. {
  3638. #define CINCSMIMECAP 20
  3639. HRESULT hr;
  3640. DWORD dwBitLen;
  3641. DWORD i;
  3642. DWORD cbE;
  3643. BYTE *pbE = NULL;
  3644. DWORD dwFlags;
  3645. PCCRYPT_OID_INFO pOidInfo = NULL;
  3646. CRYPT_SMIME_CAPABILITIES smimeCaps;
  3647. DWORD crgsmimeCap = 0;
  3648. ALG_ID AlgID;
  3649. BYTE *pb = NULL;
  3650. DWORD cb = 0;
  3651. memset(&smimeCaps, 0, sizeof(CRYPT_SMIME_CAPABILITIES));
  3652. smimeCaps.rgCapability = (PCRYPT_SMIME_CAPABILITY) LocalAlloc(LPTR, CINCSMIMECAP * sizeof(CRYPT_SMIME_CAPABILITY));
  3653. if (NULL == smimeCaps.rgCapability)
  3654. {
  3655. hr = E_OUTOFMEMORY;
  3656. goto OutOfMemoryError;
  3657. }
  3658. crgsmimeCap = CINCSMIMECAP;
  3659. dwFlags = CRYPT_FIRST; //first item
  3660. while (GetAlgAndBitLen(hProv, &AlgID, &dwBitLen, dwFlags))
  3661. {
  3662. pbE = NULL;
  3663. cbE = 0;
  3664. dwFlags = 0; //next item
  3665. if(ALG_CLASS_DATA_ENCRYPT == GET_ALG_CLASS(AlgID))
  3666. {
  3667. if(AlgID == CALG_RC2 || AlgID == CALG_RC4)
  3668. {
  3669. // encode the usage
  3670. while (TRUE)
  3671. {
  3672. if(!CryptEncodeObject(
  3673. CRYPT_ASN_ENCODING,
  3674. X509_INTEGER,
  3675. &dwBitLen,
  3676. pbE, // pbEncoded
  3677. &cbE))
  3678. {
  3679. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3680. goto CryptEncodeObjectError;
  3681. }
  3682. if (NULL != pbE)
  3683. {
  3684. break;
  3685. }
  3686. pbE = (BYTE *)LocalAlloc(LPTR, cbE);
  3687. if (NULL == pbE)
  3688. {
  3689. hr = E_OUTOFMEMORY;
  3690. goto OutOfMemoryError;
  3691. }
  3692. }
  3693. }
  3694. } else {
  3695. continue;
  3696. }
  3697. // convert to an oid,
  3698. pOidInfo = xeCryptFindOIDInfo(
  3699. CRYPT_OID_INFO_ALGID_KEY,
  3700. (void *) &AlgID,
  3701. CRYPT_ENCRYPT_ALG_OID_GROUP_ID);
  3702. if(NULL == pOidInfo)
  3703. {
  3704. // don't crash on an error, just say we don't known it.
  3705. if (NULL != pbE) {
  3706. LocalFree(pbE);
  3707. }
  3708. pbE = NULL;
  3709. continue;
  3710. }
  3711. // make sure we have enough room
  3712. if(smimeCaps.cCapability >= crgsmimeCap)
  3713. {
  3714. PCRYPT_SMIME_CAPABILITY pSmimeCapsTmp;
  3715. //increment the size
  3716. crgsmimeCap += CINCSMIMECAP;
  3717. pSmimeCapsTmp = (PCRYPT_SMIME_CAPABILITY)LocalReAlloc(
  3718. smimeCaps.rgCapability,
  3719. crgsmimeCap * sizeof(CRYPT_SMIME_CAPABILITY),
  3720. LMEM_MOVEABLE | LMEM_ZEROINIT);
  3721. if(NULL == pSmimeCapsTmp)
  3722. {
  3723. hr = E_OUTOFMEMORY;
  3724. goto OutOfMemoryError;
  3725. }
  3726. smimeCaps.rgCapability = pSmimeCapsTmp;
  3727. }
  3728. smimeCaps.rgCapability[smimeCaps.cCapability].pszObjId = (char *) pOidInfo->pszOID;
  3729. smimeCaps.rgCapability[smimeCaps.cCapability].Parameters.pbData = pbE;
  3730. smimeCaps.rgCapability[smimeCaps.cCapability].Parameters.cbData = cbE;
  3731. smimeCaps.cCapability++;
  3732. pbE = NULL; // We'll free pbE through the struct we just assigned. NULL out so we don't double-free.
  3733. }
  3734. // encode the capabilities
  3735. while (TRUE)
  3736. {
  3737. if (!CryptEncodeObject(
  3738. CRYPT_ASN_ENCODING,
  3739. PKCS_SMIME_CAPABILITIES,
  3740. &smimeCaps,
  3741. pb,
  3742. &cb))
  3743. {
  3744. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3745. goto CryptEncodeObjectError;
  3746. }
  3747. if (NULL != pb)
  3748. {
  3749. break;
  3750. }
  3751. pb = (BYTE *)LocalAlloc(LPTR, cb);
  3752. }
  3753. *ppbSMime = pb;
  3754. *pcbSMime = cb;
  3755. pb = NULL;
  3756. hr = S_OK;
  3757. ErrorReturn:
  3758. if(NULL != smimeCaps.rgCapability)
  3759. {
  3760. for (i = 0; i < smimeCaps.cCapability; ++i)
  3761. {
  3762. if (NULL != smimeCaps.rgCapability[i].Parameters.pbData)
  3763. {
  3764. LocalFree(smimeCaps.rgCapability[i].Parameters.pbData);
  3765. }
  3766. }
  3767. LocalFree(smimeCaps.rgCapability);
  3768. }
  3769. if(NULL != pb)
  3770. {
  3771. LocalFree(pb);
  3772. }
  3773. if (NULL != pbE)
  3774. {
  3775. LocalFree(pbE);
  3776. }
  3777. return hr;
  3778. TRACE_ERROR(CryptEncodeObjectError)
  3779. TRACE_ERROR(OutOfMemoryError)
  3780. }
  3781. #if DBG
  3782. void DebugGetContainerSD(HCRYPTPROV hProv)
  3783. {
  3784. PSECURITY_DESCRIPTOR pSD = NULL;
  3785. DWORD cbSD;
  3786. while (TRUE)
  3787. {
  3788. if (!CryptGetProvParam(
  3789. hProv,
  3790. PP_KEYSET_SEC_DESCR,
  3791. (BYTE*)pSD,
  3792. &cbSD,
  3793. DACL_SECURITY_INFORMATION))
  3794. {
  3795. break;
  3796. }
  3797. if (NULL != pSD)
  3798. {
  3799. break;
  3800. }
  3801. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSD);
  3802. if (NULL == pSD)
  3803. {
  3804. break;
  3805. }
  3806. }
  3807. if (NULL != pSD)
  3808. {
  3809. LocalFree(pSD);
  3810. }
  3811. }
  3812. #endif //DBG
  3813. //get the current user sids
  3814. HRESULT
  3815. GetCurrentUserInfo(
  3816. OUT PTOKEN_USER *ppUserInfo,
  3817. OUT BOOL *pfAdmin)
  3818. {
  3819. HRESULT hr;
  3820. PTOKEN_USER pUserInfo = NULL;
  3821. DWORD dwSize = 0;
  3822. HANDLE hToken = NULL;
  3823. HANDLE hDupToken = NULL;
  3824. PSID psidAdministrators = NULL;
  3825. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  3826. HANDLE hThread;
  3827. HANDLE hProcess;
  3828. //init
  3829. *pfAdmin = FALSE;
  3830. if (!AllocateAndInitializeSid(
  3831. &siaNtAuthority,
  3832. 2,
  3833. SECURITY_BUILTIN_DOMAIN_RID,
  3834. DOMAIN_ALIAS_RID_ADMINS,
  3835. 0,
  3836. 0,
  3837. 0,
  3838. 0,
  3839. 0,
  3840. 0,
  3841. &psidAdministrators))
  3842. {
  3843. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3844. goto AllocateAndInitializeSidError;
  3845. }
  3846. hThread = GetCurrentThread();
  3847. if (NULL == hThread)
  3848. {
  3849. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3850. goto GetCurrentThreadError;
  3851. }
  3852. // Get the access token for current thread
  3853. if (!OpenThreadToken(
  3854. hThread,
  3855. TOKEN_QUERY | TOKEN_DUPLICATE,
  3856. FALSE,
  3857. &hToken))
  3858. {
  3859. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3860. if(HRESULT_FROM_WIN32(ERROR_NO_TOKEN) != hr)
  3861. {
  3862. goto OpenThreadTokenError;
  3863. }
  3864. //get process token instead
  3865. hProcess = GetCurrentProcess();
  3866. if (NULL == hProcess)
  3867. {
  3868. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3869. goto GetCurrentProcessError;
  3870. }
  3871. hToken = NULL;
  3872. if (!OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &hToken))
  3873. {
  3874. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3875. goto OpenProcessTokenError;
  3876. }
  3877. }
  3878. // CheckTokenMembership must operate on impersonation token, so make one
  3879. if (!DuplicateToken(hToken, SecurityIdentification, &hDupToken))
  3880. {
  3881. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3882. goto DuplicateTokenError;
  3883. }
  3884. if (!MyCheckTokenMembership(hDupToken, psidAdministrators, pfAdmin))
  3885. {
  3886. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3887. goto CheckTokenMembershipError;
  3888. }
  3889. //get current user sid
  3890. while (TRUE)
  3891. {
  3892. if (!GetTokenInformation(
  3893. hToken,
  3894. TokenUser,
  3895. pUserInfo,
  3896. dwSize,
  3897. &dwSize))
  3898. {
  3899. if (NULL != pUserInfo ||
  3900. ERROR_INSUFFICIENT_BUFFER != GetLastError())
  3901. {
  3902. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  3903. goto GetTokenInformationError;
  3904. }
  3905. }
  3906. if (NULL != pUserInfo)
  3907. {
  3908. //done
  3909. break;
  3910. }
  3911. pUserInfo = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, dwSize);
  3912. if (NULL == pUserInfo)
  3913. {
  3914. hr = E_OUTOFMEMORY;
  3915. goto LocalAllocError;
  3916. }
  3917. }
  3918. if (NULL != ppUserInfo)
  3919. {
  3920. *ppUserInfo = pUserInfo;
  3921. pUserInfo = NULL;
  3922. }
  3923. hr = S_OK;
  3924. ErrorReturn:
  3925. if (NULL != pUserInfo)
  3926. {
  3927. LocalFree(pUserInfo);
  3928. }
  3929. if (NULL != hToken)
  3930. {
  3931. CloseHandle(hToken);
  3932. }
  3933. if (NULL != hDupToken)
  3934. {
  3935. CloseHandle(hDupToken);
  3936. }
  3937. if (NULL != psidAdministrators)
  3938. {
  3939. FreeSid(psidAdministrators);
  3940. }
  3941. return hr;
  3942. TRACE_ERROR(LocalAllocError)
  3943. TRACE_ERROR(GetTokenInformationError)
  3944. TRACE_ERROR(OpenProcessTokenError)
  3945. TRACE_ERROR(GetCurrentProcessError)
  3946. TRACE_ERROR(CheckTokenMembershipError)
  3947. TRACE_ERROR(DuplicateTokenError)
  3948. TRACE_ERROR(OpenThreadTokenError)
  3949. TRACE_ERROR(GetCurrentThreadError)
  3950. TRACE_ERROR(AllocateAndInitializeSidError)
  3951. }
  3952. HRESULT
  3953. SetKeyContainerSecurityForNULLDacl(
  3954. HCRYPTPROV hProv,
  3955. DWORD dwFlags,
  3956. PTOKEN_USER pUserInfo)
  3957. {
  3958. DWORD ccNeeded;
  3959. HRESULT hr;
  3960. LPWSTR wszSD = NULL;
  3961. LPWSTR wszUserSid = NULL;
  3962. PSECURITY_DESCRIPTOR pSD = NULL;
  3963. UNREFERENCED_PARAMETER(dwFlags);
  3964. // We want the security descriptor for the new keyset to look like so:
  3965. //
  3966. // ACES:
  3967. // NT AUTHORITY\SYSTEM:F
  3968. // BUILTIN\Administrators:F
  3969. //
  3970. //
  3971. #define SDDL_NEW_KEYSET_START L"D:(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;"
  3972. #define SDDL_NEW_KEYSET_END L")"
  3973. if (!ConvertSidToStringSidW(pUserInfo->User.Sid, &wszUserSid)) {
  3974. goto ConvertSidToStringSidError;
  3975. }
  3976. ccNeeded = (DWORD)(wcslen(SDDL_NEW_KEYSET_START) + wcslen(wszUserSid) + wcslen(SDDL_NEW_KEYSET_END) + 1);
  3977. wszSD = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*ccNeeded);
  3978. if (NULL == wszSD) {
  3979. goto MemoryError;
  3980. }
  3981. wcscpy(wszSD, SDDL_NEW_KEYSET_START);
  3982. wcscat(wszSD, wszUserSid);
  3983. wcscat(wszSD, SDDL_NEW_KEYSET_END);
  3984. if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(wszSD, SDDL_REVISION_1, &pSD, NULL)) {
  3985. goto ConvertStringSecurityDescriptorToSecurityDescriptorWError;
  3986. }
  3987. if (!IsValidSecurityDescriptor(pSD)) {
  3988. goto IsValidSecurityDescriptorError;
  3989. }
  3990. #if DBG
  3991. DebugGetContainerSD(hProv); //just for ntsd debug
  3992. #endif
  3993. if (!CryptSetProvParam(hProv, PP_KEYSET_SEC_DESCR, (BYTE*)pSD, DACL_SECURITY_INFORMATION)) {
  3994. goto CryptSetProvParamError;
  3995. }
  3996. #if DBG
  3997. DebugGetContainerSD(hProv); //just for ntsd debug
  3998. #endif
  3999. hr = S_OK;
  4000. ErrorReturn:
  4001. if (NULL != wszSD)
  4002. {
  4003. LocalFree(wszSD);
  4004. }
  4005. if (NULL != wszUserSid)
  4006. {
  4007. LocalFree(wszUserSid);
  4008. }
  4009. if (NULL != pSD)
  4010. {
  4011. LocalFree(pSD);
  4012. }
  4013. return hr;
  4014. SET_HRESULT(ConvertSidToStringSidError, HRESULT_FROM_WIN32(GetLastError()));
  4015. SET_HRESULT(ConvertStringSecurityDescriptorToSecurityDescriptorWError, HRESULT_FROM_WIN32(GetLastError()));
  4016. SET_HRESULT(CryptSetProvParamError, HRESULT_FROM_WIN32(GetLastError()));
  4017. SET_HRESULT(IsValidSecurityDescriptorError, HRESULT_FROM_WIN32(ERROR_INVALID_SECURITY_DESCR));
  4018. SET_HRESULT(MemoryError, E_OUTOFMEMORY);
  4019. }
  4020. // This function ACLs new keysets (as 3rd party CSPs and downlevel CSPs may not do this correctly.
  4021. // Should *not* call this function on existing keysets (as ACLs may have been set differently by admins)
  4022. //
  4023. HRESULT
  4024. SetKeyContainerSecurity(
  4025. HCRYPTPROV hProv,
  4026. DWORD dwFlags)
  4027. {
  4028. HRESULT hr;
  4029. PSECURITY_DESCRIPTOR pNewSD = NULL;
  4030. PSECURITY_DESCRIPTOR pSD = NULL;
  4031. DWORD cbSD;
  4032. ACL_SIZE_INFORMATION AclInfo;
  4033. PTOKEN_USER pUserInfo = NULL;
  4034. PACL pNewAcl = NULL;
  4035. LPVOID pAce;
  4036. DWORD dwIndex;
  4037. BYTE AceType;
  4038. PACL pAcl;
  4039. BOOL fDacl = TRUE;
  4040. BOOL fDef = FALSE;
  4041. BOOL fAdmin;
  4042. BOOL fKeepSystemSid;
  4043. BOOL fMachineKeySet = (0x0 != (dwFlags & CRYPT_MACHINE_KEYSET)) ?
  4044. TRUE : FALSE;
  4045. PSID pSidSystem = NULL;
  4046. PSID pSidAdministrators = NULL;
  4047. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  4048. //get the current user info
  4049. hr = GetCurrentUserInfo(&pUserInfo, &fAdmin);
  4050. if (S_OK != hr)
  4051. {
  4052. goto GetCurrentUserInfoError;
  4053. }
  4054. //get the current sd from key container
  4055. while (TRUE)
  4056. {
  4057. if (!CryptGetProvParam(
  4058. hProv,
  4059. PP_KEYSET_SEC_DESCR,
  4060. (BYTE*)pSD,
  4061. &cbSD,
  4062. DACL_SECURITY_INFORMATION))
  4063. {
  4064. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4065. goto CryptGetProvParamError;
  4066. }
  4067. if (NULL != pSD)
  4068. {
  4069. break;
  4070. }
  4071. pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LMEM_FIXED, cbSD);
  4072. if (NULL == pSD)
  4073. {
  4074. hr = E_OUTOFMEMORY;
  4075. goto OutOfMemoryError;
  4076. }
  4077. }
  4078. //get acl from sd
  4079. if (!GetSecurityDescriptorDacl(
  4080. pSD,
  4081. &fDacl,
  4082. &pAcl,
  4083. &fDef))
  4084. {
  4085. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4086. goto GetSecurityDescriptorDaclError;
  4087. }
  4088. if (!fDacl)
  4089. {
  4090. //if no dacl, quit
  4091. hr = MY_HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  4092. goto GetSecurityDescriptorDaclError;
  4093. }
  4094. if (NULL == pAcl)
  4095. {
  4096. #if 0
  4097. //this means allow everyone access the key which is unexpected,
  4098. hr = SetKeyContainerSecurityForNULLDacl(hProv, dwFlags, pUserInfo);
  4099. #endif
  4100. // BUGBUG: The NULL DACL stuff doesn't work on downlevels because it requires SDDL. We don't
  4101. // have time to fix for windows update, but we should revisit this later
  4102. hr = S_OK;
  4103. goto done;
  4104. }
  4105. //get acl info
  4106. if (!GetAclInformation(
  4107. pAcl,
  4108. &AclInfo,
  4109. sizeof(AclInfo),
  4110. AclSizeInformation))
  4111. {
  4112. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4113. goto GetAclInformationError;
  4114. }
  4115. //allocate enough for new dacl since we just remove aces
  4116. pNewAcl = (PACL)LocalAlloc(LMEM_ZEROINIT, AclInfo.AclBytesInUse);
  4117. if (NULL == pNewAcl)
  4118. {
  4119. hr = E_OUTOFMEMORY;
  4120. goto LocalAllocError;
  4121. }
  4122. if (!InitializeAcl(pNewAcl, AclInfo.AclBytesInUse, ACL_REVISION))
  4123. {
  4124. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4125. goto InitializeAclError;
  4126. }
  4127. fKeepSystemSid = fAdmin && fMachineKeySet;
  4128. if (fKeepSystemSid)
  4129. {
  4130. //get system sid to later use
  4131. if (!AllocateAndInitializeSid(
  4132. &siaNtAuthority,
  4133. 1,
  4134. SECURITY_LOCAL_SYSTEM_RID,
  4135. 0,
  4136. 0,
  4137. 0,
  4138. 0,
  4139. 0,
  4140. 0,
  4141. 0,
  4142. &pSidSystem))
  4143. {
  4144. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4145. goto AllocateAndInitializeSidError;
  4146. }
  4147. }
  4148. if (!AllocateAndInitializeSid(&siaNtAuthority,
  4149. 2,
  4150. SECURITY_BUILTIN_DOMAIN_RID,
  4151. DOMAIN_ALIAS_RID_ADMINS,
  4152. 0, 0, 0, 0, 0, 0,
  4153. &pSidAdministrators
  4154. ))
  4155. {
  4156. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4157. goto AllocateAndInitializeSidError;
  4158. }
  4159. //go through each ace, get only current user aces
  4160. for (dwIndex = 0; dwIndex < AclInfo.AceCount; ++dwIndex)
  4161. {
  4162. if (!GetAce(pAcl, dwIndex, &pAce))
  4163. {
  4164. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4165. goto GetAceError;
  4166. }
  4167. AceType = ((ACCESS_ALLOWED_ACE*)pAce)->Header.AceType;
  4168. if (ACCESS_ALLOWED_ACE_TYPE == AceType)
  4169. {
  4170. if (EqualSid(pUserInfo->User.Sid, (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart))
  4171. || (fKeepSystemSid && EqualSid(pSidSystem, (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart)))
  4172. || EqualSid(pSidAdministrators, (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart)))
  4173. {
  4174. //add current user ace or system ace into new acl
  4175. if (!AddAccessAllowedAce(
  4176. pNewAcl,
  4177. ACL_REVISION,
  4178. ((PACCESS_ALLOWED_ACE)pAce)->Mask,
  4179. (PSID)&(((PACCESS_ALLOWED_ACE)pAce)->SidStart)))
  4180. {
  4181. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4182. goto AddAccessAllowedAceError;
  4183. }
  4184. }
  4185. }
  4186. else if (ACCESS_DENIED_ACE_TYPE == AceType)
  4187. {
  4188. //add all deny ace into new acl
  4189. if (!AddAccessDeniedAce(
  4190. pNewAcl,
  4191. ACL_REVISION,
  4192. ((PACCESS_ALLOWED_ACE)pAce)->Mask,
  4193. (PSID)&(((PACCESS_DENIED_ACE)pAce)->SidStart)))
  4194. {
  4195. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4196. goto AddAccessDeniedAceError;
  4197. }
  4198. }
  4199. }
  4200. // initialize a security descriptor.
  4201. pNewSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
  4202. SECURITY_DESCRIPTOR_MIN_LENGTH);
  4203. if (pNewSD == NULL)
  4204. {
  4205. hr = E_OUTOFMEMORY;
  4206. goto LocalAllocError;
  4207. }
  4208. if (!InitializeSecurityDescriptor(pNewSD, SECURITY_DESCRIPTOR_REVISION))
  4209. {
  4210. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4211. goto InitializeSecurityDescriptorError;
  4212. }
  4213. // add the ACL to the security descriptor.
  4214. if (!SetSecurityDescriptorDacl(
  4215. pNewSD,
  4216. TRUE, // fDaclPresent flag
  4217. pNewAcl,
  4218. FALSE)) // not a default DACL
  4219. {
  4220. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4221. goto SetSecurityDescriptorDaclError;
  4222. }
  4223. //ok, set sd to be protected
  4224. if (!MySetSecurityDescriptorControl(
  4225. pNewSD,
  4226. SE_DACL_PROTECTED,
  4227. SE_DACL_PROTECTED))
  4228. {
  4229. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4230. goto SetSecurityDescriptorControlError;
  4231. }
  4232. if (!IsValidSecurityDescriptor(pNewSD))
  4233. {
  4234. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4235. goto IsValidSecurityDescriptorError;
  4236. }
  4237. #if DBG
  4238. DebugGetContainerSD(hProv); //just for ntsd debug
  4239. #endif
  4240. //now we just set it
  4241. if (!CryptSetProvParam(
  4242. hProv,
  4243. PP_KEYSET_SEC_DESCR,
  4244. (BYTE*)pNewSD,
  4245. DACL_SECURITY_INFORMATION))
  4246. {
  4247. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  4248. goto CryptSetProvParamError;
  4249. }
  4250. #if DBG
  4251. DebugGetContainerSD(hProv); //just for ntsd debug
  4252. #endif
  4253. done:
  4254. hr = S_OK;
  4255. ErrorReturn:
  4256. if (NULL != pSD)
  4257. {
  4258. LocalFree(pSD);
  4259. }
  4260. if (NULL != pUserInfo)
  4261. {
  4262. LocalFree(pUserInfo);
  4263. }
  4264. if (NULL != pNewAcl)
  4265. {
  4266. LocalFree(pNewAcl);
  4267. }
  4268. if (NULL != pNewSD)
  4269. {
  4270. LocalFree(pNewSD);
  4271. }
  4272. if (NULL != pSidSystem)
  4273. {
  4274. FreeSid(pSidSystem);
  4275. }
  4276. if (NULL != pSidAdministrators)
  4277. {
  4278. FreeSid(pSidAdministrators);
  4279. }
  4280. return hr;
  4281. TRACE_ERROR(CryptSetProvParamError)
  4282. TRACE_ERROR(SetSecurityDescriptorDaclError)
  4283. TRACE_ERROR(InitializeSecurityDescriptorError)
  4284. TRACE_ERROR(LocalAllocError)
  4285. TRACE_ERROR(AddAccessAllowedAceError)
  4286. TRACE_ERROR(AddAccessDeniedAceError)
  4287. TRACE_ERROR(GetAceError)
  4288. TRACE_ERROR(GetCurrentUserInfoError)
  4289. TRACE_ERROR(InitializeAclError)
  4290. TRACE_ERROR(GetAclInformationError)
  4291. TRACE_ERROR(GetSecurityDescriptorDaclError)
  4292. TRACE_ERROR(OutOfMemoryError)
  4293. TRACE_ERROR(CryptGetProvParamError)
  4294. TRACE_ERROR(SetSecurityDescriptorControlError)
  4295. TRACE_ERROR(IsValidSecurityDescriptorError)
  4296. TRACE_ERROR(AllocateAndInitializeSidError)
  4297. }
  4298. HRESULT STDMETHODCALLTYPE CCEnroll::createPKCS10WStr(
  4299. /* [in] */ LPCWSTR DNName,
  4300. /* [in] */ LPCWSTR wszPurpose,
  4301. /* [out] */ PCRYPT_DATA_BLOB pPkcs10Blob)
  4302. {
  4303. #define EndExt 5
  4304. #define EndAttr 6
  4305. HCRYPTPROV hProv = NULL;
  4306. HCRYPTKEY hKey = NULL;
  4307. CERT_REQUEST_INFO reqInfo;
  4308. CERT_EXTENSIONS Extensions;
  4309. PCERT_EXTENSION pExtCur = NULL;
  4310. PCERT_EXTENSION rgExtension = NULL;
  4311. CRYPT_ATTRIBUTE rgAttribute[EndAttr];
  4312. CRYPT_ATTR_BLOB blobExt;
  4313. CRYPT_ATTR_BLOB blobCSPAttr;
  4314. CRYPT_CSP_PROVIDER CSPProvider;
  4315. CRYPT_ATTR_BLOB blobOSVAttr;
  4316. CRYPT_ATTR_BLOB blobSMIMEPKCS7;
  4317. CERT_NAME_VALUE cnvOSVer;
  4318. OSVERSIONINFO osvInfo;
  4319. DWORD iExt = 0;
  4320. CRYPT_BIT_BLOB bbKeyUsage;
  4321. BYTE bKeyUsage;
  4322. CERT_SIGNED_CONTENT_INFO SignatureInfo;
  4323. HRESULT hr = S_OK;
  4324. DWORD errBefore = GetLastError();
  4325. PCCERT_CONTEXT pCertContext = NULL;
  4326. HCERTSTORE hStore = NULL;
  4327. DWORD ssFlags = 0;
  4328. HANDLE hFile = NULL;
  4329. CRYPT_DATA_BLOB blobData;
  4330. DWORD cb = 0;
  4331. char * pszPurpose = NULL;
  4332. char * szStart = NULL;
  4333. char * szEnd = NULL;
  4334. char szVersion[45] = {0};
  4335. BOOL fAddCodeSign = FALSE;
  4336. DWORD cPassedEKU = 0;
  4337. DWORD i = 0;
  4338. BOOL fRet;
  4339. BYTE *pbSMime = NULL;
  4340. BYTE *pbKU = NULL;
  4341. BYTE *pbEKU = NULL;
  4342. PPROP_STACK pProp;
  4343. CRYPT_ATTR_BLOB blobClientId;
  4344. DWORD cPublicKeyInfo = 0;
  4345. BYTE *pbSubjectKeyHashExtension = NULL;
  4346. DWORD cbSubjectKeyHashExtension = 0;
  4347. DWORD dwErr;
  4348. LPWSTR pwszNotSafeRequesting = NULL;
  4349. LPWSTR pwszTitle = NULL;
  4350. //
  4351. // Declaration of extensions we need. The extensions with matching OIDs will be added
  4352. // to the temporary cert context created by this method.
  4353. //
  4354. LPSTR rgszExtensionOIDs[] = {
  4355. szOID_ENROLL_CERTTYPE_EXTENSION,
  4356. szOID_CERTIFICATE_TEMPLATE
  4357. };
  4358. // An array of the extensions we need to add to the certificate
  4359. CERT_EXTENSION rgNeededExtensions[sizeof(rgszExtensionOIDs) / sizeof(LPSTR)];
  4360. // Need to put the array in a CERT_EXTENSIONS struct.
  4361. CERT_EXTENSIONS ceExtensions;
  4362. ceExtensions.rgExtension = &rgNeededExtensions[0];
  4363. ceExtensions.cExtension = 0;
  4364. CRYPT_KEY_PROV_INFO keyProvInfoT;
  4365. CERT_ENHKEY_USAGE enhKeyUsage;
  4366. CRYPT_DATA_BLOB blobPKCS7;
  4367. CRYPT_DATA_BLOB blobRenewAttr;
  4368. RequestFlags requestFlags;
  4369. CRYPT_DATA_BLOB requestInfoBlob;
  4370. CRYPT_DATA_BLOB blobRenewalCert;
  4371. ALG_ID rgAlg[2];
  4372. PCCRYPT_OID_INFO pOidInfo = NULL;
  4373. EnterCriticalSection(&m_csXEnroll);
  4374. // for the life of our procedure.
  4375. SetLastError(ERROR_SUCCESS);
  4376. assert(pPkcs10Blob != NULL);
  4377. // clean out the PKCS 10
  4378. memset(&Extensions, 0, sizeof(CERT_EXTENSIONS));
  4379. memset(&rgAttribute, 0, sizeof(rgAttribute));
  4380. memset(&reqInfo, 0, sizeof(CERT_REQUEST_INFO));
  4381. memset(&SignatureInfo, 0, sizeof(SignatureInfo));
  4382. memset(&blobData, 0, sizeof(CRYPT_DATA_BLOB));
  4383. memset(&enhKeyUsage, 0, sizeof(CERT_ENHKEY_USAGE ));
  4384. memset(pPkcs10Blob, 0, sizeof(CRYPT_DATA_BLOB));
  4385. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  4386. memset(&blobRenewAttr, 0, sizeof(CRYPT_DATA_BLOB));
  4387. memset(&requestFlags, 0, sizeof(RequestFlags));
  4388. memset(&requestInfoBlob, 0, sizeof(CRYPT_DATA_BLOB));
  4389. memset(&CSPProvider, 0, sizeof(CRYPT_CSP_PROVIDER));
  4390. memset(&cnvOSVer, 0, sizeof(CERT_NAME_VALUE));
  4391. memset(&osvInfo, 0, sizeof(OSVERSIONINFO));
  4392. memset(&blobSMIMEPKCS7, 0, sizeof(CRYPT_ATTR_BLOB));
  4393. memset(&rgNeededExtensions[0], 0, sizeof(rgNeededExtensions));
  4394. ZeroMemory(&blobExt, sizeof(blobExt));
  4395. memset(&blobCSPAttr, 0, sizeof(CRYPT_ATTR_BLOB));
  4396. memset(&blobOSVAttr, 0, sizeof(CRYPT_ATTR_BLOB));
  4397. memset(&blobClientId, 0, sizeof(CRYPT_ATTR_BLOB));
  4398. reqInfo.dwVersion = CERT_REQUEST_V1;
  4399. // Creating a request is not safe for scripting: pop up a warning dialog if called from script
  4400. if (0 != m_dwEnabledSafteyOptions) {
  4401. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFEACTION, &pwszTitle);
  4402. if (S_OK != hr) {
  4403. SetLastError(hr);
  4404. goto xeLoadRCStringError;
  4405. }
  4406. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFE_REQUESTING_CERT, &pwszNotSafeRequesting);
  4407. if (S_OK != hr) {
  4408. SetLastError(hr);
  4409. goto xeLoadRCStringError;
  4410. }
  4411. if (IDYES != MessageBoxU(NULL, pwszNotSafeRequesting, pwszTitle, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2)) {
  4412. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  4413. SetLastError(hr);
  4414. goto CancelledError;
  4415. }
  4416. }
  4417. if(!m_fUseExistingKey)
  4418. {
  4419. // attempt to get a new keyset
  4420. if((hProv = GetProv(CRYPT_NEWKEYSET)) == NULL) {
  4421. // in the hardware token case, there may only be a finite number of containers
  4422. // if you run out, then use the default container. The Default container can
  4423. // be specified by either a NULL or empty container name.
  4424. // this is behavior requested by the smart cards, in particular smart card enrollment.
  4425. if( m_fReuseHardwareKeyIfUnableToGenNew &&
  4426. GetLastError() == NTE_TOKEN_KEYSET_STORAGE_FULL) {
  4427. // set it to the default container name
  4428. if( m_keyProvInfo.pwszContainerName != wszEmpty )
  4429. MyCoTaskMemFree(m_keyProvInfo.pwszContainerName);
  4430. m_keyProvInfo.pwszContainerName = wszEmpty;
  4431. // say we want to use an exiting key.
  4432. m_fUseExistingKey = TRUE;
  4433. }
  4434. else
  4435. goto ErrorCryptAcquireContext;
  4436. }
  4437. }
  4438. // if we are to use an existing key
  4439. if(m_fUseExistingKey) {
  4440. if((hProv = GetProv(0)) == NULL)
  4441. goto ErrorCryptAcquireContext;
  4442. }
  4443. // we have the keyset, now make sure we have the key gen'ed
  4444. if(!CryptGetUserKey(
  4445. hProv,
  4446. m_keyProvInfo.dwKeySpec,
  4447. &hKey))
  4448. {
  4449. //in case of smartcard csp, above call could be failed from
  4450. //PIN Cancel button, don't go next to try genkey
  4451. //also notice different csp could return different cancel errors
  4452. dwErr = GetLastError();
  4453. if (SCARD_W_CANCELLED_BY_USER == dwErr ||
  4454. ERROR_CANCELLED == dwErr ||
  4455. ERROR_ACCESS_DENIED == dwErr)
  4456. {
  4457. goto CryptGetUserKeyCancelError;
  4458. }
  4459. // doesn't exist so gen it
  4460. assert(hKey == NULL);
  4461. // if the cached key is non-NULL, free it to prevent memory leaks
  4462. if (NULL != m_hCachedKey)
  4463. {
  4464. CryptDestroyKey(m_hCachedKey);
  4465. m_hCachedKey = NULL;
  4466. }
  4467. if(!CryptGenKey( hProv,
  4468. m_keyProvInfo.dwKeySpec,
  4469. m_dwGenKeyFlags | CRYPT_ARCHIVABLE,
  4470. &m_hCachedKey) )
  4471. {
  4472. //could be cancelled by user? don't make next try
  4473. dwErr = GetLastError();
  4474. if (SCARD_W_CANCELLED_BY_USER == dwErr ||
  4475. ERROR_CANCELLED == dwErr ||
  4476. ERROR_ACCESS_DENIED == dwErr)
  4477. {
  4478. goto ErrorCryptGenKey;
  4479. }
  4480. //this error may be caused by not supporting CRYPT_ARCHIVABLE
  4481. //we should check against error NTE_BAD_FLAGS but I doubt all
  4482. //csps return consistent error code
  4483. //let's try one more time without archivable flag
  4484. assert(NULL == m_hCachedKey);
  4485. DWORD dwGenKeyFlags = m_dwGenKeyFlags;
  4486. if (NULL != m_PrivateKeyArchiveCertificate && m_fNewRequestMethod && (0 == (dwGenKeyFlags & CRYPT_EXPORTABLE)))
  4487. {
  4488. // We want ARCHIVABLE but not EXPORTABLE, so we needed the CRYPT_ARCHIVAL bit. Give up.
  4489. goto ErrorCryptGenKey;
  4490. }
  4491. if (!CryptGenKey(
  4492. hProv,
  4493. m_keyProvInfo.dwKeySpec,
  4494. dwGenKeyFlags,
  4495. &hKey))
  4496. {
  4497. goto ErrorCryptGenKey;
  4498. }
  4499. }
  4500. //try to set key container ACL with owner ACE only (NOTE: only do this for creation!)
  4501. hr = SetKeyContainerSecurity(hProv, m_keyProvInfo.dwFlags);
  4502. #if DBG
  4503. if (S_OK != hr)
  4504. {
  4505. goto SetKeyContainerSecurityError;
  4506. }
  4507. #endif //DBG
  4508. hr = S_OK; //free build, no error checking here, if fails, live with it
  4509. }
  4510. if (NULL != hKey)
  4511. {
  4512. // don't need the hKey on existing key, so get rid of it
  4513. CryptDestroyKey(hKey);
  4514. }
  4515. if ((NULL == m_PrivateKeyArchiveCertificate || !m_fNewRequestMethod) &&
  4516. NULL != m_hCachedKey)
  4517. {
  4518. //we don't need cache it, destroy it as soon as key is gen(ed)
  4519. CryptDestroyKey(m_hCachedKey);
  4520. m_hCachedKey = NULL;
  4521. }
  4522. // now get the public key out into m_pPublicKeyInfo
  4523. // m_pPublicKeyInfo is internal use for cache
  4524. if (NULL != m_pPublicKeyInfo)
  4525. {
  4526. LocalFree(m_pPublicKeyInfo);
  4527. m_pPublicKeyInfo = NULL;
  4528. }
  4529. while (TRUE)
  4530. {
  4531. if(!CryptExportPublicKeyInfo(hProv,
  4532. m_keyProvInfo.dwKeySpec,
  4533. X509_ASN_ENCODING,
  4534. m_pPublicKeyInfo,
  4535. &cPublicKeyInfo))
  4536. {
  4537. goto ErrorCryptExportPublicKeyInfo;
  4538. }
  4539. if (NULL != m_pPublicKeyInfo)
  4540. {
  4541. break;
  4542. }
  4543. m_pPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)LocalAlloc(
  4544. LMEM_FIXED, cPublicKeyInfo);
  4545. if (NULL == m_pPublicKeyInfo)
  4546. {
  4547. hr = E_OUTOFMEMORY;
  4548. goto OutOfMemoryError;
  4549. }
  4550. }
  4551. reqInfo.SubjectPublicKeyInfo = *m_pPublicKeyInfo;
  4552. // get the Subject DN only if one is specified
  4553. reqInfo.Subject.pbData = NULL;
  4554. while (TRUE)
  4555. {
  4556. if( !MyCertStrToNameW(
  4557. CRYPT_ASN_ENCODING,
  4558. DNName,
  4559. 0 | m_dwT61DNEncoding,
  4560. NULL,
  4561. reqInfo.Subject.pbData,
  4562. &reqInfo.Subject.cbData,
  4563. NULL))
  4564. {
  4565. if (CRYPT_E_INVALID_X500_STRING == GetLastError() &&
  4566. L'\0' == DNName[0])
  4567. {
  4568. //this is likely on W95, W98, or NT4 with some IEs
  4569. //crypt32 doesn't support empty DN conversion
  4570. //hard code here
  4571. reqInfo.Subject.cbData = 2;
  4572. reqInfo.Subject.pbData = (BYTE *)LocalAlloc(LMEM_FIXED,
  4573. reqInfo.Subject.cbData);
  4574. if (NULL == reqInfo.Subject.pbData)
  4575. {
  4576. hr = E_OUTOFMEMORY;
  4577. goto OutOfMemoryError;
  4578. }
  4579. reqInfo.Subject.pbData[0] = 0x30;
  4580. reqInfo.Subject.pbData[1] = 0x0;
  4581. //done
  4582. break;
  4583. }
  4584. else
  4585. {
  4586. goto ErrorCertStrToNameW;
  4587. }
  4588. }
  4589. if (NULL != reqInfo.Subject.pbData)
  4590. {
  4591. break;
  4592. }
  4593. reqInfo.Subject.pbData = (BYTE *)LocalAlloc(LMEM_FIXED,
  4594. reqInfo.Subject.cbData);
  4595. if (NULL == reqInfo.Subject.pbData)
  4596. {
  4597. hr = E_OUTOFMEMORY;
  4598. goto OutOfMemoryError;
  4599. }
  4600. }
  4601. // allocate room for the extensions
  4602. cb = (CountStackExtension(m_fNewRequestMethod) + EndExt) * sizeof(CERT_EXTENSION);
  4603. rgExtension = (PCERT_EXTENSION)LocalAlloc(LMEM_FIXED, cb);
  4604. if (NULL == rgExtension)
  4605. {
  4606. hr = E_OUTOFMEMORY;
  4607. goto OutOfMemoryError;
  4608. }
  4609. memset(rgExtension, 0, cb);
  4610. cb = 0;
  4611. if (!m_fUseClientKeyUsage)
  4612. {
  4613. // Make Key Usage
  4614. rgExtension[iExt].pszObjId = szOID_KEY_USAGE;
  4615. rgExtension[iExt].fCritical = TRUE;
  4616. // AT_SIGNATURE
  4617. if( m_keyProvInfo.dwKeySpec == AT_SIGNATURE)
  4618. bKeyUsage =
  4619. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  4620. CERT_NON_REPUDIATION_KEY_USAGE;
  4621. //AT_KEYEXCHANGE, limited for EMAIL single use
  4622. // email may not work if signature is present
  4623. else if(m_fLimitExchangeKeyToEncipherment)
  4624. bKeyUsage =
  4625. CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  4626. CERT_DATA_ENCIPHERMENT_KEY_USAGE;
  4627. // AT_KEYEXCHANGE and AT_SIGNATURE dual key
  4628. // This is the normal case for AT_KEYEXCHANGE since CAPI will sign with this.
  4629. else
  4630. bKeyUsage =
  4631. CERT_KEY_ENCIPHERMENT_KEY_USAGE |
  4632. CERT_DATA_ENCIPHERMENT_KEY_USAGE |
  4633. CERT_DIGITAL_SIGNATURE_KEY_USAGE |
  4634. CERT_NON_REPUDIATION_KEY_USAGE;
  4635. bbKeyUsage.pbData = &bKeyUsage;
  4636. bbKeyUsage.cbData = 1;
  4637. bbKeyUsage.cUnusedBits = 1;
  4638. // encode the usage
  4639. rgExtension[iExt].Value.pbData = NULL;
  4640. while (TRUE)
  4641. {
  4642. if(!CryptEncodeObject(
  4643. CRYPT_ASN_ENCODING,
  4644. X509_KEY_USAGE,
  4645. &bbKeyUsage,
  4646. pbKU,
  4647. &rgExtension[iExt].Value.cbData))
  4648. {
  4649. goto ErrorEncodeKeyUsage;
  4650. }
  4651. if (NULL != pbKU)
  4652. {
  4653. rgExtension[iExt].Value.pbData = pbKU;
  4654. //done
  4655. break;
  4656. }
  4657. pbKU = (BYTE *)LocalAlloc(LMEM_FIXED, rgExtension[iExt].Value.cbData);
  4658. if (NULL == pbKU)
  4659. {
  4660. hr = E_OUTOFMEMORY;
  4661. goto OutOfMemoryError;
  4662. }
  4663. }
  4664. iExt++;
  4665. }
  4666. if(m_fEnableSMIMECapabilities)
  4667. {
  4668. // add SMIME extension for symmetric algorithms
  4669. rgExtension[iExt].pszObjId = szOID_RSA_SMIMECapabilities;
  4670. rgExtension[iExt].fCritical = FALSE;
  4671. hr = CreateSMimeExtension(
  4672. hProv,
  4673. &pbSMime,
  4674. &rgExtension[iExt].Value.cbData);
  4675. if (S_OK != hr)
  4676. {
  4677. goto CreateSMimeExtensionError;
  4678. }
  4679. rgExtension[iExt].Value.pbData = pbSMime;
  4680. iExt++;
  4681. }
  4682. if (m_fHonorIncludeSubjectKeyID && m_fIncludeSubjectKeyID)
  4683. {
  4684. hr = myCreateSubjectKeyIdentifierExtension(
  4685. m_pPublicKeyInfo,
  4686. &pbSubjectKeyHashExtension,
  4687. &cbSubjectKeyHashExtension);
  4688. if (S_OK != hr)
  4689. {
  4690. goto myCreateSubjectKeyIdentifierExtensionError;
  4691. }
  4692. //add subject key ID hash extension into PKCS10
  4693. rgExtension[iExt].pszObjId = szOID_SUBJECT_KEY_IDENTIFIER;
  4694. rgExtension[iExt].fCritical = FALSE;
  4695. rgExtension[iExt].Value.pbData = pbSubjectKeyHashExtension;
  4696. rgExtension[iExt].Value.cbData = cbSubjectKeyHashExtension;
  4697. iExt++;
  4698. }
  4699. if(wszPurpose != NULL) {
  4700. cb = 0;
  4701. while (TRUE)
  4702. {
  4703. if(0 == (cb = WideCharToMultiByte(
  4704. 0, 0, wszPurpose, -1, pszPurpose, cb, NULL, NULL)))
  4705. {
  4706. SetLastError(ERROR_OUTOFMEMORY);
  4707. goto ErrorCantConvertPurpose;
  4708. }
  4709. if (NULL != pszPurpose)
  4710. {
  4711. break;
  4712. }
  4713. pszPurpose = (CHAR*)LocalAlloc(LMEM_FIXED, cb);
  4714. if (NULL == pszPurpose)
  4715. {
  4716. hr = E_OUTOFMEMORY;
  4717. goto OutOfMemoryError;
  4718. }
  4719. }
  4720. szStart = pszPurpose;
  4721. // remove leading blanks
  4722. while(*szStart == ',' || *szStart == ' ')
  4723. *szStart++ = '\0';
  4724. while( szStart[0] != '\0' ) {
  4725. // find the next string
  4726. szEnd = szStart;
  4727. while(*szEnd != ',' && *szEnd != ' ' && *szEnd != '\0')
  4728. szEnd++;
  4729. // remove trailing blanks
  4730. while(*szEnd == ',' || *szEnd == ' ')
  4731. *szEnd++ = '\0';
  4732. enhKeyUsage.cUsageIdentifier++;
  4733. // see if this implies codesigning
  4734. fAddCodeSign |= !strcmp(szStart, SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID) ||
  4735. !strcmp(szStart, SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID);
  4736. // go to next string
  4737. szStart = szEnd;
  4738. }
  4739. // count the codesign EKU once
  4740. cPassedEKU = enhKeyUsage.cUsageIdentifier;
  4741. if(fAddCodeSign)
  4742. enhKeyUsage.cUsageIdentifier++;
  4743. // encode the extension
  4744. if(enhKeyUsage.cUsageIdentifier != 0) {
  4745. // allocate the EKU array
  4746. enhKeyUsage.rgpszUsageIdentifier = (LPSTR *)LocalAlloc(LMEM_FIXED,
  4747. enhKeyUsage.cUsageIdentifier * sizeof(LPSTR));
  4748. if (NULL == enhKeyUsage.rgpszUsageIdentifier)
  4749. {
  4750. hr = E_OUTOFMEMORY;
  4751. goto OutOfMemoryError;
  4752. }
  4753. // add the EKU's
  4754. szStart = pszPurpose;
  4755. for(i=0; i<cPassedEKU; i++) {
  4756. while(*szStart == '\0')
  4757. szStart++;
  4758. enhKeyUsage.rgpszUsageIdentifier[i] = szStart;
  4759. while(*szStart != '\0')
  4760. szStart++;
  4761. }
  4762. // add the code sign EKU
  4763. if(fAddCodeSign)
  4764. enhKeyUsage.rgpszUsageIdentifier[enhKeyUsage.cUsageIdentifier - 1] = szOID_PKIX_KP_CODE_SIGNING;
  4765. // Deal with the policy, or purpose
  4766. rgExtension[iExt].pszObjId = szOID_ENHANCED_KEY_USAGE ;
  4767. rgExtension[iExt].fCritical = FALSE;
  4768. // encode the enhanced key usage
  4769. rgExtension[iExt].Value.cbData = 0;
  4770. while (TRUE)
  4771. {
  4772. if(!CryptEncodeObject(
  4773. CRYPT_ASN_ENCODING, X509_ENHANCED_KEY_USAGE,
  4774. &enhKeyUsage,
  4775. pbEKU, // pbEncoded
  4776. &rgExtension[iExt].Value.cbData))
  4777. {
  4778. goto ErrorEncodeEnhKeyUsage;
  4779. }
  4780. if (NULL != pbEKU)
  4781. {
  4782. //got it, done
  4783. rgExtension[iExt].Value.pbData = pbEKU;
  4784. break;
  4785. }
  4786. pbEKU = (BYTE *)LocalAlloc(LMEM_FIXED,
  4787. rgExtension[iExt].Value.cbData);
  4788. if (NULL == pbEKU)
  4789. {
  4790. hr = E_OUTOFMEMORY;
  4791. goto OutOfMemoryError;
  4792. }
  4793. }
  4794. iExt++;
  4795. }
  4796. }
  4797. assert(EndExt >= iExt);
  4798. // now add all of the user defined extensions
  4799. pExtCur = NULL;
  4800. while(NULL != (pExtCur = EnumStackExtension(pExtCur, m_fNewRequestMethod)) ) {
  4801. rgExtension[iExt] = *pExtCur;
  4802. iExt++;
  4803. }
  4804. // fill in the extensions structure
  4805. Extensions.cExtension = iExt;
  4806. Extensions.rgExtension = rgExtension;
  4807. // encode the extensions
  4808. reqInfo.cAttribute = 0;
  4809. reqInfo.rgAttribute = rgAttribute;
  4810. while (TRUE)
  4811. {
  4812. if(!CryptEncodeObject(
  4813. CRYPT_ASN_ENCODING, X509_EXTENSIONS,
  4814. &Extensions,
  4815. blobExt.pbData, // pbEncoded
  4816. &blobExt.cbData))
  4817. {
  4818. goto ErrorEncodeExtensions;
  4819. }
  4820. if (NULL != blobExt.pbData)
  4821. {
  4822. //got it, done
  4823. break;
  4824. }
  4825. blobExt.pbData = (BYTE *)LocalAlloc(LMEM_FIXED, blobExt.cbData);
  4826. if (NULL == blobExt.pbData)
  4827. {
  4828. hr = E_OUTOFMEMORY;
  4829. goto OutOfMemoryError;
  4830. }
  4831. }
  4832. if (m_fOID_V2)
  4833. {
  4834. //use new rsa oid
  4835. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_RSA_certExtensions;
  4836. }
  4837. else
  4838. {
  4839. //use microsoft oid for w2k clients
  4840. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_CERT_EXTENSIONS;
  4841. }
  4842. rgAttribute[reqInfo.cAttribute].cValue = 1;
  4843. rgAttribute[reqInfo.cAttribute].rgValue = &blobExt;
  4844. // put in the CSP attribute
  4845. if( !GetSignatureFromHPROV(
  4846. hProv,
  4847. &CSPProvider.Signature.pbData,
  4848. &CSPProvider.Signature.cbData
  4849. ) )
  4850. goto ErrorGetSignatureFromHPROV;
  4851. CSPProvider.pwszProviderName = m_keyProvInfo.pwszProvName;
  4852. CSPProvider.dwKeySpec = m_keyProvInfo.dwKeySpec;
  4853. while (TRUE)
  4854. {
  4855. if( !CryptEncodeObject(
  4856. CRYPT_ASN_ENCODING,
  4857. szOID_ENROLLMENT_CSP_PROVIDER,
  4858. &CSPProvider,
  4859. blobCSPAttr.pbData, // pbEncoded
  4860. &blobCSPAttr.cbData))
  4861. {
  4862. goto ErrorEncodeCSPAttr;
  4863. }
  4864. if (NULL != blobCSPAttr.pbData)
  4865. {
  4866. //got it, done
  4867. break;
  4868. }
  4869. blobCSPAttr.pbData = (BYTE *)LocalAlloc(LMEM_FIXED, blobCSPAttr.cbData);
  4870. if (NULL == blobCSPAttr.pbData)
  4871. {
  4872. hr = E_OUTOFMEMORY;
  4873. goto OutOfMemoryError;
  4874. }
  4875. }
  4876. reqInfo.cAttribute++;
  4877. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_ENROLLMENT_CSP_PROVIDER;
  4878. rgAttribute[reqInfo.cAttribute].cValue = 1;
  4879. rgAttribute[reqInfo.cAttribute].rgValue = &blobCSPAttr;
  4880. // get the OSVersion
  4881. osvInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  4882. if(!GetVersionExA(&osvInfo))
  4883. goto ErrorGetVersionEx;
  4884. wsprintfA(szVersion, "%d.%d.%d.%d",
  4885. osvInfo.dwMajorVersion,
  4886. osvInfo.dwMinorVersion,
  4887. osvInfo.dwBuildNumber,
  4888. osvInfo.dwPlatformId);
  4889. cnvOSVer.dwValueType = CERT_RDN_IA5_STRING;
  4890. cnvOSVer.Value.cbData = (DWORD)strlen(szVersion);
  4891. cnvOSVer.Value.pbData = (BYTE *) szVersion;
  4892. while (TRUE)
  4893. {
  4894. if(!CryptEncodeObject(
  4895. CRYPT_ASN_ENCODING,
  4896. X509_ANY_STRING,
  4897. &cnvOSVer,
  4898. blobOSVAttr.pbData, // pbEncoded
  4899. &blobOSVAttr.cbData))
  4900. {
  4901. goto ErrorEncodeOSVAttr;
  4902. }
  4903. if (NULL != blobOSVAttr.pbData)
  4904. {
  4905. //got it, done
  4906. break;
  4907. }
  4908. blobOSVAttr.pbData = (BYTE *)LocalAlloc(LMEM_FIXED, blobOSVAttr.cbData);
  4909. if (NULL == blobOSVAttr.pbData)
  4910. {
  4911. hr = E_OUTOFMEMORY;
  4912. goto OutOfMemoryError;
  4913. }
  4914. }
  4915. reqInfo.cAttribute++;
  4916. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_OS_VERSION;
  4917. rgAttribute[reqInfo.cAttribute].cValue = 1;
  4918. rgAttribute[reqInfo.cAttribute].rgValue = &blobOSVAttr;
  4919. // put in the renewal cert if present
  4920. if(m_pCertContextRenewal != NULL && m_fHonorRenew) {
  4921. reqInfo.cAttribute++;
  4922. blobRenewAttr.pbData = m_pCertContextRenewal->pbCertEncoded;
  4923. blobRenewAttr.cbData = m_pCertContextRenewal->cbCertEncoded;
  4924. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_RENEWAL_CERTIFICATE;
  4925. rgAttribute[reqInfo.cAttribute].cValue = 1;
  4926. rgAttribute[reqInfo.cAttribute].rgValue = &blobRenewAttr;
  4927. }
  4928. if (m_fNewRequestMethod && XECI_DISABLE != m_lClientId)
  4929. {
  4930. //put client id as attribute
  4931. hr = myEncodeRequestClientAttributeFromClientId(
  4932. m_lClientId,
  4933. &blobClientId.pbData,
  4934. &blobClientId.cbData);
  4935. if (S_OK != hr)
  4936. {
  4937. //for any reasons, don't include client ID
  4938. hr = put_ClientId(XECI_DISABLE);
  4939. if (S_OK != hr)
  4940. {
  4941. goto putClientIdError;
  4942. }
  4943. }
  4944. else
  4945. {
  4946. reqInfo.cAttribute++;
  4947. rgAttribute[reqInfo.cAttribute].pszObjId = szOID_REQUEST_CLIENT_INFO;
  4948. rgAttribute[reqInfo.cAttribute].cValue = 1;
  4949. rgAttribute[reqInfo.cAttribute].rgValue = &blobClientId;
  4950. }
  4951. }
  4952. // NOTE: On error we always return BAD ALGID
  4953. // this is because sometimes we get an no more data enum error
  4954. // that doesn't help.
  4955. // get the signature oid
  4956. if( !GetCapiHashAndSigAlgId(rgAlg) ) {
  4957. SetLastError((DWORD)NTE_BAD_ALGID);
  4958. goto ErrorGetCapiHashAndSigAlgId;
  4959. }
  4960. // Convert to an oid
  4961. if( (NULL == (pOidInfo = xeCryptFindOIDInfo(
  4962. CRYPT_OID_INFO_SIGN_KEY,
  4963. (void *) rgAlg,
  4964. CRYPT_SIGN_ALG_OID_GROUP_ID)) ) ) {
  4965. SetLastError((DWORD)NTE_BAD_ALGID);
  4966. goto ErrorCryptFindOIDInfo;
  4967. }
  4968. // we always know we have at least 1 attribute, and we have been zero based, now go to 1 based.
  4969. reqInfo.cAttribute++;
  4970. SignatureInfo.SignatureAlgorithm.pszObjId = (char *) pOidInfo->pszOID;
  4971. #if DBG
  4972. //SignatureInfo.ToBeSigned.pbData should be null at the first
  4973. assert(NULL == SignatureInfo.ToBeSigned.pbData);
  4974. #endif
  4975. // encode PKCS10
  4976. while (TRUE)
  4977. {
  4978. if(!CryptEncodeObject(
  4979. CRYPT_ASN_ENCODING, X509_CERT_REQUEST_TO_BE_SIGNED,
  4980. &reqInfo,
  4981. SignatureInfo.ToBeSigned.pbData, // pbEncoded
  4982. &SignatureInfo.ToBeSigned.cbData))
  4983. {
  4984. goto ErrorEncodePKCS10ToBeSigned;
  4985. }
  4986. if (NULL != SignatureInfo.ToBeSigned.pbData)
  4987. {
  4988. //done
  4989. break;
  4990. }
  4991. SignatureInfo.ToBeSigned.pbData = (BYTE *)
  4992. LocalAlloc(LMEM_FIXED, SignatureInfo.ToBeSigned.cbData);
  4993. if (NULL == SignatureInfo.ToBeSigned.pbData)
  4994. {
  4995. hr = E_OUTOFMEMORY;
  4996. goto OutOfMemoryError;
  4997. }
  4998. }
  4999. // create the signature Info
  5000. // Don't care if xchange or signature key in dwkeySpec because
  5001. // we are signing with the key that is in the PKCS10
  5002. #if DBG
  5003. assert(NULL == SignatureInfo.Signature.pbData);
  5004. #endif
  5005. while (TRUE)
  5006. {
  5007. if(!CryptSignCertificate(
  5008. hProv,
  5009. m_keyProvInfo.dwKeySpec,
  5010. CRYPT_ASN_ENCODING,
  5011. SignatureInfo.ToBeSigned.pbData,
  5012. SignatureInfo.ToBeSigned.cbData,
  5013. &SignatureInfo.SignatureAlgorithm,
  5014. NULL, // reserved
  5015. SignatureInfo.Signature.pbData, // pbSignature
  5016. &SignatureInfo.Signature.cbData))
  5017. {
  5018. goto ErrorCryptSignCertificatePKCS10;
  5019. }
  5020. if (NULL != SignatureInfo.Signature.pbData)
  5021. {
  5022. //done
  5023. break;
  5024. }
  5025. SignatureInfo.Signature.pbData = (BYTE *)
  5026. LocalAlloc(LMEM_FIXED, SignatureInfo.Signature.cbData);
  5027. if (NULL == SignatureInfo.Signature.pbData)
  5028. {
  5029. hr = E_OUTOFMEMORY;
  5030. goto OutOfMemoryError;
  5031. }
  5032. }
  5033. // encode the final signed request
  5034. if( !CryptEncodeObject(
  5035. CRYPT_ASN_ENCODING,
  5036. X509_CERT,
  5037. &SignatureInfo,
  5038. NULL,
  5039. &pPkcs10Blob->cbData
  5040. ) ||
  5041. (pPkcs10Blob->pbData = (BYTE *)
  5042. MyCoTaskMemAlloc(pPkcs10Blob->cbData)) == NULL ||
  5043. !CryptEncodeObject(
  5044. CRYPT_ASN_ENCODING,
  5045. X509_CERT,
  5046. &SignatureInfo,
  5047. pPkcs10Blob->pbData,
  5048. &pPkcs10Blob->cbData
  5049. ) ) {
  5050. goto ErrorEncodePKCS10Request;
  5051. }
  5052. // go ahead and make the pkcs 7
  5053. if((m_pCertContextRenewal != NULL ||
  5054. m_pCertContextSigner != NULL) &&
  5055. m_fHonorRenew &&
  5056. !m_fCMCFormat) //if CMC, don't make pkcs7
  5057. {
  5058. // create a pkcs7 signed by the old cert
  5059. if(S_OK != CreatePKCS7RequestFromRequest(
  5060. pPkcs10Blob,
  5061. (NULL != m_pCertContextRenewal) ? m_pCertContextRenewal :
  5062. m_pCertContextSigner,
  5063. &blobPKCS7) )
  5064. goto ErrorCreatePKCS7RARequestFromPKCS10;
  5065. assert(pPkcs10Blob->pbData != NULL);
  5066. MyCoTaskMemFree(pPkcs10Blob->pbData);
  5067. *pPkcs10Blob = blobPKCS7;
  5068. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  5069. }
  5070. ssFlags = CERT_CREATE_SELFSIGN_NO_SIGN;
  5071. if(m_wszPVKFileName[0] != 0)
  5072. ssFlags |= CERT_CREATE_SELFSIGN_NO_KEY_INFO;
  5073. // Get the cert extensions we wish to add to the certificate.
  5074. // Search for the extensions we need.
  5075. {
  5076. PCERT_EXTENSION pCertExtCertTypeName = NULL;
  5077. while(NULL != (pCertExtCertTypeName = EnumStackExtension(pCertExtCertTypeName, m_fNewRequestMethod)) ) {
  5078. for (DWORD dTmp = 0; dTmp < sizeof(rgszExtensionOIDs) / sizeof(LPSTR); dTmp++) {
  5079. if (0 == strcmp(rgszExtensionOIDs[dTmp], pCertExtCertTypeName->pszObjId))
  5080. rgNeededExtensions[(ceExtensions.cExtension)++] = *pCertExtCertTypeName;
  5081. }
  5082. }
  5083. // Even if we didn't find all of the extensions we wanted, continue ...
  5084. }
  5085. assert(pCertContext == NULL);
  5086. pCertContext = MyCertCreateSelfSignCertificate(
  5087. hProv,
  5088. &reqInfo.Subject,
  5089. ssFlags,
  5090. &m_keyProvInfo,
  5091. NULL,
  5092. NULL,
  5093. NULL,
  5094. (ceExtensions.cExtension > 0) ? &ceExtensions : NULL
  5095. );
  5096. if (NULL == pCertContext)
  5097. goto ErrorCertCreateSelfSignCertificate;
  5098. // now put the pass thru data on the cert
  5099. requestFlags.fWriteToCSP = (m_fWriteCertToCSP != 0);
  5100. requestFlags.fWriteToDS = (m_fWriteCertToUserDS != 0);
  5101. requestFlags.openFlags = m_RequestStore.dwFlags;
  5102. #if DBG
  5103. assert(NULL == requestInfoBlob.pbData);
  5104. #endif
  5105. while (TRUE)
  5106. {
  5107. if(!CryptEncodeObject(
  5108. CRYPT_ASN_ENCODING,
  5109. XENROLL_REQUEST_INFO,
  5110. &requestFlags,
  5111. requestInfoBlob.pbData,
  5112. &requestInfoBlob.cbData))
  5113. {
  5114. goto ErrorEncodeRequestInfoBlob;
  5115. }
  5116. if (NULL != requestInfoBlob.pbData)
  5117. {
  5118. //done
  5119. break;
  5120. }
  5121. requestInfoBlob.pbData = (BYTE *)LocalAlloc(LMEM_FIXED, requestInfoBlob.cbData);
  5122. if (NULL == requestInfoBlob.pbData)
  5123. {
  5124. hr = E_OUTOFMEMORY;
  5125. goto OutOfMemoryError;
  5126. }
  5127. }
  5128. // set the property on the dummy request cert.
  5129. if( !CertSetCertificateContextProperty(
  5130. pCertContext,
  5131. XENROLL_PASS_THRU_PROP_ID,
  5132. 0,
  5133. &requestInfoBlob) )
  5134. goto ErrorCertSetCertificateContextProperty;
  5135. if(m_pCertContextRenewal != NULL && m_fHonorRenew) {
  5136. blobRenewalCert.pbData = m_pCertContextRenewal->pbCertEncoded;
  5137. blobRenewalCert.cbData = m_pCertContextRenewal->cbCertEncoded;
  5138. // set the renewal property if any
  5139. if( !CertSetCertificateContextProperty(
  5140. pCertContext,
  5141. XENROLL_RENEWAL_CERTIFICATE_PROP_ID,
  5142. 0,
  5143. &blobRenewalCert) )
  5144. goto ErrorCertSetCertificateContextProperty;
  5145. }
  5146. // save the private key away if needed
  5147. if(m_wszPVKFileName[0] != 0) {
  5148. // open the PVK File
  5149. if( (hFile = CreateOpenFileSafely2(m_wszPVKFileName, IDS_PVK_C, IDS_PVK_O)) == NULL )
  5150. goto ErrorCreatePVKFile;
  5151. assert(m_keyProvInfo.dwKeySpec == AT_SIGNATURE || m_keyProvInfo.dwKeySpec == AT_KEYEXCHANGE);
  5152. // write out the private key
  5153. if( !PrivateKeySave(
  5154. hProv,
  5155. hFile,
  5156. m_keyProvInfo.dwKeySpec,
  5157. NULL,
  5158. m_wszPVKFileName,
  5159. 0
  5160. ) ) {
  5161. goto ErrorPrivateKeySave;
  5162. }
  5163. // put a different kind of propery in the store that just points to the pvk file
  5164. keyProvInfoT = m_keyProvInfo;
  5165. keyProvInfoT.pwszContainerName = m_wszPVKFileName;
  5166. if( !CreatePvkProperty(&keyProvInfoT, &blobData) )
  5167. goto ErrorCreatePvkProperty;
  5168. // This is really not needed, it is only nice for other tools
  5169. // like makecert or signcode to be able to look at a cert without
  5170. // specifying a .PVK file if the cert points to the .pvk file.
  5171. // So we don't care if this actually fail, which it will on Auth2 and
  5172. // SP3 Crypt32.dll since Phil was so kind as to not allow any unknown property
  5173. // to be set on the cert --- BAD PHIL!
  5174. CertSetCertificateContextProperty(
  5175. pCertContext,
  5176. CERT_PVK_FILE_PROP_ID,
  5177. 0,
  5178. &blobData);
  5179. // only delete the keyset if the key was not pre-existing
  5180. // this is if we write it out to a PVK file only
  5181. // This is safe for scripting since we just generated this and we are putting it to
  5182. // a pvk file. We really aren't deleting the key.
  5183. if (!m_fNewRequestMethod)
  5184. {
  5185. //keep old behavior for createPKCS10 call
  5186. if(!m_fUseExistingKey)
  5187. GetProv(CRYPT_DELETEKEYSET);
  5188. }
  5189. }
  5190. //set all properties from the caller
  5191. pProp = EnumStackProperty(NULL);
  5192. while (NULL != pProp)
  5193. {
  5194. //goto request cert
  5195. if (!CertSetCertificateContextProperty(
  5196. pCertContext,
  5197. pProp->lPropId,
  5198. 0,
  5199. &pProp->prop))
  5200. {
  5201. goto ErrorCertSetCertificateContextProperty;
  5202. }
  5203. pProp = EnumStackProperty(pProp);
  5204. }
  5205. // open the request cert store
  5206. if( (hStore = GetStore(StoreREQUEST)) == NULL)
  5207. goto ErrorCertOpenRequestStore;
  5208. //if old pending request exists, free it first
  5209. fRet = CertFreeCertificateContext(m_pCertContextPendingRequest);
  5210. #if DBG
  5211. assert(fRet);
  5212. #endif //DBG
  5213. m_pCertContextPendingRequest = NULL;
  5214. // save the temp cert
  5215. if( !MySafeCertAddCertificateContextToStore(
  5216. hStore,
  5217. pCertContext,
  5218. CERT_STORE_ADD_NEW,
  5219. &m_pCertContextPendingRequest,
  5220. m_dwEnabledSafteyOptions) ) {
  5221. goto ErrorCertAddToRequestStore;
  5222. }
  5223. // Remove the cached HASH.
  5224. if (m_hashBlobPendingRequest.pbData != NULL)
  5225. {
  5226. LocalFree(m_hashBlobPendingRequest.pbData);
  5227. m_hashBlobPendingRequest.pbData = NULL;
  5228. }
  5229. CommonReturn:
  5230. if(pCertContext != NULL)
  5231. CertFreeCertificateContext(pCertContext);
  5232. if(hFile != NULL)
  5233. CloseHandle(hFile);
  5234. if(blobData.pbData != NULL)
  5235. MyCoTaskMemFree(blobData.pbData);
  5236. if(blobPKCS7.pbData != NULL)
  5237. MyCoTaskMemFree(blobPKCS7.pbData);
  5238. if(CSPProvider.Signature.pbData)
  5239. LocalFree(CSPProvider.Signature.pbData);
  5240. if (NULL != pbSMime)
  5241. {
  5242. LocalFree(pbSMime);
  5243. }
  5244. if (NULL != reqInfo.Subject.pbData)
  5245. {
  5246. LocalFree(reqInfo.Subject.pbData);
  5247. }
  5248. if (NULL != rgExtension)
  5249. {
  5250. LocalFree(rgExtension);
  5251. }
  5252. if (NULL != pbKU)
  5253. {
  5254. LocalFree(pbKU);
  5255. }
  5256. if (NULL != pbEKU)
  5257. {
  5258. LocalFree(pbEKU);
  5259. }
  5260. if (NULL != pszPurpose)
  5261. {
  5262. LocalFree(pszPurpose);
  5263. }
  5264. if (NULL != enhKeyUsage.rgpszUsageIdentifier)
  5265. {
  5266. LocalFree(enhKeyUsage.rgpszUsageIdentifier);
  5267. }
  5268. if (NULL != blobExt.pbData)
  5269. {
  5270. LocalFree(blobExt.pbData);
  5271. }
  5272. if (NULL != blobCSPAttr.pbData)
  5273. {
  5274. LocalFree(blobCSPAttr.pbData);
  5275. }
  5276. if (NULL != blobOSVAttr.pbData)
  5277. {
  5278. LocalFree(blobOSVAttr.pbData);
  5279. }
  5280. if (NULL != SignatureInfo.ToBeSigned.pbData)
  5281. {
  5282. LocalFree(SignatureInfo.ToBeSigned.pbData);
  5283. }
  5284. if (NULL != SignatureInfo.Signature.pbData)
  5285. {
  5286. LocalFree(SignatureInfo.Signature.pbData);
  5287. }
  5288. if (NULL != requestInfoBlob.pbData)
  5289. {
  5290. LocalFree(requestInfoBlob.pbData);
  5291. }
  5292. if (NULL != blobClientId.pbData)
  5293. {
  5294. LocalFree(blobClientId.pbData);
  5295. }
  5296. if (NULL != pbSubjectKeyHashExtension)
  5297. {
  5298. LocalFree(pbSubjectKeyHashExtension);
  5299. }
  5300. if (NULL != pwszNotSafeRequesting)
  5301. {
  5302. LocalFree(pwszNotSafeRequesting);
  5303. }
  5304. if (NULL != pwszTitle)
  5305. {
  5306. LocalFree(pwszTitle);
  5307. }
  5308. // don't know if we have an error or not
  5309. // but I do know the errBefore is set properly
  5310. SetLastError(errBefore);
  5311. LeaveCriticalSection(&m_csXEnroll);
  5312. return(hr);
  5313. ErrorReturn:
  5314. if(GetLastError() == ERROR_SUCCESS)
  5315. SetLastError((DWORD)E_UNEXPECTED);
  5316. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5317. // We have an error, make sure we set it.
  5318. errBefore = GetLastError();
  5319. // on error return a NULL
  5320. if(pPkcs10Blob->pbData != NULL)
  5321. MyCoTaskMemFree(pPkcs10Blob->pbData);
  5322. memset(pPkcs10Blob, 0, sizeof(CRYPT_DATA_BLOB));
  5323. goto CommonReturn;
  5324. TRACE_ERROR(ErrorGetSignatureFromHPROV);
  5325. TRACE_ERROR(ErrorEncodeCSPAttr);
  5326. TRACE_ERROR(ErrorCertSetCertificateContextProperty);
  5327. TRACE_ERROR(ErrorCryptAcquireContext);
  5328. TRACE_ERROR(ErrorCryptGenKey);
  5329. TRACE_ERROR(ErrorCryptExportPublicKeyInfo);
  5330. TRACE_ERROR(ErrorCertStrToNameW);
  5331. TRACE_ERROR(ErrorEncodeKeyUsage);
  5332. TRACE_ERROR(ErrorEncodeEnhKeyUsage);
  5333. TRACE_ERROR(ErrorEncodeExtensions);
  5334. TRACE_ERROR(ErrorEncodePKCS10ToBeSigned);
  5335. TRACE_ERROR(ErrorCryptSignCertificatePKCS10);
  5336. TRACE_ERROR(ErrorEncodePKCS10Request);
  5337. TRACE_ERROR(ErrorCantConvertPurpose);
  5338. TRACE_ERROR(ErrorCertOpenRequestStore);
  5339. TRACE_ERROR(ErrorCertAddToRequestStore);
  5340. TRACE_ERROR(ErrorCreatePVKFile);
  5341. TRACE_ERROR(ErrorPrivateKeySave);
  5342. TRACE_ERROR(ErrorCreatePvkProperty);
  5343. TRACE_ERROR(ErrorCertCreateSelfSignCertificate);
  5344. TRACE_ERROR(ErrorEncodeRequestInfoBlob);
  5345. TRACE_ERROR(ErrorCreatePKCS7RARequestFromPKCS10);
  5346. TRACE_ERROR(ErrorGetCapiHashAndSigAlgId);
  5347. TRACE_ERROR(ErrorCryptFindOIDInfo);
  5348. TRACE_ERROR(ErrorEncodeOSVAttr);
  5349. TRACE_ERROR(ErrorGetVersionEx);
  5350. TRACE_ERROR(CancelledError);
  5351. TRACE_ERROR(CreateSMimeExtensionError);
  5352. TRACE_ERROR(OutOfMemoryError);
  5353. TRACE_ERROR(putClientIdError);
  5354. TRACE_ERROR(myCreateSubjectKeyIdentifierExtensionError)
  5355. TRACE_ERROR(xeLoadRCStringError);
  5356. TRACE_ERROR(CryptGetUserKeyCancelError)
  5357. #if DBG
  5358. TRACE_ERROR(SetKeyContainerSecurityError)
  5359. #endif //DBG
  5360. }
  5361. HRESULT STDMETHODCALLTYPE CCEnroll::acceptPKCS7Blob(
  5362. /* [in] */ PCRYPT_DATA_BLOB pBlobPKCS7) {
  5363. HRESULT hr;
  5364. HRESULT hr2 = S_OK;
  5365. LONG dwKeySpec = 0;
  5366. PCCERT_CONTEXT pCertContextMy = NULL;
  5367. PCCERT_CONTEXT pCertContextRequest = NULL;
  5368. PCCERT_CONTEXT pCertContextEnd = NULL;
  5369. HANDLE hFile = NULL;
  5370. DWORD cb = 0;
  5371. HCRYPTPROV hProv = NULL;
  5372. HCRYPTKEY hKey = NULL;
  5373. HCERTSTORE hStoreDS = NULL;
  5374. HCERTSTORE hStoreRequest = NULL;
  5375. HCERTSTORE hStoreMy = NULL;
  5376. LPWSTR pwszTitle = NULL;
  5377. LPWSTR pwszNotSafeAccepting = NULL;
  5378. EnterCriticalSection(&m_csXEnroll);
  5379. // Accepting a request is not safe for scripting: pop up a warning dialog if called from script
  5380. if (0 != m_dwEnabledSafteyOptions) {
  5381. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFEACTION, &pwszTitle);
  5382. if (S_OK != hr)
  5383. goto xeLoadRCStringError;
  5384. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFE_ACCEPTING_CERT, &pwszNotSafeAccepting);
  5385. if (S_OK != hr)
  5386. goto xeLoadRCStringError;
  5387. if (IDYES != MessageBoxU(NULL, pwszNotSafeAccepting, pwszTitle, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2)) {
  5388. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  5389. goto CancelledError;
  5390. }
  5391. }
  5392. // get the end entity cert
  5393. hr2 = GetEndEntityCert(pBlobPKCS7, TRUE, &pCertContextEnd);
  5394. if (S_OK != hr2 && XENROLL_E_CANNOT_ADD_ROOT_CERT != hr2)
  5395. {
  5396. hr = hr2;
  5397. goto ErrorGetEndEntityCert;
  5398. }
  5399. if(m_fDeleteRequestCert)
  5400. {
  5401. if ((hStoreRequest = GetStore(StoreREQUEST)) == NULL)
  5402. {
  5403. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5404. goto ErrorCertOpenRequestStore;
  5405. }
  5406. // check to see if this is in the request store
  5407. if ((pCertContextRequest = CertFindCertificateInStore(
  5408. hStoreRequest,
  5409. CRYPT_ASN_ENCODING,
  5410. 0,
  5411. CERT_FIND_PUBLIC_KEY,
  5412. (void *) &pCertContextEnd->pCertInfo->SubjectPublicKeyInfo,
  5413. NULL)) != NULL)
  5414. {
  5415. CertDeleteCertificateFromStore(pCertContextRequest);
  5416. pCertContextRequest = NULL;
  5417. }
  5418. }
  5419. cb = 0;
  5420. // if the cert is to be written to the CSP,
  5421. // put it there but only if we have keys
  5422. if (m_fWriteCertToCSP &&
  5423. CertGetCertificateContextProperty(
  5424. pCertContextEnd,
  5425. CERT_KEY_PROV_INFO_PROP_ID, NULL, &cb))
  5426. {
  5427. if ((hProv = GetProv(0)) == NULL)
  5428. {
  5429. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5430. goto ErrorCryptAcquireContext;
  5431. }
  5432. // This can't fail
  5433. get_KeySpec(&dwKeySpec);
  5434. if (!CryptGetUserKey(
  5435. hProv,
  5436. dwKeySpec,
  5437. &hKey))
  5438. {
  5439. hKey = NULL;
  5440. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5441. goto ErrorCryptGetUserKey;
  5442. }
  5443. // always attempt to write the cert to the csp
  5444. if (!CryptSetKeyParam(
  5445. hKey,
  5446. KP_CERTIFICATE,
  5447. pCertContextEnd->pbCertEncoded,
  5448. 0))
  5449. {
  5450. // only return an error if it is a smart card error
  5451. // otherwise ignore the error
  5452. if (SCODE_FACILITY(GetLastError()) == FACILITY_SCARD)
  5453. {
  5454. //return error code from writing cert to csp
  5455. //important to save the error code before following clean up
  5456. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5457. //if can't write cert back to smartcard, remove the cert from my store
  5458. if ((hStoreMy = GetStore(StoreMY)) == NULL)
  5459. {
  5460. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5461. goto ErrorCertOpenMyStore;
  5462. }
  5463. // check to see if this is in the MY store
  5464. if ((pCertContextMy = CertFindCertificateInStore(
  5465. hStoreMy,
  5466. CRYPT_ASN_ENCODING,
  5467. 0,
  5468. CERT_FIND_PUBLIC_KEY,
  5469. (void *) &pCertContextEnd->pCertInfo->SubjectPublicKeyInfo,
  5470. NULL)) != NULL)
  5471. {
  5472. //try to remove it
  5473. CertDeleteCertificateFromStore(pCertContextMy);
  5474. pCertContextMy = NULL;
  5475. }
  5476. if (!m_fUseExistingKey)
  5477. {
  5478. GetProv(CRYPT_DELETEKEYSET);
  5479. }
  5480. //error any way
  5481. goto ErrorWriteToCSP;
  5482. }
  5483. }
  5484. }
  5485. if(m_fWriteCertToUserDS)
  5486. {
  5487. // otherwise attempt to open the store
  5488. if ((hStoreDS = CertOpenStore(
  5489. CERT_STORE_PROV_SYSTEM,
  5490. X509_ASN_ENCODING,
  5491. NULL,
  5492. CERT_SYSTEM_STORE_CURRENT_USER,
  5493. L"UserDS")) == NULL)
  5494. {
  5495. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5496. goto ErrorCertOpenDSStore;
  5497. }
  5498. if (!CertAddCertificateContextToStore(
  5499. hStoreDS,
  5500. pCertContextEnd,
  5501. CERT_STORE_ADD_NEW,
  5502. NULL))
  5503. {
  5504. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5505. goto ErrorAddCertificateContextToDSStore;
  5506. }
  5507. CertCloseStore(hStoreDS, 0);
  5508. hStoreDS = NULL;
  5509. }
  5510. // determine if he wants to save the spc file
  5511. if (m_wszSPCFileName[0] != 0)
  5512. {
  5513. // open the spc file
  5514. hFile = CreateOpenFileSafely2(m_wszSPCFileName, IDS_SPC_C, IDS_SPC_O);
  5515. if (NULL == hFile)
  5516. {
  5517. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5518. goto ErrorCreateSPCFile;
  5519. }
  5520. // write the spc
  5521. assert(pBlobPKCS7->pbData != NULL);
  5522. cb = 0;
  5523. if (!WriteFile(
  5524. hFile,
  5525. pBlobPKCS7->pbData,
  5526. pBlobPKCS7->cbData,
  5527. &cb,
  5528. NULL))
  5529. {
  5530. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5531. goto ErrorWriteSPCFile;
  5532. }
  5533. }
  5534. if (S_OK != hr2)
  5535. {
  5536. //return hr2 error
  5537. hr = hr2;
  5538. }
  5539. else
  5540. {
  5541. hr = S_OK;
  5542. }
  5543. ErrorReturn:
  5544. if(hKey != NULL)
  5545. CryptDestroyKey(hKey);
  5546. if(hFile != NULL)
  5547. CloseHandle(hFile);
  5548. if(pCertContextEnd != NULL)
  5549. CertFreeCertificateContext(pCertContextEnd);
  5550. if(hStoreDS != NULL)
  5551. CertCloseStore(hStoreDS, 0);
  5552. if (NULL != pwszNotSafeAccepting)
  5553. LocalFree(pwszNotSafeAccepting);
  5554. if (NULL != pwszTitle)
  5555. LocalFree(pwszTitle);
  5556. LeaveCriticalSection(&m_csXEnroll);
  5557. return(hr);
  5558. TRACE_ERROR(ErrorWriteToCSP);
  5559. TRACE_ERROR(ErrorCreateSPCFile);
  5560. TRACE_ERROR(ErrorWriteSPCFile);
  5561. TRACE_ERROR(ErrorGetEndEntityCert);
  5562. TRACE_ERROR(ErrorCryptAcquireContext);
  5563. TRACE_ERROR(ErrorCryptGetUserKey);
  5564. TRACE_ERROR(ErrorCertOpenDSStore);
  5565. TRACE_ERROR(ErrorAddCertificateContextToDSStore);
  5566. TRACE_ERROR(ErrorCertOpenRequestStore);
  5567. TRACE_ERROR(ErrorCertOpenMyStore);
  5568. TRACE_ERROR(CancelledError);
  5569. TRACE_ERROR(xeLoadRCStringError);
  5570. }
  5571. PCCERT_CONTEXT STDMETHODCALLTYPE CCEnroll::getCertContextFromPKCS7(
  5572. /* [in] */ PCRYPT_DATA_BLOB pBlobPKCS7) {
  5573. HRESULT hr;
  5574. PCCERT_CONTEXT pCert;
  5575. // get the end entity cert
  5576. hr = GetEndEntityCert(pBlobPKCS7, FALSE, &pCert);
  5577. #if DBG
  5578. if (S_OK != hr)
  5579. {
  5580. assert(NULL == pCert);
  5581. }
  5582. #endif //DBG
  5583. return pCert;
  5584. }
  5585. HRESULT STDMETHODCALLTYPE CCEnroll::enumProvidersWStr(
  5586. /* [in] */ LONG dwIndex,
  5587. /* [in] */ LONG dwFlags,
  5588. /* [out] */ LPWSTR __RPC_FAR *ppwsz) {
  5589. DWORD iLast = 0;
  5590. LONG i;
  5591. DWORD dwProvType = 0;
  5592. DWORD cb = 0;
  5593. HRESULT hr = S_OK;
  5594. DWORD errBefore = GetLastError();
  5595. assert(ppwsz != NULL);
  5596. *ppwsz = NULL;
  5597. SetLastError(ERROR_SUCCESS);
  5598. EnterCriticalSection(&m_csXEnroll);
  5599. for(i=0; i<=dwIndex; i++) {
  5600. do {
  5601. cb = 0;
  5602. if( !CryptEnumProvidersU(
  5603. iLast,
  5604. 0,
  5605. 0,
  5606. &dwProvType,
  5607. NULL,
  5608. &cb
  5609. ) ) {
  5610. // only skip if entry is bad
  5611. if( GetLastError() != NTE_PROV_TYPE_ENTRY_BAD)
  5612. goto ErrorCryptEnumProvidersU;
  5613. }
  5614. iLast++;
  5615. } while((CRYPT_ENUM_ALL_PROVIDERS & dwFlags) != CRYPT_ENUM_ALL_PROVIDERS &&
  5616. dwProvType != m_keyProvInfo.dwProvType);
  5617. }
  5618. iLast--;
  5619. if( (*ppwsz = (LPWSTR) MyCoTaskMemAlloc(cb)) == NULL ||
  5620. !CryptEnumProvidersU(
  5621. iLast,
  5622. 0,
  5623. 0,
  5624. &dwProvType,
  5625. *ppwsz,
  5626. &cb
  5627. ) ) {
  5628. goto ErrorCryptEnumProvidersU;
  5629. }
  5630. CommonReturn:
  5631. SetLastError(errBefore);
  5632. LeaveCriticalSection(&m_csXEnroll);
  5633. return(hr);
  5634. ErrorReturn:
  5635. if(GetLastError() == ERROR_SUCCESS)
  5636. SetLastError((DWORD)E_UNEXPECTED);
  5637. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5638. // We have an error, make sure we set it.
  5639. errBefore = GetLastError();
  5640. if(*ppwsz != NULL)
  5641. {
  5642. MyCoTaskMemFree(*ppwsz);
  5643. *ppwsz = NULL;
  5644. }
  5645. goto CommonReturn;
  5646. TRACE_ERROR(ErrorCryptEnumProvidersU);
  5647. }
  5648. //--------------------------------------------------------------------------------
  5649. //
  5650. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  5651. //
  5652. //--------------------------------------------------------------------------------
  5653. HRESULT STDMETHODCALLTYPE CCEnroll::enumContainersWStr(
  5654. /* [in] */ LONG dwIndex,
  5655. /* [out] */ LPWSTR __RPC_FAR *ppwsz) {
  5656. DWORD errBefore = GetLastError();
  5657. DWORD cb = 0;
  5658. LONG i = 0;
  5659. char * psz = NULL;
  5660. HRESULT hr = S_OK;
  5661. EnterCriticalSection(&m_csXEnroll);
  5662. SetLastError(ERROR_SUCCESS);
  5663. assert(ppwsz != NULL);
  5664. *ppwsz = NULL;
  5665. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  5666. goto AccessDeniedError;
  5667. hr = GetVerifyProv();
  5668. if (S_OK != hr)
  5669. {
  5670. goto GetVerifyProvError;
  5671. }
  5672. while (TRUE)
  5673. {
  5674. if(!CryptGetProvParam(
  5675. m_hVerifyProv,
  5676. PP_ENUMCONTAINERS,
  5677. (BYTE*)psz,
  5678. &cb,
  5679. CRYPT_FIRST))
  5680. {
  5681. goto ErrorCryptGetProvParam;
  5682. }
  5683. if (NULL != psz)
  5684. {
  5685. //done
  5686. break;
  5687. }
  5688. psz = (char*)LocalAlloc(LMEM_FIXED, cb);
  5689. if (NULL == psz)
  5690. {
  5691. goto ErrorOutOfMem;
  5692. }
  5693. }
  5694. for(i=1; i<=dwIndex; i++) {
  5695. //assume 1st enum buffer size is big enough for all?
  5696. if( !CryptGetProvParam(
  5697. m_hVerifyProv,
  5698. PP_ENUMCONTAINERS,
  5699. (BYTE *) psz,
  5700. &cb,
  5701. 0) )
  5702. goto ErrorCryptGetProvParam;
  5703. }
  5704. if( (*ppwsz = WideFromMB(psz)) == NULL )
  5705. goto ErrorOutOfMem;
  5706. CommonReturn:
  5707. if (NULL != psz)
  5708. {
  5709. LocalFree(psz);
  5710. }
  5711. SetLastError(errBefore);
  5712. LeaveCriticalSection(&m_csXEnroll);
  5713. return(hr);
  5714. ErrorReturn:
  5715. if(GetLastError() == ERROR_SUCCESS)
  5716. SetLastError((DWORD)E_UNEXPECTED);
  5717. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5718. // We have an error, make sure we set it.
  5719. errBefore = GetLastError();
  5720. if(*ppwsz != NULL)
  5721. MyCoTaskMemFree(*ppwsz);
  5722. *ppwsz = NULL;
  5723. goto CommonReturn;
  5724. SET_ERROR(AccessDeniedError, E_ACCESSDENIED);
  5725. TRACE_ERROR(GetVerifyProvError);
  5726. TRACE_ERROR(ErrorCryptGetProvParam);
  5727. TRACE_ERROR(ErrorOutOfMem);
  5728. }
  5729. HRESULT CCEnroll::PKCS10ToCert(IN HCERTSTORE hCertStore,
  5730. IN CRYPT_DATA_BLOB pkcs10Blob,
  5731. OUT PCCERT_CONTEXT *ppCertContext)
  5732. {
  5733. HRESULT hr = E_FAIL;
  5734. PCERT_REQUEST_INFO pReqInfo = NULL;
  5735. // Input validation:
  5736. if (NULL == hCertStore || NULL == pkcs10Blob.pbData || NULL == ppCertContext)
  5737. return E_INVALIDARG;
  5738. if( !MyCryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  5739. &pkcs10Blob,
  5740. CERT_QUERY_CONTENT_FLAG_PKCS10,
  5741. CERT_QUERY_FORMAT_FLAG_ALL,
  5742. CRYPT_DECODE_ALLOC_FLAG,
  5743. NULL,
  5744. NULL,
  5745. NULL,
  5746. NULL,
  5747. NULL,
  5748. (const void **) &pReqInfo) )
  5749. goto MyCryptQueryObjectError;
  5750. if ( NULL == (*ppCertContext = CertFindCertificateInStore
  5751. (hCertStore,
  5752. CRYPT_ASN_ENCODING,
  5753. 0,
  5754. CERT_FIND_PUBLIC_KEY,
  5755. (void *) &pReqInfo->SubjectPublicKeyInfo,
  5756. NULL)) )
  5757. goto CertFindCertificateInStoreError;
  5758. hr = S_OK;
  5759. CommonReturn:
  5760. if (NULL != pReqInfo) { LocalFree(pReqInfo); } // Allocated in CryptQueryObject().
  5761. return hr;
  5762. ErrorReturn:
  5763. goto CommonReturn;
  5764. SET_HRESULT(CertFindCertificateInStoreError, MY_HRESULT_FROM_WIN32(GetLastError()));
  5765. SET_HRESULT(MyCryptQueryObjectError, MY_HRESULT_FROM_WIN32(GetLastError()));
  5766. }
  5767. HRESULT CCEnroll::PKCS7ToCert(IN HCERTSTORE hCertStore,
  5768. IN CRYPT_DATA_BLOB pkcs7Blob,
  5769. OUT PCCERT_CONTEXT *ppCertContext)
  5770. {
  5771. CRYPT_DATA_BLOB pkcs10Blob;
  5772. CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
  5773. HRESULT hr = E_FAIL;
  5774. // Init locals:
  5775. ZeroMemory(&pkcs10Blob, sizeof(pkcs10Blob));
  5776. ZeroMemory(&VerifyPara, sizeof(VerifyPara));
  5777. VerifyPara.cbSize = sizeof(VerifyPara);
  5778. VerifyPara.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
  5779. if (!MyCryptVerifyMessageSignature
  5780. (&VerifyPara,
  5781. 0, // dwSignerIndex
  5782. pkcs7Blob.pbData,
  5783. pkcs7Blob.cbData,
  5784. pkcs10Blob.pbData,
  5785. &(pkcs10Blob.cbData),
  5786. NULL // ppSignerCert
  5787. ) || 0 == pkcs10Blob.cbData)
  5788. goto MyCryptVerifyMessageSignatureError;
  5789. if (NULL == (pkcs10Blob.pbData = (PBYTE)LocalAlloc(LPTR, pkcs10Blob.cbData)))
  5790. goto MemoryError;
  5791. if (!MyCryptVerifyMessageSignature
  5792. (&VerifyPara,
  5793. 0, // dwSignerIndex
  5794. pkcs7Blob.pbData,
  5795. pkcs7Blob.cbData,
  5796. pkcs10Blob.pbData,
  5797. &pkcs10Blob.cbData,
  5798. NULL // ppSignerCert
  5799. ))
  5800. goto MyCryptVerifyMessageSignatureError;
  5801. hr = this->PKCS10ToCert(hCertStore, pkcs10Blob, ppCertContext);
  5802. CommonReturn:
  5803. if (NULL != pkcs10Blob.pbData) { LocalFree(pkcs10Blob.pbData); }
  5804. return hr;
  5805. ErrorReturn:
  5806. goto CommonReturn;
  5807. SET_HRESULT(MemoryError, E_OUTOFMEMORY);
  5808. SET_HRESULT(MyCryptVerifyMessageSignatureError, MY_HRESULT_FROM_WIN32(GetLastError()));
  5809. }
  5810. HRESULT STDMETHODCALLTYPE CCEnroll::freeRequestInfoBlob(
  5811. /* [in] */ CRYPT_DATA_BLOB pkcs7OrPkcs10) {
  5812. DWORD dwContentType = NULL;
  5813. HCERTSTORE hStoreRequest = NULL;
  5814. HRESULT hr = E_FAIL;
  5815. PCCERT_CONTEXT pCertContext = NULL;
  5816. // We're not supposed to delete the cert anyway, so we're done!
  5817. if (!m_fDeleteRequestCert)
  5818. return S_OK;
  5819. if (NULL == pkcs7OrPkcs10.pbData)
  5820. return E_INVALIDARG;
  5821. EnterCriticalSection(&m_csXEnroll);
  5822. // Step 1) Determine if we have a PKCS7 or a PKCS10:
  5823. //
  5824. if( !MyCryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  5825. &pkcs7OrPkcs10,
  5826. (CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | CERT_QUERY_CONTENT_FLAG_PKCS10),
  5827. CERT_QUERY_FORMAT_FLAG_ALL,
  5828. 0,
  5829. NULL,
  5830. &dwContentType, // OUT: PKCS10 or PKCS7
  5831. NULL,
  5832. NULL,
  5833. NULL,
  5834. NULL) )
  5835. goto MyCryptQueryObjectError;
  5836. // Step 2) Find a cert context with a matching public key in the request store:
  5837. //
  5838. if (NULL == (hStoreRequest = GetStore(StoreREQUEST)))
  5839. goto UnexpectedError;
  5840. switch (dwContentType)
  5841. {
  5842. case CERT_QUERY_CONTENT_PKCS7_SIGNED:
  5843. hr = this->PKCS7ToCert(hStoreRequest, pkcs7OrPkcs10, &pCertContext);
  5844. if (S_OK != hr)
  5845. {
  5846. if (CRYPT_E_NOT_FOUND == hr)
  5847. {
  5848. //freeRequestInfo could be called when cert is not issued
  5849. //PKCS7 could be CMC which is signed by request key and
  5850. //cert is not in local store yet. We try cached cert
  5851. if (NULL != m_pCertContextPendingRequest)
  5852. {
  5853. //looks we still have cached request cert handle
  5854. pCertContext = CertDuplicateCertificateContext(
  5855. m_pCertContextPendingRequest);
  5856. if (NULL == pCertContext)
  5857. {
  5858. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5859. goto CertDuplicateCertificateContextError;
  5860. }
  5861. }
  5862. else if (NULL != m_hashBlobPendingRequest.pbData &&
  5863. 0 < m_hashBlobPendingRequest.cbData)
  5864. {
  5865. //don't have cached request handle but thumbprint exists
  5866. //retrieve the request cert handle from store
  5867. pCertContext = CertFindCertificateInStore(
  5868. hStoreRequest, //request store
  5869. X509_ASN_ENCODING,
  5870. 0,
  5871. CERT_FIND_HASH,
  5872. &m_hashBlobPendingRequest,
  5873. NULL);
  5874. if (NULL == pCertContext)
  5875. {
  5876. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5877. goto CertFindCertificateInStoreError;
  5878. }
  5879. }
  5880. else
  5881. {
  5882. //sorry, don't know which cert to be free
  5883. //however, can try to find public key from PKCS7
  5884. goto PKCS7ToCertError;
  5885. }
  5886. }
  5887. else
  5888. {
  5889. //other errors
  5890. goto PKCS7ToCertError;
  5891. }
  5892. }
  5893. break;
  5894. case CERT_QUERY_CONTENT_PKCS10:
  5895. if (S_OK != (hr = this->PKCS10ToCert(hStoreRequest, pkcs7OrPkcs10, &pCertContext)))
  5896. goto PKCS10ToCertError;
  5897. break;
  5898. default:
  5899. goto InvalidContentTypeError;
  5900. }
  5901. if (!CertDeleteCertificateFromStore(pCertContext))
  5902. {
  5903. // pCertContext is freed even when CertDeleteCertificateFromStore() returns an error.
  5904. pCertContext = NULL;
  5905. goto CertDeleteCertificateFromStoreError;
  5906. }
  5907. hr = S_OK;
  5908. CommonReturn:
  5909. LeaveCriticalSection(&m_csXEnroll);
  5910. return hr;
  5911. ErrorReturn:
  5912. if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
  5913. goto CommonReturn;
  5914. SET_HRESULT(CertDeleteCertificateFromStoreError, MY_HRESULT_FROM_WIN32(GetLastError()));
  5915. SET_HRESULT(PKCS7ToCertError, hr);
  5916. SET_HRESULT(PKCS10ToCertError, hr);
  5917. SET_HRESULT(InvalidContentTypeError, E_INVALIDARG);
  5918. SET_HRESULT(MyCryptQueryObjectError, MY_HRESULT_FROM_WIN32(GetLastError()));
  5919. SET_HRESULT(UnexpectedError, E_UNEXPECTED);
  5920. TRACE_ERROR(CertDuplicateCertificateContextError)
  5921. TRACE_ERROR(CertFindCertificateInStoreError)
  5922. }
  5923. HRESULT STDMETHODCALLTYPE CCEnroll::get_SPCFileNameWStr(
  5924. /* [out] */ LPWSTR __RPC_FAR *szw) {
  5925. HRESULT hr = S_OK;
  5926. EnterCriticalSection(&m_csXEnroll);
  5927. if( (*szw = CopyWideString(m_wszSPCFileName)) == NULL )
  5928. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5929. LeaveCriticalSection(&m_csXEnroll);
  5930. return(hr);
  5931. }
  5932. HRESULT STDMETHODCALLTYPE CCEnroll::put_SPCFileNameWStr(
  5933. /* [in] */ LPWSTR pwsz) {
  5934. HRESULT hr = S_OK;
  5935. if(pwsz == NULL)
  5936. return(MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  5937. EnterCriticalSection(&m_csXEnroll);
  5938. if( m_wszSPCFileName != wszEmpty)
  5939. MyCoTaskMemFree(m_wszSPCFileName);
  5940. if( (m_wszSPCFileName = CopyWideString(pwsz)) == NULL )
  5941. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5942. LeaveCriticalSection(&m_csXEnroll);
  5943. return(hr);
  5944. }
  5945. HRESULT STDMETHODCALLTYPE CCEnroll::get_PVKFileNameWStr(
  5946. /* [out] */ LPWSTR __RPC_FAR *szw) {
  5947. HRESULT hr = S_OK;
  5948. EnterCriticalSection(&m_csXEnroll);
  5949. if( (*szw = CopyWideString(m_wszPVKFileName)) == NULL )
  5950. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5951. LeaveCriticalSection(&m_csXEnroll);
  5952. return(hr);
  5953. }
  5954. HRESULT STDMETHODCALLTYPE CCEnroll::put_PVKFileNameWStr(
  5955. /* [in] */ LPWSTR pwsz) {
  5956. HRESULT hr = S_OK;
  5957. if(pwsz == NULL)
  5958. return(MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  5959. EnterCriticalSection(&m_csXEnroll);
  5960. if( m_wszPVKFileName != wszEmpty)
  5961. MyCoTaskMemFree(m_wszPVKFileName);
  5962. if( (m_wszPVKFileName = CopyWideString(pwsz)) == NULL )
  5963. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5964. else
  5965. m_dwGenKeyFlags |= CRYPT_EXPORTABLE; //why???
  5966. LeaveCriticalSection(&m_csXEnroll);
  5967. return(hr);
  5968. }
  5969. HRESULT STDMETHODCALLTYPE CCEnroll::get_HashAlgorithmWStr(
  5970. /* [out] */ LPWSTR __RPC_FAR *ppwsz) {
  5971. PCCRYPT_OID_INFO pOidInfo = NULL;
  5972. ALG_ID rgAlg[2];
  5973. HRESULT hr = S_OK;
  5974. EnterCriticalSection(&m_csXEnroll);
  5975. assert(ppwsz != NULL);
  5976. *ppwsz = NULL;
  5977. if( !GetCapiHashAndSigAlgId(rgAlg) )
  5978. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5979. // Convert to an oid
  5980. else if( (NULL == (pOidInfo = xeCryptFindOIDInfo(
  5981. CRYPT_OID_INFO_ALGID_KEY,
  5982. (void *) &rgAlg[0],
  5983. CRYPT_HASH_ALG_OID_GROUP_ID)) ) ) {
  5984. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5985. }
  5986. else if( (*ppwsz = WideFromMB(pOidInfo->pszOID)) == NULL)
  5987. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  5988. LeaveCriticalSection(&m_csXEnroll);
  5989. return(hr);
  5990. }
  5991. HRESULT STDMETHODCALLTYPE CCEnroll::put_HashAlgorithmWStr(
  5992. /* [in] */ LPWSTR pwsz) {
  5993. HRESULT hr = S_OK;
  5994. char * szObjId = NULL;
  5995. PCCRYPT_OID_INFO pOidInfo = NULL;
  5996. if(pwsz == NULL) {
  5997. return(MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  5998. }
  5999. if(!_wcsicmp(L"SHA1", pwsz))
  6000. szObjId = CopyAsciiString(szOID_OIWSEC_sha1);
  6001. else if(!_wcsicmp(L"MD5", pwsz))
  6002. szObjId = CopyAsciiString(szOID_RSA_MD5RSA);
  6003. else if(!_wcsicmp(L"MD2", pwsz))
  6004. szObjId = CopyAsciiString(szOID_RSA_MD2RSA);
  6005. else
  6006. szObjId = MBFromWide(pwsz);
  6007. // something went wrong
  6008. if(szObjId == NULL)
  6009. return(MY_HRESULT_FROM_WIN32(GetLastError()));
  6010. // find the hashing algid
  6011. if( (NULL == (pOidInfo = xeCryptFindOIDInfo(
  6012. CRYPT_OID_INFO_OID_KEY,
  6013. szObjId,
  6014. 0)) ) )
  6015. {
  6016. //XIAOHS: CryptFindOIDInfo does not set the LastError in this case.
  6017. //AV in xEnroll. See bug# 189320
  6018. //hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6019. hr=NTE_BAD_ALGID;
  6020. }
  6021. assert(szObjId != NULL);
  6022. MyCoTaskMemFree(szObjId);
  6023. EnterCriticalSection(&m_csXEnroll);
  6024. if(hr == S_OK) {
  6025. if( pOidInfo->dwGroupId == CRYPT_HASH_ALG_OID_GROUP_ID ||
  6026. pOidInfo->dwGroupId == CRYPT_SIGN_ALG_OID_GROUP_ID )
  6027. m_HashAlgId = pOidInfo->Algid;
  6028. else
  6029. hr = CRYPT_E_NOT_FOUND;
  6030. }
  6031. LeaveCriticalSection(&m_csXEnroll);
  6032. return(hr);
  6033. }
  6034. HRESULT STDMETHODCALLTYPE CCEnroll::put_HashAlgID(
  6035. LONG hashAlgID
  6036. ) {
  6037. EnterCriticalSection(&m_csXEnroll);
  6038. m_HashAlgId = hashAlgID;
  6039. LeaveCriticalSection(&m_csXEnroll);
  6040. return(S_OK);
  6041. }
  6042. HRESULT STDMETHODCALLTYPE CCEnroll::get_HashAlgID(
  6043. LONG * hashAlgID
  6044. ) {
  6045. EnterCriticalSection(&m_csXEnroll);
  6046. *hashAlgID = m_HashAlgId;
  6047. LeaveCriticalSection(&m_csXEnroll);
  6048. return(S_OK);
  6049. }
  6050. HRESULT STDMETHODCALLTYPE CCEnroll::get_RenewalCertificate(
  6051. /* [out] */ PCCERT_CONTEXT __RPC_FAR *ppCertContext) {
  6052. HRESULT hr = S_OK;
  6053. *ppCertContext = NULL;
  6054. if( m_pCertContextRenewal == NULL)
  6055. return(MY_HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND));
  6056. EnterCriticalSection(&m_csXEnroll);
  6057. if( NULL == (*ppCertContext = CertDuplicateCertificateContext(m_pCertContextRenewal)) )
  6058. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6059. LeaveCriticalSection(&m_csXEnroll);
  6060. return(hr);
  6061. }
  6062. HRESULT STDMETHODCALLTYPE CCEnroll::put_RenewalCertificate(
  6063. /* [in] */ PCCERT_CONTEXT pCertContext)
  6064. {
  6065. HRESULT hr;
  6066. PCCERT_CONTEXT pGoodCertContext= NULL;
  6067. EnterCriticalSection(&m_csXEnroll);
  6068. hr = GetGoodCertContext(pCertContext, &pGoodCertContext);
  6069. if (S_OK != hr)
  6070. {
  6071. goto GetGoodCertContextError;
  6072. }
  6073. if(m_pCertContextRenewal != NULL)
  6074. {
  6075. CertFreeCertificateContext(m_pCertContextRenewal);
  6076. }
  6077. m_pCertContextRenewal = pGoodCertContext;
  6078. hr = S_OK;
  6079. ErrorReturn:
  6080. LeaveCriticalSection(&m_csXEnroll);
  6081. return hr;
  6082. TRACE_ERROR(GetGoodCertContextError);
  6083. }
  6084. BOOL
  6085. CCEnroll::CopyAndPushStackExtension(
  6086. PCERT_EXTENSION pExt,
  6087. BOOL fCMC)
  6088. {
  6089. DWORD cb = 0;
  6090. DWORD cbOid = 0;
  6091. PEXT_STACK pExtStackEle = NULL;
  6092. PBYTE pb = NULL;
  6093. PEXT_STACK *ppExtStack = NULL;
  6094. DWORD *pcExtStack = NULL;
  6095. assert(pExt != NULL);
  6096. // allocate the space
  6097. cbOid = POINTERROUND((DWORD)strlen(pExt->pszObjId) + 1); //ia64 align
  6098. cb = sizeof(EXT_STACK) + cbOid + pExt->Value.cbData;
  6099. if(NULL == (pb = (PBYTE) malloc(cb))) {
  6100. SetLastError(ERROR_OUTOFMEMORY);
  6101. return(FALSE);
  6102. }
  6103. // set my pointers
  6104. pExtStackEle = (PEXT_STACK) pb;
  6105. pb += sizeof(EXT_STACK);
  6106. pExtStackEle->ext.pszObjId = (LPSTR) pb;
  6107. pb += cbOid;
  6108. pExtStackEle->ext.Value.pbData = pb;
  6109. // set the values
  6110. strcpy(pExtStackEle->ext.pszObjId, pExt->pszObjId);
  6111. pExtStackEle->ext.fCritical = pExt->fCritical;
  6112. pExtStackEle->ext.Value.cbData = pExt->Value.cbData;
  6113. memcpy(pExtStackEle->ext.Value.pbData, pExt->Value.pbData, pExt->Value.cbData);
  6114. // insert on the list
  6115. EnterCriticalSection(&m_csXEnroll);
  6116. ppExtStack = fCMC ? &m_pExtStackNew : &m_pExtStack;
  6117. pcExtStack = fCMC ? &m_cExtStackNew : &m_cExtStack;
  6118. pExtStackEle->pNext = *ppExtStack;
  6119. *ppExtStack = pExtStackEle;
  6120. (*pcExtStack)++;
  6121. LeaveCriticalSection(&m_csXEnroll);
  6122. return(TRUE);
  6123. }
  6124. PCERT_EXTENSION
  6125. CCEnroll::PopStackExtension(
  6126. BOOL fCMC)
  6127. {
  6128. PEXT_STACK pExtStackEle = NULL;
  6129. PEXT_STACK *ppExtStack = NULL;
  6130. DWORD *pcExtStack = NULL;
  6131. EnterCriticalSection(&m_csXEnroll);
  6132. ppExtStack = fCMC ? &m_pExtStackNew : &m_pExtStack;
  6133. if(NULL != *ppExtStack)
  6134. {
  6135. pExtStackEle = *ppExtStack;
  6136. *ppExtStack = (*ppExtStack)->pNext;
  6137. pcExtStack = fCMC ? &m_cExtStackNew : &m_cExtStack;
  6138. (*pcExtStack)--;
  6139. }
  6140. LeaveCriticalSection(&m_csXEnroll);
  6141. return((PCERT_EXTENSION) pExtStackEle);
  6142. }
  6143. DWORD
  6144. CCEnroll::CountStackExtension(BOOL fCMC)
  6145. {
  6146. DWORD cExt = 0;
  6147. EnterCriticalSection(&m_csXEnroll);
  6148. cExt = fCMC ? m_cExtStackNew : m_cExtStack;
  6149. LeaveCriticalSection(&m_csXEnroll);
  6150. return(cExt);
  6151. }
  6152. PCERT_EXTENSION
  6153. CCEnroll::EnumStackExtension(
  6154. PCERT_EXTENSION pExtLast,
  6155. BOOL fCMC)
  6156. {
  6157. PEXT_STACK pExtStackEle = (PEXT_STACK)pExtLast;
  6158. EnterCriticalSection(&m_csXEnroll);
  6159. if(NULL == pExtStackEle)
  6160. {
  6161. pExtStackEle = fCMC ? m_pExtStackNew : m_pExtStack;
  6162. }
  6163. else
  6164. {
  6165. pExtStackEle = pExtStackEle->pNext;
  6166. }
  6167. LeaveCriticalSection(&m_csXEnroll);
  6168. return((PCERT_EXTENSION) pExtStackEle);
  6169. }
  6170. void
  6171. CCEnroll::FreeAllStackExtension(void)
  6172. {
  6173. EnterCriticalSection(&m_csXEnroll);
  6174. //free cmc extensions
  6175. while(0 != m_cExtStackNew)
  6176. {
  6177. FreeStackExtension(PopStackExtension(TRUE));
  6178. }
  6179. //free old client extensions
  6180. while(0 != m_cExtStack)
  6181. {
  6182. FreeStackExtension(PopStackExtension(FALSE));
  6183. }
  6184. LeaveCriticalSection(&m_csXEnroll);
  6185. }
  6186. void CCEnroll::FreeStackExtension(PCERT_EXTENSION pExt) {
  6187. if(pExt != NULL)
  6188. free(pExt);
  6189. }
  6190. //obselete call for new client
  6191. HRESULT STDMETHODCALLTYPE
  6192. CCEnroll::AddExtensionsToRequest(
  6193. /* [in] */ PCERT_EXTENSIONS pCertExtensions)
  6194. {
  6195. HRESULT hr = S_OK;
  6196. DWORD i = 0;
  6197. assert(pCertExtensions != NULL);
  6198. for(i = 0; i < pCertExtensions->cExtension; i++)
  6199. {
  6200. //push into old extension stack
  6201. if(!CopyAndPushStackExtension(&pCertExtensions->rgExtension[i], FALSE))
  6202. {
  6203. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6204. break;
  6205. }
  6206. }
  6207. return(hr);
  6208. }
  6209. BOOL
  6210. CCEnroll::CopyAndPushStackAttribute(
  6211. PCRYPT_ATTRIBUTE pAttr,
  6212. BOOL fCMC)
  6213. {
  6214. DWORD i = 0;
  6215. DWORD cb = 0;
  6216. DWORD cbOid = 0;
  6217. PATTR_STACK pAttrStackEle = NULL;
  6218. PBYTE pb = NULL;
  6219. PATTR_STACK *ppAttrStack = NULL;
  6220. DWORD *pcAttrStack = NULL;
  6221. assert(pAttr != NULL);
  6222. // allocate the space
  6223. cb = sizeof(ATTR_STACK);
  6224. //make sure aligned for ia64
  6225. cbOid = POINTERROUND((DWORD)strlen(pAttr->pszObjId) + 1);
  6226. cb += cbOid;
  6227. cb += sizeof(CRYPT_ATTR_BLOB) * pAttr->cValue;
  6228. for(i=0; i<pAttr->cValue; i++)
  6229. cb += POINTERROUND(pAttr->rgValue[i].cbData); //pointer align
  6230. if(NULL == (pb = (PBYTE) malloc(cb))) {
  6231. SetLastError(ERROR_OUTOFMEMORY);
  6232. return(FALSE);
  6233. }
  6234. // set my pointers
  6235. pAttrStackEle = (PATTR_STACK) pb;
  6236. pb += sizeof(ATTR_STACK);
  6237. pAttrStackEle->attr.pszObjId = (LPSTR) pb;
  6238. pb += cbOid;
  6239. strcpy(pAttrStackEle->attr.pszObjId, pAttr->pszObjId);
  6240. pAttrStackEle->attr.cValue = pAttr->cValue;
  6241. pAttrStackEle->attr.rgValue = (PCRYPT_ATTR_BLOB) pb;
  6242. pb += sizeof(CRYPT_ATTR_BLOB) * pAttr->cValue;
  6243. for(i=0; i<pAttr->cValue; i++) {
  6244. pAttrStackEle->attr.rgValue[i].pbData = pb;
  6245. pAttrStackEle->attr.rgValue[i].cbData = pAttr->rgValue[i].cbData;
  6246. memcpy(pAttrStackEle->attr.rgValue[i].pbData, pAttr->rgValue[i].pbData, pAttr->rgValue[i].cbData);
  6247. pb += POINTERROUND(pAttr->rgValue[i].cbData);
  6248. }
  6249. assert( pb == ((BYTE *) pAttrStackEle) + cb );
  6250. // insert on the list
  6251. EnterCriticalSection(&m_csXEnroll);
  6252. ppAttrStack = fCMC ? &m_pAttrStackNew : &m_pAttrStack;
  6253. pcAttrStack = fCMC ? &m_cAttrStackNew : &m_cAttrStack;
  6254. pAttrStackEle->pNext = *ppAttrStack;
  6255. *ppAttrStack = pAttrStackEle;
  6256. (*pcAttrStack)++;
  6257. LeaveCriticalSection(&m_csXEnroll);
  6258. return(TRUE);
  6259. }
  6260. PCRYPT_ATTRIBUTE
  6261. CCEnroll::PopStackAttribute(BOOL fCMC)
  6262. {
  6263. PATTR_STACK pAttrStackEle = NULL;
  6264. PATTR_STACK *ppAttrStack = NULL;
  6265. DWORD *pcAttrStack = NULL;
  6266. EnterCriticalSection(&m_csXEnroll);
  6267. ppAttrStack = fCMC ? &m_pAttrStackNew : &m_pAttrStack;
  6268. if(NULL != *ppAttrStack)
  6269. {
  6270. pAttrStackEle = *ppAttrStack;
  6271. *ppAttrStack = (*ppAttrStack)->pNext;
  6272. pcAttrStack = fCMC ? &m_cAttrStackNew : &m_cAttrStack;
  6273. (*pcAttrStack)--;
  6274. }
  6275. LeaveCriticalSection(&m_csXEnroll);
  6276. return((PCRYPT_ATTRIBUTE) pAttrStackEle);
  6277. }
  6278. DWORD
  6279. CCEnroll::CountStackAttribute(BOOL fCMC)
  6280. {
  6281. DWORD cAttr = 0;
  6282. EnterCriticalSection(&m_csXEnroll);
  6283. cAttr = fCMC ? m_cAttrStackNew : m_cAttrStack;
  6284. LeaveCriticalSection(&m_csXEnroll);
  6285. return(cAttr);
  6286. }
  6287. PCRYPT_ATTRIBUTE
  6288. CCEnroll::EnumStackAttribute(
  6289. PCRYPT_ATTRIBUTE pAttrLast,
  6290. BOOL fCMC)
  6291. {
  6292. PATTR_STACK pAttrStackEle = (PATTR_STACK) pAttrLast;
  6293. EnterCriticalSection(&m_csXEnroll);
  6294. if(NULL == pAttrLast)
  6295. {
  6296. pAttrStackEle = fCMC ? m_pAttrStackNew : m_pAttrStack;
  6297. }
  6298. else
  6299. {
  6300. pAttrStackEle = pAttrStackEle->pNext;
  6301. }
  6302. LeaveCriticalSection(&m_csXEnroll);
  6303. return((PCRYPT_ATTRIBUTE) pAttrStackEle);
  6304. }
  6305. void CCEnroll::FreeAllStackAttribute(void)
  6306. {
  6307. EnterCriticalSection(&m_csXEnroll);
  6308. while(0 != m_cAttrStackNew)
  6309. {
  6310. FreeStackAttribute(PopStackAttribute(TRUE));
  6311. }
  6312. while(0 != m_cAttrStack)
  6313. {
  6314. FreeStackAttribute(PopStackAttribute(FALSE));
  6315. }
  6316. LeaveCriticalSection(&m_csXEnroll);
  6317. }
  6318. void CCEnroll::FreeStackAttribute(PCRYPT_ATTRIBUTE pAttr) {
  6319. if(pAttr != NULL)
  6320. free(pAttr);
  6321. }
  6322. HRESULT STDMETHODCALLTYPE
  6323. CCEnroll::AddAuthenticatedAttributesToPKCS7Request(
  6324. /* [in] */ PCRYPT_ATTRIBUTES pAttributes)
  6325. {
  6326. HRESULT hr = S_OK;
  6327. DWORD i;
  6328. for(i = 0; i < pAttributes->cAttr; i++)
  6329. {
  6330. if(!CopyAndPushStackAttribute(&pAttributes->rgAttr[i], FALSE))
  6331. {
  6332. hr = (MY_HRESULT_FROM_WIN32(GetLastError()));
  6333. break;
  6334. }
  6335. //put into cmc stack too
  6336. if(!CopyAndPushStackAttribute(&pAttributes->rgAttr[i], TRUE))
  6337. {
  6338. hr = (MY_HRESULT_FROM_WIN32(GetLastError()));
  6339. break;
  6340. }
  6341. }
  6342. return(hr);
  6343. }
  6344. HRESULT STDMETHODCALLTYPE CCEnroll::CreatePKCS7RequestFromRequest(
  6345. /* [in] */ PCRYPT_DATA_BLOB pRequest,
  6346. /* [in] */ PCCERT_CONTEXT pSigningRACertContext,
  6347. /* [out] */ PCRYPT_DATA_BLOB pPkcs7Blob) {
  6348. HRESULT hr = S_OK;
  6349. DWORD errBefore = GetLastError();
  6350. CRYPT_SIGN_MESSAGE_PARA signMsgPara;
  6351. PCCRYPT_OID_INFO pOidInfo = NULL;
  6352. PCRYPT_ATTRIBUTE pAttrCur = NULL;
  6353. DWORD i;
  6354. ALG_ID rgAlg[2];
  6355. CRYPT_KEY_PROV_INFO *pKeyProvInfo = NULL;
  6356. DWORD cb = 0;
  6357. assert(pSigningRACertContext != NULL);
  6358. assert(pRequest != NULL);
  6359. assert(pPkcs7Blob != NULL);
  6360. memset(&signMsgPara, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA));
  6361. memset(pPkcs7Blob, 0, sizeof(CRYPT_DATA_BLOB));
  6362. if( !GetCapiHashAndSigAlgId(rgAlg) )
  6363. goto ErrorGetCapiHashAndSigAlgId;
  6364. // find out what the oid is
  6365. if( (NULL == (pOidInfo = xeCryptFindOIDInfo(
  6366. CRYPT_OID_INFO_ALGID_KEY,
  6367. (void *) &rgAlg[0],
  6368. CRYPT_HASH_ALG_OID_GROUP_ID)) ) )
  6369. {
  6370. SetLastError((DWORD)NTE_BAD_ALGID);
  6371. goto ErrorCryptFindOIDInfo;
  6372. }
  6373. // now add all of the user defined extensions
  6374. EnterCriticalSection(&m_csXEnroll);
  6375. signMsgPara.cAuthAttr = CountStackAttribute(m_fNewRequestMethod);
  6376. signMsgPara.rgAuthAttr = (PCRYPT_ATTRIBUTE)LocalAlloc(LMEM_FIXED,
  6377. signMsgPara.cAuthAttr * sizeof(CRYPT_ATTRIBUTE));
  6378. if( NULL == signMsgPara.rgAuthAttr)
  6379. {
  6380. SetLastError(ERROR_OUTOFMEMORY);
  6381. LeaveCriticalSection(&m_csXEnroll);
  6382. goto ErrorOutOfMemory;
  6383. }
  6384. i = 0;
  6385. pAttrCur = NULL;
  6386. while(NULL != (pAttrCur = EnumStackAttribute(pAttrCur, m_fNewRequestMethod)) ) {
  6387. signMsgPara.rgAuthAttr[i] = *pAttrCur;
  6388. i++;
  6389. }
  6390. LeaveCriticalSection(&m_csXEnroll);
  6391. signMsgPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
  6392. signMsgPara.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
  6393. signMsgPara.pSigningCert = pSigningRACertContext;
  6394. signMsgPara.HashAlgorithm.pszObjId = (char *) pOidInfo->pszOID;
  6395. signMsgPara.cMsgCert = 1;
  6396. signMsgPara.rgpMsgCert = &pSigningRACertContext;
  6397. //get key prov info
  6398. while (TRUE)
  6399. {
  6400. if(!CertGetCertificateContextProperty(
  6401. pSigningRACertContext,
  6402. CERT_KEY_PROV_INFO_PROP_ID,
  6403. pKeyProvInfo,
  6404. &cb))
  6405. {
  6406. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6407. goto CertGetCertificateContextPropertyError;
  6408. }
  6409. if (NULL != pKeyProvInfo)
  6410. {
  6411. //got it, done
  6412. break;
  6413. }
  6414. pKeyProvInfo = (CRYPT_KEY_PROV_INFO*)LocalAlloc(LMEM_FIXED, cb);
  6415. if (NULL == pKeyProvInfo)
  6416. {
  6417. hr = E_OUTOFMEMORY;
  6418. goto ErrorOutOfMemory;
  6419. }
  6420. }
  6421. if (0x0 != (pKeyProvInfo->dwFlags & CRYPT_SILENT))
  6422. {
  6423. //have to set silent through msg param
  6424. signMsgPara.dwFlags |= CRYPT_MESSAGE_SILENT_KEYSET_FLAG;
  6425. }
  6426. if( !CryptSignMessage(
  6427. &signMsgPara,
  6428. FALSE,
  6429. 1,
  6430. (const BYTE **) &pRequest->pbData,
  6431. &pRequest->cbData ,
  6432. NULL,
  6433. &pPkcs7Blob->cbData) ||
  6434. (pPkcs7Blob->pbData = (BYTE *)
  6435. MyCoTaskMemAlloc(pPkcs7Blob->cbData)) == NULL ||
  6436. !CryptSignMessage(
  6437. &signMsgPara,
  6438. FALSE,
  6439. 1,
  6440. (const BYTE **) &pRequest->pbData,
  6441. &pRequest->cbData ,
  6442. pPkcs7Blob->pbData,
  6443. &pPkcs7Blob->cbData) )
  6444. goto ErrorCryptSignMessage;
  6445. CommonReturn:
  6446. if (NULL != pKeyProvInfo)
  6447. {
  6448. LocalFree(pKeyProvInfo);
  6449. }
  6450. if (NULL != signMsgPara.rgAuthAttr)
  6451. {
  6452. LocalFree(signMsgPara.rgAuthAttr);
  6453. }
  6454. // don't know if we have an error or not
  6455. // but I do know the errBefore is set properly
  6456. SetLastError(errBefore);
  6457. return(hr);
  6458. ErrorReturn:
  6459. if(GetLastError() == ERROR_SUCCESS)
  6460. SetLastError((DWORD)E_UNEXPECTED);
  6461. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6462. // We have an error, make sure we set it.
  6463. errBefore = GetLastError();
  6464. // on error return a NULL
  6465. if(pPkcs7Blob->pbData != NULL)
  6466. MyCoTaskMemFree(pPkcs7Blob->pbData);
  6467. memset(pPkcs7Blob, 0, sizeof(CRYPT_DATA_BLOB));
  6468. goto CommonReturn;
  6469. TRACE_ERROR(ErrorGetCapiHashAndSigAlgId);
  6470. TRACE_ERROR(ErrorCryptSignMessage);
  6471. TRACE_ERROR(ErrorCryptFindOIDInfo);
  6472. TRACE_ERROR(ErrorOutOfMemory);
  6473. TRACE_ERROR(CertGetCertificateContextPropertyError)
  6474. }
  6475. HRESULT STDMETHODCALLTYPE
  6476. CCEnroll::AddNameValuePairToSignatureWStr(
  6477. /* [in] */ LPWSTR pwszName,
  6478. /* [in] */ LPWSTR pwszValue)
  6479. {
  6480. HRESULT hr = S_OK;
  6481. assert(pwszName != NULL && pwszValue != NULL);
  6482. CRYPT_ENROLLMENT_NAME_VALUE_PAIR nameValuePair = {pwszName, pwszValue};
  6483. CRYPT_ATTR_BLOB blobAttr;
  6484. CRYPT_ATTRIBUTE attr = {szOID_ENROLLMENT_NAME_VALUE_PAIR, 1, &blobAttr};
  6485. CRYPT_ATTRIBUTES attrs = {1, &attr};
  6486. memset(&blobAttr, 0, sizeof(CRYPT_ATTR_BLOB));
  6487. hr = xeEncodeNameValuePair(
  6488. &nameValuePair,
  6489. &blobAttr.pbData,
  6490. &blobAttr.cbData);
  6491. if (S_OK != hr)
  6492. {
  6493. goto error;
  6494. }
  6495. hr = AddAuthenticatedAttributesToPKCS7Request(&attrs);
  6496. error:
  6497. if (NULL != blobAttr.pbData)
  6498. {
  6499. MyCoTaskMemFree(blobAttr.pbData);
  6500. }
  6501. return hr;
  6502. }
  6503. HRESULT STDMETHODCALLTYPE CCEnroll::AddCertTypeToRequestWStr(
  6504. LPWSTR szw) {
  6505. HRESULT hr = S_OK;
  6506. DWORD errBefore = GetLastError();
  6507. CERT_NAME_VALUE nameValue;
  6508. CERT_EXTENSION ext;
  6509. CERT_EXTENSIONS exts = {1, &ext};
  6510. memset(&ext, 0, sizeof(CERT_EXTENSION));
  6511. nameValue.dwValueType = CERT_RDN_BMP_STRING;
  6512. nameValue.Value.cbData = 0;
  6513. nameValue.Value.pbData = (PBYTE) szw;
  6514. ext.pszObjId = szOID_ENROLL_CERTTYPE_EXTENSION;
  6515. if( !CryptEncodeObject(
  6516. CRYPT_ASN_ENCODING,
  6517. X509_UNICODE_ANY_STRING,
  6518. &nameValue,
  6519. NULL,
  6520. &ext.Value.cbData
  6521. ) )
  6522. goto ErrorCryptEncodeObject;
  6523. ext.Value.pbData = (PBYTE)LocalAlloc(LMEM_FIXED, ext.Value.cbData);
  6524. if(NULL == ext.Value.pbData)
  6525. {
  6526. SetLastError(ERROR_OUTOFMEMORY);
  6527. goto ErrorOutOfMemory;
  6528. }
  6529. if( !CryptEncodeObject(
  6530. CRYPT_ASN_ENCODING,
  6531. X509_UNICODE_ANY_STRING,
  6532. &nameValue,
  6533. ext.Value.pbData,
  6534. &ext.Value.cbData
  6535. ) )
  6536. goto ErrorCryptEncodeObject;
  6537. if(S_OK != AddExtensionsToRequest(&exts))
  6538. goto ErrorAddExtensionsToRequest;
  6539. //put cert template extension into CMC stack
  6540. if(!CopyAndPushStackExtension(&ext, TRUE))
  6541. {
  6542. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6543. goto CopyAndPushStackExtensionError;
  6544. }
  6545. CommonReturn:
  6546. if (NULL != ext.Value.pbData)
  6547. {
  6548. LocalFree(ext.Value.pbData);
  6549. }
  6550. // don't know if we have an error or not
  6551. // but I do know the errBefore is set properly
  6552. SetLastError(errBefore);
  6553. return(hr);
  6554. ErrorReturn:
  6555. if(GetLastError() == ERROR_SUCCESS)
  6556. SetLastError((DWORD)E_UNEXPECTED);
  6557. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6558. // We have an error, make sure we set it.
  6559. errBefore = GetLastError();
  6560. goto CommonReturn;
  6561. TRACE_ERROR(ErrorCryptEncodeObject);
  6562. TRACE_ERROR(ErrorAddExtensionsToRequest);
  6563. TRACE_ERROR(ErrorOutOfMemory);
  6564. TRACE_ERROR(CopyAndPushStackExtensionError);
  6565. }
  6566. HRESULT STDMETHODCALLTYPE CCEnroll::AddCertTypeToRequestWStrEx(
  6567. IN LONG lType,
  6568. IN LPCWSTR pwszOIDOrName,
  6569. IN LONG lMajorVersion,
  6570. IN BOOL fMinorVersion,
  6571. IN LONG lMinorVersion)
  6572. {
  6573. HRESULT hr;
  6574. LPCSTR lpszStructType;
  6575. CERT_NAME_VALUE nameValue;
  6576. CERT_TEMPLATE_EXT Template;
  6577. VOID *pv;
  6578. CERT_EXTENSION ext; //free pbData
  6579. DWORD cb = 0;
  6580. CHAR *pszOID = NULL;
  6581. //init
  6582. ZeroMemory(&ext, sizeof(ext));
  6583. ext.fCritical = FALSE;
  6584. if (NULL == pwszOIDOrName)
  6585. {
  6586. hr = E_INVALIDARG;
  6587. goto InvalidArgError;
  6588. }
  6589. switch (lType)
  6590. {
  6591. case XECT_EXTENSION_V1:
  6592. ext.pszObjId = szOID_ENROLL_CERTTYPE_EXTENSION;
  6593. nameValue.dwValueType = CERT_RDN_BMP_STRING;
  6594. nameValue.Value.cbData = 0;
  6595. nameValue.Value.pbData = (BYTE*)pwszOIDOrName;
  6596. pv = (VOID*)&nameValue;
  6597. lpszStructType = X509_UNICODE_ANY_STRING;
  6598. break;
  6599. case XECT_EXTENSION_V2:
  6600. ext.pszObjId = szOID_CERTIFICATE_TEMPLATE;
  6601. //convert wsz OID to ansi
  6602. while (TRUE)
  6603. {
  6604. cb = WideCharToMultiByte(
  6605. GetACP(),
  6606. 0,
  6607. pwszOIDOrName,
  6608. -1,
  6609. pszOID,
  6610. cb,
  6611. NULL,
  6612. NULL);
  6613. if (0 == cb)
  6614. {
  6615. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6616. goto WideCharToMultiByteError;
  6617. }
  6618. if (NULL != pszOID)
  6619. {
  6620. //done
  6621. break;
  6622. }
  6623. pszOID = (CHAR*)LocalAlloc(LMEM_FIXED, cb);
  6624. if (NULL == pszOID)
  6625. {
  6626. hr = E_OUTOFMEMORY;
  6627. goto OutOfMemoryError;
  6628. }
  6629. }
  6630. ZeroMemory(&Template, sizeof(Template));
  6631. Template.pszObjId = pszOID;
  6632. Template.dwMajorVersion = lMajorVersion;
  6633. Template.fMinorVersion = fMinorVersion;
  6634. Template.dwMinorVersion = lMinorVersion;
  6635. pv = (VOID*)&Template;
  6636. lpszStructType = X509_CERTIFICATE_TEMPLATE;
  6637. break;
  6638. default:
  6639. hr = E_INVALIDARG;
  6640. goto InvalidArgError;
  6641. break;
  6642. }
  6643. while (TRUE)
  6644. {
  6645. if (!CryptEncodeObject(
  6646. X509_ASN_ENCODING,
  6647. lpszStructType,
  6648. pv,
  6649. ext.Value.pbData,
  6650. &ext.Value.cbData))
  6651. {
  6652. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6653. goto CryptEncodeObjectError;
  6654. }
  6655. if (NULL != ext.Value.pbData)
  6656. {
  6657. //done
  6658. break;
  6659. }
  6660. ext.Value.pbData = (BYTE*)LocalAlloc(LMEM_FIXED, ext.Value.cbData);
  6661. if (NULL == ext.Value.pbData)
  6662. {
  6663. hr = E_OUTOFMEMORY;
  6664. goto OutOfMemoryError;
  6665. }
  6666. }
  6667. //put cert template extension into CMC stack
  6668. if(!CopyAndPushStackExtension(&ext, TRUE))
  6669. {
  6670. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6671. goto CopyAndPushStackExtensionError;
  6672. }
  6673. hr = S_OK;
  6674. ErrorReturn:
  6675. if (NULL != pszOID)
  6676. {
  6677. LocalFree(pszOID);
  6678. }
  6679. if (NULL != ext.Value.pbData)
  6680. {
  6681. LocalFree(ext.Value.pbData);
  6682. }
  6683. return hr;
  6684. TRACE_ERROR(InvalidArgError)
  6685. TRACE_ERROR(CopyAndPushStackExtensionError)
  6686. TRACE_ERROR(OutOfMemoryError)
  6687. TRACE_ERROR(CryptEncodeObjectError)
  6688. TRACE_ERROR(WideCharToMultiByteError)
  6689. }
  6690. HRESULT STDMETHODCALLTYPE CCEnroll::getProviderTypeWStr(
  6691. IN LPCWSTR pwszProvName,
  6692. OUT LONG * plProvType)
  6693. {
  6694. HRESULT hr;
  6695. DWORD i = 0;
  6696. DWORD cb;
  6697. DWORD dwProvType;
  6698. WCHAR *pwszEnumProvName = NULL;
  6699. if (NULL == pwszProvName)
  6700. {
  6701. hr = E_INVALIDARG;
  6702. goto InvalidArgError;
  6703. }
  6704. //init
  6705. *plProvType = -1;
  6706. while (TRUE)
  6707. {
  6708. while (TRUE)
  6709. {
  6710. if (!CryptEnumProvidersU(
  6711. i,
  6712. NULL,
  6713. 0,
  6714. &dwProvType,
  6715. pwszEnumProvName,
  6716. &cb))
  6717. {
  6718. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6719. if (MY_HRESULT_FROM_WIN32(NTE_PROV_TYPE_ENTRY_BAD) == hr)
  6720. {
  6721. //skip bad one and goto next
  6722. assert(NULL == pwszEnumProvName);
  6723. break; //skip this one
  6724. }
  6725. //error
  6726. goto CryptEnumProvidersUError;
  6727. }
  6728. if (NULL != pwszEnumProvName)
  6729. {
  6730. //get the current csp name
  6731. break;
  6732. }
  6733. pwszEnumProvName = (WCHAR*)LocalAlloc(LMEM_FIXED, cb);
  6734. if (NULL == pwszEnumProvName)
  6735. {
  6736. hr = E_OUTOFMEMORY;
  6737. goto OutOfMemoryError;
  6738. }
  6739. }
  6740. if (NULL != pwszEnumProvName)
  6741. {
  6742. if (0 == _wcsicmp(pwszProvName, pwszEnumProvName))
  6743. {
  6744. //found matched name
  6745. *plProvType = (LONG)dwProvType;
  6746. break; //out of outer loop
  6747. }
  6748. }
  6749. //not mached, go to next one
  6750. ++i;
  6751. if (NULL != pwszEnumProvName)
  6752. {
  6753. LocalFree(pwszEnumProvName);
  6754. pwszEnumProvName = NULL;
  6755. }
  6756. }
  6757. hr = S_OK;
  6758. ErrorReturn:
  6759. if (NULL != pwszEnumProvName)
  6760. {
  6761. LocalFree(pwszEnumProvName);
  6762. }
  6763. return hr;
  6764. TRACE_ERROR(InvalidArgError)
  6765. TRACE_ERROR(OutOfMemoryError)
  6766. TRACE_ERROR(CryptEnumProvidersUError)
  6767. }
  6768. HRESULT STDMETHODCALLTYPE CCEnroll::InstallPKCS7Blob(
  6769. /* [in] */ PCRYPT_DATA_BLOB pBlobPKCS7)
  6770. {
  6771. return InstallPKCS7BlobEx(pBlobPKCS7, NULL);
  6772. }
  6773. HRESULT CCEnroll::InstallPKCS7BlobEx(
  6774. /* [in] */ PCRYPT_DATA_BLOB pBlobPKCS7,
  6775. /* [out] */ LONG *plCertInstalled)
  6776. {
  6777. HRESULT hr = S_OK;
  6778. DWORD errBefore = GetLastError();
  6779. HCERTSTORE hStoreMsg = NULL;
  6780. LPWSTR pwszTitle = NULL;
  6781. LPWSTR pwszNotSafeAccepting = NULL;
  6782. EnterCriticalSection(&m_csXEnroll);
  6783. // Accepting a request is not safe for scripting: pop up a warning dialog if called from script
  6784. if (0 != m_dwEnabledSafteyOptions) {
  6785. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFEACTION, &pwszTitle);
  6786. if (S_OK != hr) {
  6787. SetLastError(hr);
  6788. goto xeLoadRCStringError;
  6789. }
  6790. hr = xeLoadRCString(hInstanceXEnroll, IDS_NOTSAFE_ACCEPTING_CERT, &pwszNotSafeAccepting);
  6791. if (S_OK != hr) {
  6792. SetLastError(hr);
  6793. goto xeLoadRCStringError;
  6794. }
  6795. if (IDYES != MessageBoxU(NULL, pwszNotSafeAccepting, pwszTitle, MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2)) {
  6796. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  6797. SetLastError(hr);
  6798. goto CancelledError;
  6799. }
  6800. }
  6801. if( !MyCryptQueryObject(CERT_QUERY_OBJECT_BLOB,
  6802. pBlobPKCS7,
  6803. (CERT_QUERY_CONTENT_FLAG_CERT |
  6804. CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
  6805. CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
  6806. CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED) ,
  6807. CERT_QUERY_FORMAT_FLAG_ALL,
  6808. 0,
  6809. NULL,
  6810. NULL,
  6811. NULL,
  6812. &hStoreMsg,
  6813. NULL,
  6814. NULL) )
  6815. goto ErrorCryptQueryObject;
  6816. hr = AddCertsToStores(hStoreMsg, plCertInstalled);
  6817. //don't treat cancel as error but return the err code
  6818. if (S_OK != hr && MY_HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr)
  6819. {
  6820. goto ErrorAddCertsToStores;
  6821. }
  6822. CommonReturn:
  6823. if(hStoreMsg != NULL)
  6824. CertCloseStore(hStoreMsg, 0);
  6825. if (NULL != pwszNotSafeAccepting)
  6826. LocalFree(pwszNotSafeAccepting);
  6827. if (NULL != pwszTitle)
  6828. LocalFree(pwszTitle);
  6829. // don't know if we have an error or not
  6830. // but I do know the errBefore is set properly
  6831. SetLastError(errBefore);
  6832. LeaveCriticalSection(&m_csXEnroll);
  6833. return(hr);
  6834. ErrorReturn:
  6835. if(GetLastError() == ERROR_SUCCESS)
  6836. SetLastError((DWORD)E_UNEXPECTED);
  6837. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6838. // We have an error, make sure we set it.
  6839. errBefore = GetLastError();
  6840. goto CommonReturn;
  6841. TRACE_ERROR(ErrorCryptQueryObject);
  6842. TRACE_ERROR(ErrorAddCertsToStores);
  6843. TRACE_ERROR(CancelledError);
  6844. TRACE_ERROR(xeLoadRCStringError);
  6845. }
  6846. HRESULT STDMETHODCALLTYPE CCEnroll::InstallPKCS7(
  6847. /* [in] */ BSTR wszPKCS7)
  6848. {
  6849. CRYPT_DATA_BLOB blobPKCS7;
  6850. assert(wszPKCS7 != NULL);
  6851. // just put into a blob
  6852. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  6853. blobPKCS7.cbData = SysStringByteLen(wszPKCS7);
  6854. blobPKCS7.pbData = (PBYTE) wszPKCS7;
  6855. // install the blob
  6856. return(InstallPKCS7Blob(&blobPKCS7));
  6857. }
  6858. HRESULT STDMETHODCALLTYPE CCEnroll::InstallPKCS7Ex(
  6859. /* [in] */ BSTR wszPKCS7,
  6860. /* [out] */ LONG __RPC_FAR *plCertInstalled)
  6861. {
  6862. CRYPT_DATA_BLOB blobPKCS7;
  6863. assert(wszPKCS7 != NULL);
  6864. // just put into a blob
  6865. memset(&blobPKCS7, 0, sizeof(CRYPT_DATA_BLOB));
  6866. blobPKCS7.cbData = SysStringByteLen(wszPKCS7);
  6867. blobPKCS7.pbData = (PBYTE) wszPKCS7;
  6868. // install the blob
  6869. return(InstallPKCS7BlobEx(&blobPKCS7, plCertInstalled));
  6870. }
  6871. // this is a scary routine. Put in for louis, use at your own risk.
  6872. HRESULT STDMETHODCALLTYPE CCEnroll::Reset(void)
  6873. {
  6874. HRESULT hr;
  6875. EnterCriticalSection(&m_csXEnroll);
  6876. Destruct();
  6877. hr = Init();
  6878. LeaveCriticalSection(&m_csXEnroll);
  6879. return hr;
  6880. }
  6881. HRESULT STDMETHODCALLTYPE CCEnroll::GetSupportedKeySpec(
  6882. LONG __RPC_FAR *pdwKeySpec) {
  6883. DWORD errBefore = GetLastError();
  6884. DWORD hr = S_OK;
  6885. DWORD cb = sizeof(DWORD);
  6886. SetLastError(ERROR_SUCCESS);
  6887. assert(pdwKeySpec != NULL);
  6888. *pdwKeySpec = 0;
  6889. EnterCriticalSection(&m_csXEnroll);
  6890. hr = GetVerifyProv();
  6891. if (S_OK != hr)
  6892. {
  6893. goto GetVerifyProvError;
  6894. }
  6895. if( !CryptGetProvParam(
  6896. m_hVerifyProv,
  6897. PP_KEYSPEC,
  6898. (BYTE *) pdwKeySpec,
  6899. &cb,
  6900. 0
  6901. ) )
  6902. goto ErrorCryptGetProvParam;
  6903. CommonReturn:
  6904. SetLastError(errBefore);
  6905. LeaveCriticalSection(&m_csXEnroll);
  6906. return(hr);
  6907. ErrorReturn:
  6908. if(GetLastError() == ERROR_SUCCESS)
  6909. SetLastError((DWORD)E_UNEXPECTED);
  6910. // We have an error, make sure we set it.
  6911. errBefore = GetLastError();
  6912. goto CommonReturn;
  6913. TRACE_ERROR(ErrorCryptGetProvParam);
  6914. TRACE_ERROR(GetVerifyProvError);
  6915. }
  6916. HRESULT STDMETHODCALLTYPE CCEnroll::GetKeyLenEx(
  6917. LONG lSizeSpec,
  6918. LONG lKeySpec,
  6919. LONG __RPC_FAR *pdwKeySize)
  6920. {
  6921. BOOL fKeyX;
  6922. BOOL fKeyInc = FALSE;
  6923. DWORD dwKeySize = 0xFFFFFFFF;
  6924. DWORD cb;
  6925. HRESULT hr = S_OK;
  6926. EnterCriticalSection(&m_csXEnroll);
  6927. switch (lKeySpec)
  6928. {
  6929. case XEKL_KEYSPEC_KEYX:
  6930. fKeyX = TRUE;
  6931. break;
  6932. case XEKL_KEYSPEC_SIG:
  6933. fKeyX = FALSE;
  6934. break;
  6935. default:
  6936. //invalid parameter
  6937. hr = E_INVALIDARG;
  6938. goto InvalidArgError;
  6939. }
  6940. switch (lSizeSpec)
  6941. {
  6942. case XEKL_KEYSIZE_MIN:
  6943. case XEKL_KEYSIZE_MAX:
  6944. case XEKL_KEYSIZE_DEFAULT:
  6945. break;
  6946. case XEKL_KEYSIZE_INC:
  6947. fKeyInc = TRUE;
  6948. break;
  6949. default:
  6950. //invalid parameter
  6951. hr = E_INVALIDARG;
  6952. goto InvalidArgError;
  6953. }
  6954. if (!fKeyInc)
  6955. {
  6956. DWORD dwAlg = (fKeyX ? ALG_CLASS_KEY_EXCHANGE : ALG_CLASS_SIGNATURE);
  6957. *pdwKeySize = GetKeySizeInfo(lSizeSpec, dwAlg);
  6958. if(0xFFFFFFFF == *pdwKeySize)
  6959. {
  6960. *pdwKeySize = 0;
  6961. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6962. goto GetKeySizeInfoError;
  6963. }
  6964. }
  6965. else
  6966. {
  6967. if ((fKeyX && (0 != m_dwXhgKeyLenInc)) ||
  6968. (!fKeyX && (0 != m_dwSigKeyLenInc)))
  6969. {
  6970. //we got the cached inc size
  6971. if (fKeyX)
  6972. {
  6973. *pdwKeySize = m_dwXhgKeyLenInc;
  6974. }
  6975. else
  6976. {
  6977. *pdwKeySize = m_dwSigKeyLenInc;
  6978. }
  6979. }
  6980. else
  6981. {
  6982. hr = GetVerifyProv();
  6983. if (S_OK != hr)
  6984. {
  6985. goto GetVerifyProvError;
  6986. }
  6987. //init
  6988. *pdwKeySize = 0;
  6989. cb = sizeof(dwKeySize);
  6990. if (!CryptGetProvParam(
  6991. m_hVerifyProv,
  6992. fKeyX ? PP_KEYX_KEYSIZE_INC : PP_SIG_KEYSIZE_INC,
  6993. (BYTE*)&dwKeySize,
  6994. &cb,
  6995. 0))
  6996. {
  6997. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  6998. goto CryptGetProvParamError;
  6999. }
  7000. else
  7001. {
  7002. *pdwKeySize = dwKeySize;
  7003. //cache it
  7004. if (fKeyX)
  7005. {
  7006. m_dwXhgKeyLenInc = dwKeySize;
  7007. }
  7008. else
  7009. {
  7010. m_dwSigKeyLenInc = dwKeySize;
  7011. }
  7012. }
  7013. }
  7014. }
  7015. ErrorReturn:
  7016. LeaveCriticalSection(&m_csXEnroll);
  7017. return(hr);
  7018. TRACE_ERROR(GetVerifyProvError);
  7019. TRACE_ERROR(CryptGetProvParamError)
  7020. TRACE_ERROR(InvalidArgError)
  7021. TRACE_ERROR(GetKeySizeInfoError)
  7022. }
  7023. HRESULT STDMETHODCALLTYPE CCEnroll::GetKeyLen(
  7024. BOOL fMin,
  7025. BOOL fExchange,
  7026. LONG __RPC_FAR *pdwKeySize) {
  7027. DWORD hr = S_OK;
  7028. LONG lKeySizeSpec = (fMin ? XEKL_KEYSIZE_MIN : XEKL_KEYSIZE_MAX);
  7029. if(fExchange)
  7030. *pdwKeySize = GetKeySizeInfo(lKeySizeSpec, ALG_CLASS_KEY_EXCHANGE);
  7031. else
  7032. *pdwKeySize = GetKeySizeInfo(lKeySizeSpec, ALG_CLASS_SIGNATURE);
  7033. if(*pdwKeySize == 0xFFFFFFFF) {
  7034. *pdwKeySize = 0;
  7035. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7036. }
  7037. return(hr);
  7038. }
  7039. DWORD CCEnroll::GetKeySizeInfo(
  7040. LONG lKeySizeSpec,
  7041. DWORD algClass) {
  7042. DWORD cb = sizeof(PROV_ENUMALGS_EX);
  7043. HRESULT hr = S_OK;
  7044. DWORD errBefore = GetLastError();
  7045. DWORD dwFlags = CRYPT_FIRST;
  7046. PROV_ENUMALGS_EX algInfo;
  7047. DWORD dwKeySize = 0xFFFFFFFF;
  7048. DWORD err = ERROR_SUCCESS;
  7049. #ifdef DBG
  7050. //only accept two flags
  7051. assert(ALG_CLASS_KEY_EXCHANGE == algClass ||
  7052. ALG_CLASS_SIGNATURE == algClass);
  7053. #endif //DBG
  7054. SetLastError(ERROR_SUCCESS);
  7055. memset(&algInfo, 0, sizeof(algInfo));
  7056. EnterCriticalSection(&m_csXEnroll);
  7057. if ((ALG_CLASS_KEY_EXCHANGE == algClass && 0 != m_dwXhgKeyLenMax) ||
  7058. (ALG_CLASS_SIGNATURE == algClass && 0 != m_dwSigKeyLenMax))
  7059. {
  7060. //got cached sizes, use only KeyLenMax as check
  7061. #if DBG
  7062. if (ALG_CLASS_KEY_EXCHANGE == algClass)
  7063. {
  7064. assert(0 != m_dwXhgKeyLenMin);
  7065. assert(0 != m_dwXhgKeyLenDef);
  7066. }
  7067. if (ALG_CLASS_SIGNATURE == algClass)
  7068. {
  7069. assert(0 != m_dwSigKeyLenMin);
  7070. assert(0 != m_dwSigKeyLenDef);
  7071. }
  7072. #endif //DBG
  7073. //OK, cached, easy
  7074. }
  7075. else
  7076. {
  7077. #if DBG
  7078. if (ALG_CLASS_KEY_EXCHANGE == algClass)
  7079. {
  7080. assert(0 == m_dwXhgKeyLenMin);
  7081. assert(0 == m_dwXhgKeyLenDef);
  7082. }
  7083. if (ALG_CLASS_SIGNATURE == algClass)
  7084. {
  7085. assert(0 == m_dwSigKeyLenMin);
  7086. assert(0 == m_dwSigKeyLenDef);
  7087. }
  7088. #endif //DBG
  7089. hr = GetVerifyProv();
  7090. if (S_OK != hr)
  7091. {
  7092. goto GetVerifyProvError;
  7093. }
  7094. while (CryptGetProvParam(
  7095. m_hVerifyProv,
  7096. PP_ENUMALGS_EX,
  7097. (BYTE *) &algInfo,
  7098. &cb,
  7099. dwFlags))
  7100. {
  7101. // get rid of CRYPT_FIRST flag
  7102. dwFlags = 0;
  7103. if (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(algInfo.aiAlgid))
  7104. {
  7105. //cache them
  7106. m_dwXhgKeyLenMax = algInfo.dwMaxLen;
  7107. m_dwXhgKeyLenMin = algInfo.dwMinLen;
  7108. m_dwXhgKeyLenDef = algInfo.dwDefaultLen;
  7109. }
  7110. else if (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(algInfo.aiAlgid))
  7111. {
  7112. m_dwSigKeyLenMax = algInfo.dwMaxLen;
  7113. m_dwSigKeyLenMin = algInfo.dwMinLen;
  7114. m_dwSigKeyLenDef = algInfo.dwDefaultLen;
  7115. }
  7116. //see if we cache all sizes through single enum loop
  7117. if (0 != m_dwXhgKeyLenMax &&
  7118. 0 != m_dwXhgKeyLenMin &&
  7119. 0 != m_dwXhgKeyLenDef &&
  7120. 0 != m_dwSigKeyLenMax &&
  7121. 0 != m_dwSigKeyLenMin &&
  7122. 0 != m_dwSigKeyLenDef)
  7123. {
  7124. //looks we cached all
  7125. break;
  7126. }
  7127. }
  7128. }
  7129. // if we got here,
  7130. // either PP_ENUMALGS_EX is not supported by CSP , should return error
  7131. // or csp doesn't support specified algorithm, should ERROR_NO_MORE_ITEMS
  7132. err = GetLastError();
  7133. if (err != ERROR_SUCCESS)
  7134. {
  7135. if (err != ERROR_NO_MORE_ITEMS)
  7136. {
  7137. goto ErrorCryptGetProvParam;
  7138. }
  7139. // should be ERROR_NO_MORE_ITEMS
  7140. if ((ALG_CLASS_KEY_EXCHANGE == algClass && 0 != m_dwXhgKeyLenMax) ||
  7141. (ALG_CLASS_SIGNATURE == algClass && 0 != m_dwSigKeyLenMax))
  7142. {
  7143. //we may get here because the csp is signature or exchange only
  7144. //so we cannot cache both once
  7145. SetLastError(ERROR_SUCCESS);
  7146. }
  7147. else
  7148. {
  7149. SetLastError((DWORD)NTE_BAD_ALGID);
  7150. }
  7151. }
  7152. //should have all sizes
  7153. if(XEKL_KEYSIZE_MIN == lKeySizeSpec)
  7154. {
  7155. if (ALG_CLASS_KEY_EXCHANGE == algClass)
  7156. {
  7157. dwKeySize = m_dwXhgKeyLenMin;
  7158. }
  7159. else
  7160. {
  7161. dwKeySize = m_dwSigKeyLenMin;
  7162. }
  7163. }
  7164. else if (XEKL_KEYSIZE_MAX == lKeySizeSpec)
  7165. {
  7166. if (ALG_CLASS_KEY_EXCHANGE == algClass)
  7167. {
  7168. dwKeySize = m_dwXhgKeyLenMax;
  7169. }
  7170. else
  7171. {
  7172. dwKeySize = m_dwSigKeyLenMax;
  7173. }
  7174. }
  7175. else if (XEKL_KEYSIZE_DEFAULT == lKeySizeSpec)
  7176. {
  7177. if (ALG_CLASS_KEY_EXCHANGE == algClass)
  7178. {
  7179. dwKeySize = m_dwXhgKeyLenDef;
  7180. }
  7181. else
  7182. {
  7183. dwKeySize = m_dwSigKeyLenDef;
  7184. }
  7185. }
  7186. CommonReturn:
  7187. SetLastError(errBefore);
  7188. LeaveCriticalSection(&m_csXEnroll);
  7189. return(dwKeySize);
  7190. ErrorReturn:
  7191. if(GetLastError() == ERROR_SUCCESS)
  7192. SetLastError((DWORD)E_UNEXPECTED);
  7193. // We have an error, make sure we set it.
  7194. errBefore = GetLastError();
  7195. goto CommonReturn;
  7196. TRACE_ERROR(GetVerifyProvError);
  7197. TRACE_ERROR(ErrorCryptGetProvParam);
  7198. }
  7199. HRESULT STDMETHODCALLTYPE CCEnroll::EnumAlgs(
  7200. /* [in] */ LONG dwIndex,
  7201. /* [in] */ LONG algMask,
  7202. /* [out] */ LONG __RPC_FAR *pdwAlgID) {
  7203. DWORD errBefore = GetLastError();
  7204. PROV_ENUMALGS enumAlgs;
  7205. DWORD cb = sizeof(enumAlgs);
  7206. LONG i = 0;
  7207. HRESULT hr = S_OK;
  7208. DWORD dwFlags;
  7209. BOOL f1st = TRUE;
  7210. SetLastError(ERROR_SUCCESS);
  7211. memset(&enumAlgs, 0, sizeof(enumAlgs));
  7212. assert(pdwAlgID != NULL);
  7213. *pdwAlgID = 0;
  7214. EnterCriticalSection(&m_csXEnroll);
  7215. hr = GetVerifyProv();
  7216. if (S_OK != hr)
  7217. {
  7218. goto GetVerifyProvError;
  7219. }
  7220. if (MAXDWORD != m_dwLastAlgIndex &&
  7221. ((DWORD)dwIndex) == m_dwLastAlgIndex + 1)
  7222. {
  7223. //continue enum
  7224. dwFlags = 0;
  7225. while (f1st || (DWORD)algMask != GET_ALG_CLASS(enumAlgs.aiAlgid))
  7226. {
  7227. if(!CryptGetProvParam(
  7228. m_hVerifyProv,
  7229. PP_ENUMALGS,
  7230. (BYTE*)&enumAlgs,
  7231. &cb,
  7232. dwFlags))
  7233. {
  7234. goto ErrorCryptGetProvParam;
  7235. }
  7236. f1st = FALSE;
  7237. }
  7238. }
  7239. else
  7240. {
  7241. dwFlags = CRYPT_FIRST;
  7242. for (i = 0; i <= dwIndex; i++)
  7243. {
  7244. if(!CryptGetProvParam(
  7245. m_hVerifyProv,
  7246. PP_ENUMALGS,
  7247. (BYTE*)&enumAlgs,
  7248. &cb,
  7249. dwFlags))
  7250. {
  7251. goto ErrorCryptGetProvParam;
  7252. }
  7253. dwFlags = 0;
  7254. // if we have not hit something we are counting, do it again
  7255. if ((DWORD)algMask != GET_ALG_CLASS(enumAlgs.aiAlgid))
  7256. {
  7257. i--;
  7258. }
  7259. }
  7260. }
  7261. //update cached index
  7262. m_dwLastAlgIndex = dwIndex;
  7263. *pdwAlgID = enumAlgs.aiAlgid;
  7264. CommonReturn:
  7265. SetLastError(errBefore);
  7266. LeaveCriticalSection(&m_csXEnroll);
  7267. return(hr);
  7268. ErrorReturn:
  7269. if(GetLastError() == ERROR_SUCCESS)
  7270. SetLastError((DWORD)E_UNEXPECTED);
  7271. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7272. // We have an error, make sure we set it.
  7273. errBefore = GetLastError();
  7274. //error, reset index
  7275. m_dwLastAlgIndex = MAXDWORD;
  7276. goto CommonReturn;
  7277. TRACE_ERROR(GetVerifyProvError);
  7278. TRACE_ERROR(ErrorCryptGetProvParam);
  7279. }
  7280. HRESULT STDMETHODCALLTYPE CCEnroll::GetAlgNameWStr(
  7281. /* [in] */ LONG algID,
  7282. /* [out] */ LPWSTR __RPC_FAR *ppwsz) {
  7283. DWORD errBefore = GetLastError();
  7284. PROV_ENUMALGS enumAlgs;
  7285. DWORD cb = sizeof(enumAlgs);
  7286. HRESULT hr = S_OK;
  7287. DWORD dwFlags = CRYPT_FIRST;
  7288. SetLastError(ERROR_SUCCESS);
  7289. memset(&enumAlgs, 0, sizeof(enumAlgs));
  7290. EnterCriticalSection(&m_csXEnroll);
  7291. hr = GetVerifyProv();
  7292. if (S_OK != hr)
  7293. {
  7294. goto GetVerifyProvError;
  7295. }
  7296. do {
  7297. if( !CryptGetProvParam(
  7298. m_hVerifyProv,
  7299. PP_ENUMALGS,
  7300. (BYTE *) &enumAlgs,
  7301. &cb,
  7302. dwFlags) )
  7303. goto ErrorCryptGetProvParam;
  7304. dwFlags = 0;
  7305. } while((DWORD)algID != enumAlgs.aiAlgid);
  7306. if( (*ppwsz = WideFromMB(enumAlgs.szName)) == NULL )
  7307. goto ErrorOutOfMem;
  7308. CommonReturn:
  7309. SetLastError(errBefore);
  7310. LeaveCriticalSection(&m_csXEnroll);
  7311. return(hr);
  7312. ErrorReturn:
  7313. if(GetLastError() == ERROR_SUCCESS)
  7314. SetLastError((DWORD)E_UNEXPECTED);
  7315. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7316. // We have an error, make sure we set it.
  7317. errBefore = GetLastError();
  7318. goto CommonReturn;
  7319. TRACE_ERROR(GetVerifyProvError);
  7320. TRACE_ERROR(ErrorCryptGetProvParam);
  7321. TRACE_ERROR(ErrorOutOfMem);
  7322. }
  7323. HRESULT STDMETHODCALLTYPE CCEnroll::GetAlgName(
  7324. /* [in] */ LONG algID,
  7325. /* [out][retval] */ BSTR __RPC_FAR *pbstr) {
  7326. DWORD errBefore = GetLastError();
  7327. LPWSTR pwsz = NULL;
  7328. HRESULT hr = S_OK;
  7329. SetLastError(ERROR_SUCCESS);
  7330. assert(pbstr != NULL);
  7331. if((hr = GetAlgNameWStr(algID, &pwsz)) != S_OK)
  7332. goto ErrorgetAlgNameWStr;
  7333. if( (*pbstr = SysAllocString(pwsz)) == NULL )
  7334. goto ErrorSysAllocString;
  7335. CommonReturn:
  7336. if(pwsz != NULL)
  7337. MyCoTaskMemFree(pwsz);
  7338. SetLastError(errBefore);
  7339. return(hr);
  7340. ErrorReturn:
  7341. if(GetLastError() == ERROR_SUCCESS)
  7342. SetLastError((DWORD)E_UNEXPECTED);
  7343. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7344. // We have an error, make sure we set it.
  7345. errBefore = GetLastError();
  7346. goto CommonReturn;
  7347. TRACE_ERROR(ErrorgetAlgNameWStr);
  7348. TRACE_ERROR(ErrorSysAllocString);
  7349. }
  7350. HRESULT STDMETHODCALLTYPE CCEnroll::get_ReuseHardwareKeyIfUnableToGenNew(
  7351. /* [retval][out] */ BOOL __RPC_FAR *fBool) {
  7352. EnterCriticalSection(&m_csXEnroll);
  7353. *fBool = m_fReuseHardwareKeyIfUnableToGenNew;
  7354. LeaveCriticalSection(&m_csXEnroll);
  7355. return(S_OK);
  7356. }
  7357. HRESULT STDMETHODCALLTYPE CCEnroll::put_ReuseHardwareKeyIfUnableToGenNew(
  7358. /* [in] */ BOOL fBool) {
  7359. EnterCriticalSection(&m_csXEnroll);
  7360. m_fReuseHardwareKeyIfUnableToGenNew = fBool;
  7361. LeaveCriticalSection(&m_csXEnroll);
  7362. return(S_OK);
  7363. }
  7364. HRESULT STDMETHODCALLTYPE CCEnroll::SetHStoreMy(
  7365. HCERTSTORE hStore
  7366. ) {
  7367. HRESULT hr = S_OK;
  7368. EnterCriticalSection(&m_csXEnroll);
  7369. if(m_MyStore.hStore != NULL)
  7370. hr = E_ACCESSDENIED;
  7371. else {
  7372. if(m_MyStore.wszName != wszMY)
  7373. MyCoTaskMemFree(m_MyStore.wszName);
  7374. m_MyStore.wszName = NULL;
  7375. m_MyStore.hStore = CertDuplicateStore(hStore);
  7376. }
  7377. LeaveCriticalSection(&m_csXEnroll);
  7378. return(hr);
  7379. }
  7380. HRESULT STDMETHODCALLTYPE CCEnroll::SetHStoreCA(
  7381. HCERTSTORE hStore
  7382. ) {
  7383. HRESULT hr = S_OK;
  7384. EnterCriticalSection(&m_csXEnroll);
  7385. if(m_CAStore.hStore != NULL)
  7386. hr = E_ACCESSDENIED;
  7387. else {
  7388. if(m_CAStore.wszName != wszCA)
  7389. MyCoTaskMemFree(m_CAStore.wszName);
  7390. m_CAStore.wszName = NULL;
  7391. m_CAStore.hStore = CertDuplicateStore(hStore);
  7392. }
  7393. LeaveCriticalSection(&m_csXEnroll);
  7394. return(hr);
  7395. }
  7396. HRESULT STDMETHODCALLTYPE CCEnroll::SetHStoreROOT(
  7397. HCERTSTORE hStore
  7398. ) {
  7399. HRESULT hr = S_OK;
  7400. EnterCriticalSection(&m_csXEnroll);
  7401. if(m_RootStore.hStore != NULL)
  7402. hr = E_ACCESSDENIED;
  7403. else {
  7404. if(m_RootStore.wszName != wszROOT && m_RootStore.wszName != wszCA)
  7405. MyCoTaskMemFree(m_RootStore.wszName);
  7406. m_RootStore.wszName = NULL;
  7407. m_RootStore.hStore = CertDuplicateStore(hStore);
  7408. }
  7409. LeaveCriticalSection(&m_csXEnroll);
  7410. return(hr);
  7411. }
  7412. HRESULT STDMETHODCALLTYPE CCEnroll::SetHStoreRequest(
  7413. HCERTSTORE hStore
  7414. ) {
  7415. HRESULT hr = S_OK;
  7416. EnterCriticalSection(&m_csXEnroll);
  7417. if(m_RequestStore.hStore != NULL)
  7418. hr = E_ACCESSDENIED;
  7419. else {
  7420. if(m_RequestStore.wszName != wszREQUEST)
  7421. MyCoTaskMemFree(m_RequestStore.wszName);
  7422. m_RequestStore.wszName = NULL;
  7423. m_RequestStore.hStore = CertDuplicateStore(hStore);
  7424. }
  7425. LeaveCriticalSection(&m_csXEnroll);
  7426. return(hr);
  7427. }
  7428. HRESULT STDMETHODCALLTYPE CCEnroll::put_LimitExchangeKeyToEncipherment(
  7429. BOOL fBool
  7430. ) {
  7431. EnterCriticalSection(&m_csXEnroll);
  7432. m_fLimitExchangeKeyToEncipherment = fBool;
  7433. LeaveCriticalSection(&m_csXEnroll);
  7434. return(S_OK);
  7435. }
  7436. HRESULT STDMETHODCALLTYPE CCEnroll::get_LimitExchangeKeyToEncipherment(
  7437. BOOL * fBool
  7438. ) {
  7439. EnterCriticalSection(&m_csXEnroll);
  7440. *fBool = m_fLimitExchangeKeyToEncipherment;
  7441. LeaveCriticalSection(&m_csXEnroll);
  7442. return(S_OK);
  7443. }
  7444. HRESULT STDMETHODCALLTYPE CCEnroll::put_EnableSMIMECapabilities(
  7445. BOOL fSMIME
  7446. )
  7447. {
  7448. HRESULT hr;
  7449. EnterCriticalSection(&m_csXEnroll);
  7450. if (m_fKeySpecSetByClient)
  7451. {
  7452. //SMIME is set by the client
  7453. if (AT_SIGNATURE == m_keyProvInfo.dwKeySpec && fSMIME)
  7454. {
  7455. //try to set signature key spec also SMIME
  7456. hr = XENROLL_E_KEYSPEC_SMIME_MISMATCH;
  7457. goto MismatchError;
  7458. }
  7459. }
  7460. else
  7461. {
  7462. //user didn't set key spec
  7463. //determine the spec accordingly
  7464. m_keyProvInfo.dwKeySpec = fSMIME ? AT_KEYEXCHANGE : AT_SIGNATURE;
  7465. }
  7466. m_fEnableSMIMECapabilities = fSMIME;
  7467. m_fSMIMESetByClient = TRUE;
  7468. hr = S_OK;
  7469. ErrorReturn:
  7470. LeaveCriticalSection(&m_csXEnroll);
  7471. return(hr);
  7472. TRACE_ERROR(MismatchError)
  7473. }
  7474. HRESULT STDMETHODCALLTYPE CCEnroll::get_EnableSMIMECapabilities(
  7475. BOOL * fBool
  7476. ) {
  7477. EnterCriticalSection(&m_csXEnroll);
  7478. *fBool = m_fEnableSMIMECapabilities;
  7479. LeaveCriticalSection(&m_csXEnroll);
  7480. return(S_OK);
  7481. }
  7482. //ICEnroll4
  7483. HRESULT
  7484. GetCertificateContextFromBStr(
  7485. IN BSTR bstrCert,
  7486. OUT PCCERT_CONTEXT *ppCert)
  7487. {
  7488. HRESULT hr;
  7489. PCCERT_CONTEXT pCert = NULL;
  7490. BYTE *pbCert = NULL;
  7491. DWORD cbCert = 0;
  7492. // could be any form, binary or base64
  7493. while (TRUE)
  7494. {
  7495. if (!MyCryptStringToBinaryW(
  7496. (WCHAR*)bstrCert,
  7497. SysStringLen(bstrCert),
  7498. CRYPT_STRING_ANY,
  7499. pbCert,
  7500. &cbCert,
  7501. NULL,
  7502. NULL))
  7503. {
  7504. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7505. goto MyCryptStringToBinaryWError;
  7506. }
  7507. if (NULL != pbCert)
  7508. {
  7509. break; //done
  7510. }
  7511. pbCert = (BYTE*)LocalAlloc(LMEM_FIXED, cbCert);
  7512. if (NULL == pbCert)
  7513. {
  7514. hr = E_OUTOFMEMORY;
  7515. goto OutOfMemoryError;
  7516. }
  7517. }
  7518. pCert = CertCreateCertificateContext(
  7519. X509_ASN_ENCODING,
  7520. pbCert,
  7521. cbCert);
  7522. if (NULL == pCert)
  7523. {
  7524. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7525. goto CertCreateCertificateContextError;
  7526. }
  7527. *ppCert = pCert;
  7528. pCert = NULL;
  7529. hr = S_OK;
  7530. ErrorReturn:
  7531. if (NULL != pbCert)
  7532. {
  7533. LocalFree(pbCert);
  7534. }
  7535. if (NULL != pCert)
  7536. {
  7537. CertFreeCertificateContext(pCert);
  7538. }
  7539. return (hr);
  7540. TRACE_ERROR(CertCreateCertificateContextError)
  7541. TRACE_ERROR(MyCryptStringToBinaryWError)
  7542. TRACE_ERROR(OutOfMemoryError)
  7543. }
  7544. HRESULT STDMETHODCALLTYPE
  7545. CCEnroll::put_PrivateKeyArchiveCertificate(
  7546. IN BSTR bstrCert)
  7547. {
  7548. HRESULT hr;
  7549. PCCERT_CONTEXT pPrivateKeyArchiveCert = NULL;
  7550. if (NULL != bstrCert)
  7551. {
  7552. hr = GetCertificateContextFromBStr(bstrCert, &pPrivateKeyArchiveCert);
  7553. if (S_OK != hr)
  7554. {
  7555. goto GetCertificateContextFromBStrError;
  7556. }
  7557. }
  7558. // set key archive certificate
  7559. hr = SetPrivateKeyArchiveCertificate(pPrivateKeyArchiveCert);
  7560. if (S_OK != hr)
  7561. {
  7562. goto SetPrivateKeyArchiveCertificateError;
  7563. }
  7564. hr = S_OK;
  7565. ErrorReturn:
  7566. if (NULL != pPrivateKeyArchiveCert)
  7567. {
  7568. CertFreeCertificateContext(pPrivateKeyArchiveCert);
  7569. }
  7570. return hr;
  7571. TRACE_ERROR(GetCertificateContextFromBStrError)
  7572. TRACE_ERROR(SetPrivateKeyArchiveCertificateError)
  7573. }
  7574. HRESULT STDMETHODCALLTYPE
  7575. CCEnroll::get_PrivateKeyArchiveCertificate(
  7576. OUT BSTR __RPC_FAR *pbstrCert)
  7577. {
  7578. HRESULT hr;
  7579. PCCERT_CONTEXT pPrivateKeyArchiveCert = NULL;
  7580. CRYPT_DATA_BLOB blobCert;
  7581. //init
  7582. *pbstrCert = NULL;
  7583. pPrivateKeyArchiveCert = GetPrivateKeyArchiveCertificate();
  7584. if (NULL != pPrivateKeyArchiveCert)
  7585. {
  7586. blobCert.pbData = pPrivateKeyArchiveCert->pbCertEncoded;
  7587. blobCert.cbData = pPrivateKeyArchiveCert->cbCertEncoded;
  7588. hr = BlobToBstring(&blobCert, CRYPT_STRING_BASE64HEADER, pbstrCert);
  7589. if (S_OK != hr)
  7590. {
  7591. goto BlobToBstringError;
  7592. }
  7593. }
  7594. hr = S_OK;
  7595. ErrorReturn:
  7596. if (NULL != pPrivateKeyArchiveCert)
  7597. {
  7598. CertFreeCertificateContext(pPrivateKeyArchiveCert);
  7599. }
  7600. return hr;
  7601. TRACE_ERROR(BlobToBstringError)
  7602. }
  7603. HRESULT STDMETHODCALLTYPE
  7604. CCEnroll::put_ThumbPrint(IN BSTR bstrThumbPrint)
  7605. {
  7606. CRYPT_DATA_BLOB hashBlob;
  7607. HRESULT hr;
  7608. if (bstrThumbPrint == NULL)
  7609. return E_INVALIDARG;
  7610. hashBlob.cbData = 0;
  7611. hashBlob.pbData = NULL;
  7612. if (!MyCryptStringToBinaryW
  7613. ((WCHAR*)bstrThumbPrint,
  7614. SysStringLen(bstrThumbPrint),
  7615. CRYPT_STRING_BASE64,
  7616. hashBlob.pbData,
  7617. &hashBlob.cbData,
  7618. NULL,
  7619. NULL))
  7620. goto MyCryptToBinaryErr;
  7621. hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
  7622. if (NULL == hashBlob.pbData)
  7623. goto MemoryErr;
  7624. if (!MyCryptStringToBinaryW
  7625. ((WCHAR*)bstrThumbPrint,
  7626. SysStringLen(bstrThumbPrint),
  7627. CRYPT_STRING_BASE64,
  7628. hashBlob.pbData,
  7629. &hashBlob.cbData,
  7630. NULL,
  7631. NULL))
  7632. goto MyCryptToBinaryErr;
  7633. hr = this->put_ThumbPrintWStr(hashBlob);
  7634. ErrorReturn:
  7635. if (NULL != hashBlob.pbData) { LocalFree(hashBlob.pbData); }
  7636. return hr;
  7637. SET_HRESULT(MyCryptToBinaryErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  7638. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  7639. }
  7640. HRESULT STDMETHODCALLTYPE
  7641. CCEnroll::put_ThumbPrintWStr(IN CRYPT_DATA_BLOB hashBlob)
  7642. {
  7643. if (hashBlob.pbData == NULL)
  7644. return E_INVALIDARG;
  7645. if (m_hashBlobPendingRequest.pbData != NULL)
  7646. {
  7647. LocalFree(m_hashBlobPendingRequest.pbData);
  7648. m_hashBlobPendingRequest.pbData = NULL;
  7649. }
  7650. m_hashBlobPendingRequest.cbData = hashBlob.cbData;
  7651. m_hashBlobPendingRequest.pbData = (LPBYTE)LocalAlloc(LPTR, m_hashBlobPendingRequest.cbData);
  7652. if (m_hashBlobPendingRequest.pbData == NULL)
  7653. return E_OUTOFMEMORY;
  7654. CopyMemory(m_hashBlobPendingRequest.pbData, hashBlob.pbData, hashBlob.cbData);
  7655. return S_OK;
  7656. }
  7657. HRESULT STDMETHODCALLTYPE
  7658. CCEnroll::get_ThumbPrint(OUT BSTR __RPC_FAR *pbstrThumbPrint)
  7659. {
  7660. CRYPT_DATA_BLOB hashBlob;
  7661. DWORD cchThumbPrintStr;
  7662. HRESULT hr;
  7663. WCHAR *pwszThumbPrint = NULL;
  7664. int i, n;
  7665. // Input validation:
  7666. if (pbstrThumbPrint == NULL)
  7667. return E_INVALIDARG;
  7668. // Initialize locals:
  7669. ZeroMemory(&hashBlob, sizeof(hashBlob));
  7670. *pbstrThumbPrint = NULL;
  7671. if (S_OK != (hr = this->get_ThumbPrintWStr(&hashBlob)))
  7672. goto ErrorReturn;
  7673. hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
  7674. if (NULL == hashBlob.pbData)
  7675. goto MemoryErr;
  7676. if (S_OK != (hr = this->get_ThumbPrintWStr(&hashBlob)))
  7677. goto ErrorReturn;
  7678. // Now we have a binary thumbprint. Convert this to base64:
  7679. while (TRUE)
  7680. {
  7681. if (!MyCryptBinaryToStringW(
  7682. hashBlob.pbData,
  7683. hashBlob.cbData,
  7684. CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR,
  7685. pwszThumbPrint,
  7686. &cchThumbPrintStr))
  7687. {
  7688. goto MyCryptToStringErr;
  7689. }
  7690. if (NULL != pwszThumbPrint)
  7691. {
  7692. //done
  7693. break;
  7694. }
  7695. pwszThumbPrint = (WCHAR*)LocalAlloc(LMEM_FIXED,
  7696. cchThumbPrintStr * sizeof(WCHAR));
  7697. if (NULL == pwszThumbPrint)
  7698. {
  7699. goto MemoryErr;
  7700. }
  7701. }
  7702. //make sure no new line and CR
  7703. n = (int)wcslen(pwszThumbPrint);
  7704. for (i = n - 1; i > -1; --i)
  7705. {
  7706. if (L'\r' != pwszThumbPrint[i] &&
  7707. L'\n' != pwszThumbPrint[i])
  7708. {
  7709. break; //done
  7710. }
  7711. pwszThumbPrint[i] = L'\0'; //null it
  7712. }
  7713. // Ok, we've acquired the HASH. Now copy it to the out parameter:
  7714. *pbstrThumbPrint = SysAllocString(pwszThumbPrint);
  7715. if (NULL == *pbstrThumbPrint)
  7716. {
  7717. goto MemoryErr;
  7718. }
  7719. hr = S_OK;
  7720. ErrorReturn:
  7721. if (NULL != hashBlob.pbData)
  7722. {
  7723. LocalFree(hashBlob.pbData);
  7724. }
  7725. if (NULL != pwszThumbPrint)
  7726. {
  7727. LocalFree(pwszThumbPrint);
  7728. }
  7729. return hr;
  7730. SET_HRESULT(MyCryptToStringErr, MY_HRESULT_FROM_WIN32(GetLastError()))
  7731. SET_HRESULT(MemoryErr, E_OUTOFMEMORY)
  7732. }
  7733. HRESULT STDMETHODCALLTYPE
  7734. CCEnroll::get_ThumbPrintWStr(IN OUT PCRYPT_DATA_BLOB pHashBlob) {
  7735. HRESULT hr = S_OK;
  7736. // Input validation:
  7737. if (NULL == pHashBlob)
  7738. return E_INVALIDARG;
  7739. // TWO CASES:
  7740. //
  7741. // 1) the thumbprint has been explicitly set by an external caller.
  7742. // 2) the thumbprint _wasn't_ explicitly set. In this case, use the thumbprint
  7743. // of the request generated by the last call to createPKCS10().
  7744. //
  7745. // CASE 1:
  7746. //
  7747. if (NULL != m_hashBlobPendingRequest.pbData)
  7748. {
  7749. if (NULL != pHashBlob->pbData)
  7750. {
  7751. if (pHashBlob->cbData < m_hashBlobPendingRequest.cbData) {
  7752. hr = MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  7753. }
  7754. else {
  7755. CopyMemory(pHashBlob->pbData, m_hashBlobPendingRequest.pbData, m_hashBlobPendingRequest.cbData);
  7756. hr = S_OK;
  7757. }
  7758. }
  7759. pHashBlob->cbData = m_hashBlobPendingRequest.cbData;
  7760. return hr;
  7761. }
  7762. // CASE 2:
  7763. //
  7764. else
  7765. {
  7766. if (NULL == m_pCertContextPendingRequest)
  7767. return E_POINTER;
  7768. // Executes at most twice.
  7769. if (!CertGetCertificateContextProperty
  7770. (m_pCertContextPendingRequest,
  7771. CERT_HASH_PROP_ID,
  7772. (LPVOID)(pHashBlob->pbData),
  7773. &(pHashBlob->cbData)))
  7774. {
  7775. return MY_HRESULT_FROM_WIN32(GetLastError());
  7776. }
  7777. return S_OK;
  7778. }
  7779. }
  7780. HRESULT STDMETHODCALLTYPE
  7781. CCEnroll::binaryToString(
  7782. IN LONG Flags,
  7783. IN BSTR strBinary,
  7784. OUT BSTR *pstrEncoded)
  7785. {
  7786. HRESULT hr;
  7787. CRYPT_DATA_BLOB blobBinary;
  7788. WCHAR *pwszEncoded = NULL;
  7789. blobBinary.pbData = (BYTE*)strBinary;
  7790. blobBinary.cbData = SysStringByteLen(strBinary);
  7791. hr = binaryBlobToString(Flags, &blobBinary, &pwszEncoded);
  7792. if (S_OK != hr)
  7793. {
  7794. goto binaryBlobToStringError;
  7795. }
  7796. *pstrEncoded = SysAllocString(pwszEncoded);
  7797. if (NULL == pstrEncoded)
  7798. {
  7799. hr = E_OUTOFMEMORY;
  7800. goto SysAllocStringLenError;
  7801. }
  7802. hr = S_OK;
  7803. ErrorReturn:
  7804. if (NULL != pwszEncoded)
  7805. {
  7806. MyCoTaskMemFree(pwszEncoded);
  7807. }
  7808. return hr;
  7809. TRACE_ERROR(binaryBlobToStringError);
  7810. TRACE_ERROR(SysAllocStringLenError);
  7811. }
  7812. HRESULT STDMETHODCALLTYPE
  7813. CCEnroll::stringToBinary(
  7814. IN LONG Flags,
  7815. IN BSTR strEncoded,
  7816. OUT BSTR *pstrBinary)
  7817. {
  7818. HRESULT hr;
  7819. CRYPT_DATA_BLOB blobBinary;
  7820. ZeroMemory(&blobBinary, sizeof(blobBinary));
  7821. hr = stringToBinaryBlob(Flags, (LPCWSTR)strEncoded, &blobBinary, NULL, NULL);
  7822. if (S_OK != hr)
  7823. {
  7824. goto stringToBinaryBlobError;
  7825. }
  7826. *pstrBinary = SysAllocStringLen(
  7827. (OLECHAR*)blobBinary.pbData, blobBinary.cbData);
  7828. if (NULL == *pstrBinary)
  7829. {
  7830. hr = E_OUTOFMEMORY;
  7831. goto SysAllocStringLenError;
  7832. }
  7833. hr = S_OK;
  7834. ErrorReturn:
  7835. if (NULL != blobBinary.pbData)
  7836. {
  7837. MyCoTaskMemFree(blobBinary.pbData);
  7838. }
  7839. return hr;
  7840. TRACE_ERROR(stringToBinaryBlobError);
  7841. TRACE_ERROR(SysAllocStringLenError);
  7842. }
  7843. HRESULT STDMETHODCALLTYPE
  7844. CCEnroll::addExtensionToRequest(
  7845. IN LONG Flags,
  7846. IN BSTR strName,
  7847. IN BSTR strValue)
  7848. {
  7849. HRESULT hr;
  7850. CRYPT_DATA_BLOB blobValue;
  7851. DWORD cchStrValue = SysStringLen(strValue);
  7852. BYTE *pbExtVal = NULL;
  7853. DWORD cbExtVal = 0;
  7854. //convert to binary in case base64 etc.
  7855. while (TRUE)
  7856. {
  7857. if (!MyCryptStringToBinaryW(
  7858. (WCHAR*)strValue,
  7859. cchStrValue,
  7860. CRYPT_STRING_ANY,
  7861. pbExtVal,
  7862. &cbExtVal,
  7863. NULL,
  7864. NULL))
  7865. {
  7866. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7867. goto MyCryptStringToBinaryWError;
  7868. }
  7869. if (NULL != pbExtVal)
  7870. {
  7871. //done
  7872. break;
  7873. }
  7874. pbExtVal = (BYTE*)LocalAlloc(LMEM_FIXED, cbExtVal);
  7875. if (NULL == pbExtVal)
  7876. {
  7877. hr = E_OUTOFMEMORY;
  7878. goto LocalAllocError;
  7879. }
  7880. }
  7881. blobValue.pbData = pbExtVal;
  7882. blobValue.cbData = cbExtVal;
  7883. hr = addExtensionToRequestWStr(Flags, strName, &blobValue);
  7884. if (S_OK != hr)
  7885. {
  7886. goto addExtensionToRequestWStrError;
  7887. }
  7888. hr = S_OK;
  7889. ErrorReturn:
  7890. if (NULL != pbExtVal)
  7891. {
  7892. LocalFree(pbExtVal);
  7893. }
  7894. return hr;
  7895. TRACE_ERROR(MyCryptStringToBinaryWError)
  7896. TRACE_ERROR(LocalAllocError)
  7897. TRACE_ERROR(addExtensionToRequestWStrError)
  7898. }
  7899. HRESULT STDMETHODCALLTYPE
  7900. CCEnroll::addAttributeToRequest(
  7901. IN LONG Flags,
  7902. IN BSTR strName,
  7903. IN BSTR strValue)
  7904. {
  7905. HRESULT hr;
  7906. CRYPT_DATA_BLOB blobValue;
  7907. DWORD cchStrValue = SysStringLen(strValue);
  7908. BYTE *pbAttVal = NULL;
  7909. DWORD cbAttVal = 0;
  7910. //convert to binary in case base64 etc.
  7911. while (TRUE)
  7912. {
  7913. if (!MyCryptStringToBinaryW(
  7914. (WCHAR*)strValue,
  7915. cchStrValue,
  7916. CRYPT_STRING_ANY,
  7917. pbAttVal,
  7918. &cbAttVal,
  7919. NULL,
  7920. NULL))
  7921. {
  7922. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  7923. goto MyCryptStringToBinaryWError;
  7924. }
  7925. if (NULL != pbAttVal)
  7926. {
  7927. //done
  7928. break;
  7929. }
  7930. pbAttVal = (BYTE*)LocalAlloc(LMEM_FIXED, cbAttVal);
  7931. if (NULL == pbAttVal)
  7932. {
  7933. hr = E_OUTOFMEMORY;
  7934. goto LocalAllocError;
  7935. }
  7936. }
  7937. blobValue.pbData = pbAttVal;
  7938. blobValue.cbData = cbAttVal;
  7939. hr = addAttributeToRequestWStr(Flags, strName, &blobValue);
  7940. if (S_OK != hr)
  7941. {
  7942. goto addAttributeToRequestWStrError;
  7943. }
  7944. hr = S_OK;
  7945. ErrorReturn:
  7946. if (NULL != pbAttVal)
  7947. {
  7948. LocalFree(pbAttVal);
  7949. }
  7950. return hr;
  7951. TRACE_ERROR(MyCryptStringToBinaryWError)
  7952. TRACE_ERROR(LocalAllocError)
  7953. TRACE_ERROR(addAttributeToRequestWStrError)
  7954. }
  7955. HRESULT STDMETHODCALLTYPE
  7956. CCEnroll::addNameValuePairToRequest(
  7957. IN LONG Flags, //not used
  7958. IN BSTR strName,
  7959. IN BSTR strValue)
  7960. {
  7961. return addNameValuePairToRequestWStr(Flags, strName, strValue);
  7962. }
  7963. HRESULT STDMETHODCALLTYPE CCEnroll::addBlobPropertyToCertificate(
  7964. IN LONG lPropertyId,
  7965. IN LONG lFlags,
  7966. IN BSTR strProperty)
  7967. {
  7968. CRYPT_DATA_BLOB blob;
  7969. blob.pbData = (BYTE*)strProperty;
  7970. blob.cbData = SysStringByteLen(strProperty);
  7971. if (0x0 != (XECP_STRING_PROPERTY & lFlags))
  7972. {
  7973. //this is a string property, including null
  7974. blob.cbData += sizeof(WCHAR);
  7975. }
  7976. return addBlobPropertyToCertificateWStr(lPropertyId, lFlags, &blob);
  7977. }
  7978. HRESULT STDMETHODCALLTYPE
  7979. CCEnroll::put_SignerCertificate(
  7980. IN BSTR bstrCert)
  7981. {
  7982. HRESULT hr;
  7983. PCCERT_CONTEXT pSignerCert = NULL;
  7984. if (NULL != bstrCert)
  7985. {
  7986. hr = GetCertificateContextFromBStr(bstrCert, &pSignerCert);
  7987. if (S_OK != hr)
  7988. {
  7989. goto GetCertificateContextFromBStrError;
  7990. }
  7991. }
  7992. // set key archive certificate
  7993. hr = SetSignerCertificate(pSignerCert);
  7994. if (S_OK != hr)
  7995. {
  7996. goto SetSignerCertificateError;
  7997. }
  7998. hr = S_OK;
  7999. ErrorReturn:
  8000. if (NULL != pSignerCert)
  8001. {
  8002. CertFreeCertificateContext(pSignerCert);
  8003. }
  8004. return hr;
  8005. TRACE_ERROR(GetCertificateContextFromBStrError)
  8006. TRACE_ERROR(SetSignerCertificateError)
  8007. }
  8008. HRESULT STDMETHODCALLTYPE
  8009. CCEnroll::resetExtensions()
  8010. {
  8011. HRESULT hr = S_OK;
  8012. FreeAllStackExtension();
  8013. return hr;
  8014. }
  8015. HRESULT STDMETHODCALLTYPE
  8016. CCEnroll::resetAttributes()
  8017. {
  8018. HRESULT hr = S_OK;
  8019. FreeAllStackAttribute();
  8020. return hr;
  8021. }
  8022. HRESULT STDMETHODCALLTYPE
  8023. CCEnroll::createRequest(
  8024. IN LONG Flags,
  8025. IN BSTR strDNName,
  8026. IN BSTR strUsage,
  8027. OUT BSTR *pstrRequest)
  8028. {
  8029. return createRequestWStrBStr(
  8030. Flags,
  8031. (LPCWSTR)strDNName,
  8032. (LPCWSTR)strUsage,
  8033. CRYPT_STRING_BASE64REQUESTHEADER,
  8034. pstrRequest);
  8035. }
  8036. HRESULT STDMETHODCALLTYPE
  8037. CCEnroll::createFileRequest(
  8038. IN LONG Flags,
  8039. IN BSTR strDNName,
  8040. IN BSTR strUsage,
  8041. IN BSTR strRequestFileName)
  8042. {
  8043. return createFileRequestWStr(Flags, (LPCWSTR)strDNName, (LPCWSTR)strUsage, (LPCWSTR)strRequestFileName);
  8044. }
  8045. HRESULT STDMETHODCALLTYPE
  8046. CCEnroll::acceptResponse(
  8047. IN BSTR bstrResponse)
  8048. {
  8049. HRESULT hr;
  8050. CRYPT_DATA_BLOB blobResponse;
  8051. DWORD cchStrResponse;
  8052. ZeroMemory(&blobResponse, sizeof(blobResponse));
  8053. if (NULL == bstrResponse)
  8054. {
  8055. hr = MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  8056. goto InvalidParameterError;
  8057. }
  8058. //assume a string
  8059. cchStrResponse = SysStringLen(bstrResponse);
  8060. //convert to binary in case base64 etc.
  8061. while (TRUE)
  8062. {
  8063. if (!MyCryptStringToBinaryW(
  8064. (WCHAR*)bstrResponse,
  8065. cchStrResponse,
  8066. CRYPT_STRING_ANY,
  8067. blobResponse.pbData,
  8068. &blobResponse.cbData,
  8069. NULL,
  8070. NULL))
  8071. {
  8072. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8073. goto MyCryptStringToBinaryWError;
  8074. }
  8075. if (NULL != blobResponse.pbData)
  8076. {
  8077. //done
  8078. break;
  8079. }
  8080. blobResponse.pbData = (BYTE*)LocalAlloc(
  8081. LMEM_FIXED, blobResponse.cbData);
  8082. if (NULL == blobResponse.pbData)
  8083. {
  8084. hr = E_OUTOFMEMORY;
  8085. goto LocalAllocError;
  8086. }
  8087. }
  8088. // accept the blob
  8089. hr = acceptResponseBlob(&blobResponse);
  8090. if (S_OK != hr)
  8091. {
  8092. goto acceptResponseBlobError;
  8093. }
  8094. hr = S_OK;
  8095. ErrorReturn:
  8096. if (NULL != blobResponse.pbData)
  8097. {
  8098. LocalFree(blobResponse.pbData);
  8099. }
  8100. return (hr);
  8101. TRACE_ERROR(acceptResponseBlobError)
  8102. TRACE_ERROR(InvalidParameterError)
  8103. TRACE_ERROR(MyCryptStringToBinaryWError)
  8104. TRACE_ERROR(LocalAllocError)
  8105. }
  8106. HRESULT STDMETHODCALLTYPE
  8107. CCEnroll::acceptFileResponse(
  8108. IN BSTR bstrResponseFileName)
  8109. {
  8110. return acceptFileResponseWStr((LPCWSTR)bstrResponseFileName);
  8111. }
  8112. HRESULT
  8113. CCEnroll::GetCertFromResponseBlobToBStr(
  8114. IN CRYPT_DATA_BLOB *pBlobResponse,
  8115. OUT BSTR *pstrCert)
  8116. {
  8117. HRESULT hr;
  8118. CRYPT_DATA_BLOB blobCert;
  8119. PCCERT_CONTEXT pCert = NULL;
  8120. hr = getCertContextFromResponseBlob(
  8121. pBlobResponse,
  8122. &pCert);
  8123. if (S_OK != hr)
  8124. {
  8125. goto getCertContextFromResponseBlobError;
  8126. }
  8127. assert(NULL != pCert);
  8128. blobCert.pbData = pCert->pbCertEncoded;
  8129. blobCert.cbData = pCert->cbCertEncoded;
  8130. hr = BlobToBstring(&blobCert, CRYPT_STRING_BASE64HEADER, pstrCert);
  8131. if (S_OK != hr)
  8132. {
  8133. goto BlobToBstringError;
  8134. }
  8135. hr = S_OK;
  8136. ErrorReturn:
  8137. if (NULL != pCert)
  8138. {
  8139. CertFreeCertificateContext(pCert);
  8140. }
  8141. return hr;
  8142. TRACE_ERROR(getCertContextFromResponseBlobError)
  8143. TRACE_ERROR(BlobToBstringError)
  8144. }
  8145. HRESULT STDMETHODCALLTYPE
  8146. CCEnroll::getCertFromResponse(
  8147. IN BSTR strResponse,
  8148. OUT BSTR *pstrCert)
  8149. {
  8150. HRESULT hr;
  8151. CRYPT_DATA_BLOB blobResponse;
  8152. ZeroMemory(&blobResponse, sizeof(blobResponse));
  8153. if (NULL == strResponse)
  8154. {
  8155. hr = E_POINTER;
  8156. goto NullPointerError;
  8157. }
  8158. hr = BstringToBlob(strResponse, &blobResponse);
  8159. if (S_OK != hr)
  8160. {
  8161. goto BstringToBlobError;
  8162. }
  8163. hr = GetCertFromResponseBlobToBStr(
  8164. &blobResponse,
  8165. pstrCert);
  8166. if (S_OK != hr)
  8167. {
  8168. goto GetCertFromResponseBlobToBStrError;
  8169. }
  8170. hr = S_OK;
  8171. ErrorReturn:
  8172. return hr;
  8173. TRACE_ERROR(NullPointerError)
  8174. TRACE_ERROR(BstringToBlobError)
  8175. TRACE_ERROR(GetCertFromResponseBlobToBStrError)
  8176. }
  8177. HRESULT STDMETHODCALLTYPE
  8178. CCEnroll::getCertFromFileResponse(
  8179. IN BSTR strResponseFileName,
  8180. OUT BSTR *pstrCert)
  8181. {
  8182. HRESULT hr;
  8183. CRYPT_DATA_BLOB blobResponse;
  8184. ZeroMemory(&blobResponse, sizeof(blobResponse));
  8185. hr = xeStringToBinaryFromFile(
  8186. (LPCWSTR)strResponseFileName,
  8187. &blobResponse.pbData,
  8188. &blobResponse.cbData,
  8189. CRYPT_STRING_ANY);
  8190. if (S_OK != hr)
  8191. {
  8192. goto xeStringToBinaryFromFileError;
  8193. }
  8194. hr = GetCertFromResponseBlobToBStr(
  8195. &blobResponse,
  8196. pstrCert);
  8197. if (S_OK != hr)
  8198. {
  8199. goto GetCertFromResponseBlobToBStrError;
  8200. }
  8201. hr = S_OK;
  8202. ErrorReturn:
  8203. if (NULL != blobResponse.pbData)
  8204. {
  8205. LocalFree(blobResponse.pbData);
  8206. }
  8207. return hr;
  8208. TRACE_ERROR(xeStringToBinaryFromFileError)
  8209. TRACE_ERROR(GetCertFromResponseBlobToBStrError)
  8210. }
  8211. //--------------------------------------------------------------------------------
  8212. //
  8213. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  8214. //
  8215. //--------------------------------------------------------------------------------
  8216. HRESULT STDMETHODCALLTYPE
  8217. CCEnroll::createPFX(
  8218. IN BSTR strPassword,
  8219. OUT BSTR *pstrPFX)
  8220. {
  8221. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  8222. return E_ACCESSDENIED;
  8223. return createPFXWStrBStr((LPCWSTR)strPassword, pstrPFX);
  8224. }
  8225. HRESULT STDMETHODCALLTYPE
  8226. CCEnroll::createFilePFX(
  8227. IN BSTR strPassword,
  8228. IN BSTR strPFXFileName)
  8229. {
  8230. return createFilePFXWStr((LPCWSTR)strPassword, (LPCWSTR)strPFXFileName);
  8231. }
  8232. HRESULT STDMETHODCALLTYPE
  8233. CCEnroll::setPendingRequestInfo(
  8234. IN LONG lRequestID,
  8235. IN BSTR strCADNS,
  8236. IN BSTR strCAName,
  8237. IN BSTR strFriendlyName
  8238. )
  8239. {
  8240. return setPendingRequestInfoWStr(
  8241. lRequestID,
  8242. (LPCWSTR)strCADNS,
  8243. (LPCWSTR)strCAName,
  8244. (LPCWSTR)strFriendlyName);
  8245. }
  8246. HRESULT STDMETHODCALLTYPE
  8247. CCEnroll::enumPendingRequest(
  8248. IN LONG lIndex,
  8249. IN LONG lDesiredProperty,
  8250. OUT VARIANT *pvarProperty
  8251. )
  8252. {
  8253. CRYPT_DATA_BLOB dataBlobProperty;
  8254. HRESULT hr;
  8255. LONG lProperty;
  8256. VARIANT varProperty;
  8257. // See if we're initializing an enumeration. If so, just dispatch to
  8258. // enumPendingRequestWStr:
  8259. if (XEPR_ENUM_FIRST == lIndex) {
  8260. return enumPendingRequestWStr(XEPR_ENUM_FIRST, 0, NULL);
  8261. }
  8262. // Input validation:
  8263. if (lIndex < 0 || NULL == pvarProperty)
  8264. return E_INVALIDARG;
  8265. // Initialize locals:
  8266. memset(&varProperty, 0, sizeof(VARIANT));
  8267. memset(&dataBlobProperty, 0, sizeof(CRYPT_DATA_BLOB));
  8268. switch (lDesiredProperty)
  8269. {
  8270. case XEPR_REQUESTID:
  8271. case XEPR_VERSION:
  8272. if (S_OK != (hr = enumPendingRequestWStr(lIndex, lDesiredProperty, &lProperty)))
  8273. goto ErrorReturn;
  8274. varProperty.vt = VT_I4;
  8275. varProperty.lVal = lProperty;
  8276. *pvarProperty = varProperty;
  8277. goto CommonReturn;
  8278. case XEPR_CANAME:
  8279. case XEPR_CAFRIENDLYNAME:
  8280. case XEPR_CADNS:
  8281. case XEPR_HASH:
  8282. case XEPR_V1TEMPLATENAME:
  8283. case XEPR_V2TEMPLATEOID:
  8284. dataBlobProperty.cbData = 0;
  8285. dataBlobProperty.pbData = NULL;
  8286. // Determine the size of the property we desire.
  8287. hr = enumPendingRequestWStr(lIndex, lDesiredProperty, (LPVOID)&dataBlobProperty);
  8288. if (S_OK != hr || 0 == dataBlobProperty.cbData)
  8289. goto ErrorReturn;
  8290. dataBlobProperty.pbData = (LPBYTE)LocalAlloc(LPTR, dataBlobProperty.cbData);
  8291. if (NULL == dataBlobProperty.pbData)
  8292. goto MemoryErr;
  8293. // Request the property, using our newly allocated buffer.
  8294. hr = enumPendingRequestWStr(lIndex, lDesiredProperty, (LPVOID)&dataBlobProperty);
  8295. if (hr != S_OK)
  8296. goto ErrorReturn;
  8297. varProperty.vt = VT_BSTR;
  8298. varProperty.bstrVal = SysAllocStringByteLen((LPCSTR)dataBlobProperty.pbData, dataBlobProperty.cbData);
  8299. if (NULL == varProperty.bstrVal)
  8300. goto MemoryErr;
  8301. *pvarProperty = varProperty;
  8302. goto CommonReturn;
  8303. case XEPR_DATE:
  8304. goto NotImplErr;
  8305. default:
  8306. goto InvalidArgErr;
  8307. }
  8308. CommonReturn:
  8309. if (NULL != dataBlobProperty.pbData) { LocalFree(dataBlobProperty.pbData); }
  8310. return hr;
  8311. ErrorReturn:
  8312. if (NULL != varProperty.bstrVal) { SysFreeString(varProperty.bstrVal); }
  8313. goto CommonReturn;
  8314. SET_HRESULT(InvalidArgErr, E_INVALIDARG);
  8315. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  8316. SET_HRESULT(NotImplErr, E_NOTIMPL);
  8317. }
  8318. HRESULT STDMETHODCALLTYPE
  8319. CCEnroll::removePendingRequest(
  8320. IN BSTR bstrThumbPrint
  8321. )
  8322. {
  8323. CRYPT_DATA_BLOB hashBlob;
  8324. HRESULT hr;
  8325. if (bstrThumbPrint == NULL)
  8326. return E_INVALIDARG;
  8327. hashBlob.cbData = 0;
  8328. hashBlob.pbData = NULL;
  8329. if (!MyCryptStringToBinaryW
  8330. ((WCHAR*)bstrThumbPrint,
  8331. SysStringLen(bstrThumbPrint),
  8332. CRYPT_STRING_ANY,
  8333. hashBlob.pbData,
  8334. &hashBlob.cbData,
  8335. NULL,
  8336. NULL))
  8337. goto MyCryptToBinaryErr;
  8338. hashBlob.pbData = (LPBYTE)LocalAlloc(LPTR, hashBlob.cbData);
  8339. if (NULL == hashBlob.pbData)
  8340. goto MemoryErr;
  8341. if (!MyCryptStringToBinaryW
  8342. ((WCHAR*)bstrThumbPrint,
  8343. SysStringLen(bstrThumbPrint),
  8344. CRYPT_STRING_ANY,
  8345. hashBlob.pbData,
  8346. &hashBlob.cbData,
  8347. NULL,
  8348. NULL))
  8349. goto MyCryptToBinaryErr;
  8350. hr = this->removePendingRequestWStr(hashBlob);
  8351. CommonReturn:
  8352. if (NULL != hashBlob.pbData) { LocalFree(hashBlob.pbData); }
  8353. return hr;
  8354. ErrorReturn:
  8355. goto CommonReturn;
  8356. SET_HRESULT(MyCryptToBinaryErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  8357. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  8358. }
  8359. //IEnroll4
  8360. HRESULT
  8361. myCertGetNameString(
  8362. IN PCCERT_CONTEXT pCert,
  8363. IN BOOL fIssuer,
  8364. OUT WCHAR **ppwszName)
  8365. {
  8366. HRESULT hr;
  8367. DWORD dwFlags = fIssuer ? CERT_NAME_ISSUER_FLAG : 0;
  8368. DWORD dwTypePara;
  8369. WCHAR *pwszName = NULL;
  8370. DWORD cch = 0;
  8371. while (TRUE)
  8372. {
  8373. cch = CertGetNameStringW(
  8374. pCert,
  8375. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  8376. dwFlags,
  8377. (void*)&dwTypePara,
  8378. pwszName,
  8379. cch);
  8380. if (0 == cch)
  8381. {
  8382. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8383. goto CertGetNameStringError;
  8384. }
  8385. if (NULL != pwszName)
  8386. {
  8387. //done
  8388. break;
  8389. }
  8390. pwszName = (WCHAR*)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR));
  8391. if (NULL == pwszName)
  8392. {
  8393. hr = E_OUTOFMEMORY;
  8394. goto OutOfMemoryError;
  8395. }
  8396. }
  8397. *ppwszName = pwszName;
  8398. pwszName = NULL;
  8399. hr = S_OK;
  8400. ErrorReturn:
  8401. if (NULL != pwszName)
  8402. {
  8403. LocalFree(pwszName);
  8404. }
  8405. return hr;
  8406. TRACE_ERROR(CertGetNameStringError)
  8407. TRACE_ERROR(OutOfMemoryError)
  8408. }
  8409. HRESULT CCEnroll::GetGoodCertContext(
  8410. IN PCCERT_CONTEXT pCertContext,
  8411. OUT PCCERT_CONTEXT *ppGoodCertContext)
  8412. {
  8413. HRESULT hr;
  8414. PCCERT_CONTEXT pGoodCertContext = NULL;
  8415. DWORD cb;
  8416. //init
  8417. *ppGoodCertContext = NULL;
  8418. if(pCertContext == NULL)
  8419. {
  8420. hr = MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  8421. goto InvalidParameterError;
  8422. }
  8423. //see if the passed cert has kpi
  8424. if(CertGetCertificateContextProperty(
  8425. pCertContext,
  8426. CERT_KEY_PROV_INFO_PROP_ID,
  8427. NULL,
  8428. &cb))
  8429. {
  8430. //this means kpi exists, passed cert is good
  8431. pGoodCertContext = CertDuplicateCertificateContext(pCertContext);
  8432. if (NULL == pGoodCertContext)
  8433. {
  8434. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8435. goto CertDuplicateCertificateContextError;
  8436. }
  8437. }
  8438. *ppGoodCertContext = pGoodCertContext;
  8439. pGoodCertContext = NULL;
  8440. hr = S_OK;
  8441. ErrorReturn:
  8442. if (NULL != pGoodCertContext)
  8443. {
  8444. CertFreeCertificateContext(pGoodCertContext);
  8445. }
  8446. return hr;
  8447. TRACE_ERROR(InvalidParameterError)
  8448. TRACE_ERROR(CertDuplicateCertificateContextError)
  8449. }
  8450. HRESULT STDMETHODCALLTYPE CCEnroll::SetSignerCertificate(
  8451. IN PCCERT_CONTEXT pCertContext)
  8452. {
  8453. HRESULT hr;
  8454. PCCERT_CONTEXT pCertGoodContext = NULL;
  8455. EnterCriticalSection(&m_csXEnroll);
  8456. hr = GetGoodCertContext(pCertContext, &pCertGoodContext);
  8457. if (S_OK != hr)
  8458. {
  8459. goto GetGoodCertContextError;
  8460. }
  8461. if(NULL != m_pCertContextSigner)
  8462. {
  8463. CertFreeCertificateContext(m_pCertContextSigner);
  8464. }
  8465. m_pCertContextSigner = pCertGoodContext;
  8466. hr = S_OK;
  8467. ErrorReturn:
  8468. LeaveCriticalSection(&m_csXEnroll);
  8469. return hr;
  8470. TRACE_ERROR(GetGoodCertContextError)
  8471. }
  8472. HRESULT
  8473. VerifyPrivateKeyArchiveCertificate(
  8474. IN PCCERT_CONTEXT pCert)
  8475. {
  8476. HRESULT hr;
  8477. CERT_CHAIN_PARA ChainParams;
  8478. CERT_CHAIN_POLICY_PARA ChainPolicy;
  8479. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  8480. CERT_CHAIN_CONTEXT const *pCertChain = NULL;
  8481. char *apszCAXchgOids[] = {szOID_KP_CA_EXCHANGE};
  8482. WCHAR *pwszSubject = NULL;
  8483. WCHAR *pwszIssuer = NULL;
  8484. WCHAR *pwszDesignedSubject = NULL;
  8485. //easy check to make sure ca exchange cert issuer and subject
  8486. //names are in convention
  8487. hr = myCertGetNameString(
  8488. pCert,
  8489. FALSE,
  8490. &pwszSubject);
  8491. if (S_OK != hr)
  8492. {
  8493. goto myCertGetNameStringError;
  8494. }
  8495. hr = myCertGetNameString(
  8496. pCert,
  8497. TRUE,
  8498. &pwszIssuer);
  8499. if (S_OK != hr)
  8500. {
  8501. goto myCertGetNameStringError;
  8502. }
  8503. hr = myAddNameSuffix(
  8504. pwszIssuer,
  8505. wszCNXCHGSUFFIX,
  8506. cchCOMMONNAMEMAX_XELIB,
  8507. &pwszDesignedSubject);
  8508. if (S_OK != hr)
  8509. {
  8510. goto myAddNameSuffixError;
  8511. }
  8512. if (0 != wcscmp(pwszSubject, pwszDesignedSubject))
  8513. {
  8514. //unexpected, they should match
  8515. hr = E_INVALIDARG;
  8516. goto InvalidArgError;
  8517. }
  8518. ZeroMemory(&ChainParams, sizeof(ChainParams));
  8519. ChainParams.cbSize = sizeof(ChainParams);
  8520. ChainParams.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
  8521. ChainParams.RequestedUsage.Usage.rgpszUsageIdentifier = apszCAXchgOids;
  8522. ChainParams.RequestedUsage.Usage.cUsageIdentifier = ARRAYSIZE(apszCAXchgOids);
  8523. //get cert chain 1st
  8524. if (!MyCertGetCertificateChain(
  8525. NULL, //HHCE_CURRENT_USER
  8526. pCert, //ca exchange cert
  8527. NULL, //use current system time
  8528. NULL, //no additional stores
  8529. &ChainParams, //chain params
  8530. CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, // Make sure that none of the certs in the chain were revoked
  8531. NULL, //reserved
  8532. &pCertChain))
  8533. {
  8534. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8535. goto CertGetCertificateChainError;
  8536. }
  8537. ZeroMemory(&ChainPolicy, sizeof(ChainPolicy));
  8538. ChainPolicy.cbSize = sizeof(ChainPolicy);
  8539. ChainPolicy.dwFlags = CERT_CHAIN_POLICY_IGNORE_NOT_TIME_NESTED_FLAG;
  8540. ZeroMemory(&PolicyStatus, sizeof(PolicyStatus));
  8541. PolicyStatus.cbSize = sizeof(PolicyStatus);
  8542. PolicyStatus.lChainIndex = -1;
  8543. PolicyStatus.lElementIndex = -1;
  8544. //verify the chain
  8545. if (!MyCertVerifyCertificateChainPolicy(
  8546. CERT_CHAIN_POLICY_BASE,
  8547. pCertChain,
  8548. &ChainPolicy,
  8549. &PolicyStatus))
  8550. {
  8551. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8552. goto CertVerifyCertificateChainPolicyError;
  8553. }
  8554. if (S_OK != PolicyStatus.dwError)
  8555. {
  8556. //chain back to root fails
  8557. hr = PolicyStatus.dwError;
  8558. goto CertVerifyCertificateChainPolicyError;
  8559. }
  8560. hr = S_OK;
  8561. ErrorReturn:
  8562. if (NULL != pCertChain)
  8563. {
  8564. MyCertFreeCertificateChain(pCertChain);
  8565. }
  8566. if (NULL != pwszSubject)
  8567. {
  8568. LocalFree(pwszSubject);
  8569. }
  8570. if (NULL != pwszDesignedSubject)
  8571. {
  8572. LocalFree(pwszDesignedSubject);
  8573. }
  8574. if (NULL != pwszIssuer)
  8575. {
  8576. LocalFree(pwszIssuer);
  8577. }
  8578. return hr;
  8579. TRACE_ERROR(CertGetCertificateChainError)
  8580. TRACE_ERROR(CertVerifyCertificateChainPolicyError)
  8581. TRACE_ERROR(InvalidArgError)
  8582. TRACE_ERROR(myCertGetNameStringError)
  8583. TRACE_ERROR(myAddNameSuffixError)
  8584. }
  8585. HRESULT STDMETHODCALLTYPE
  8586. CCEnroll::SetPrivateKeyArchiveCertificate(
  8587. IN PCCERT_CONTEXT pPrivateKeyArchiveCert)
  8588. {
  8589. HRESULT hr;
  8590. PCCERT_CONTEXT pCert = NULL;
  8591. if (NULL != pPrivateKeyArchiveCert)
  8592. {
  8593. //duplicate the cert
  8594. pCert = CertDuplicateCertificateContext(pPrivateKeyArchiveCert);
  8595. if (NULL == pCert)
  8596. {
  8597. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8598. goto CertDuplicateCertificateContextError;
  8599. }
  8600. //verify ca exchange cert
  8601. hr = VerifyPrivateKeyArchiveCertificate(pCert);
  8602. if (S_OK != hr)
  8603. {
  8604. goto VerifyPrivateKeyArchiveCertificateError;
  8605. }
  8606. }
  8607. EnterCriticalSection(&m_csXEnroll);
  8608. if (NULL != m_PrivateKeyArchiveCertificate)
  8609. {
  8610. CertFreeCertificateContext(m_PrivateKeyArchiveCertificate);
  8611. }
  8612. m_PrivateKeyArchiveCertificate = pCert;
  8613. pCert = NULL;
  8614. LeaveCriticalSection(&m_csXEnroll);
  8615. hr = S_OK;
  8616. ErrorReturn:
  8617. if (NULL != pCert)
  8618. {
  8619. CertFreeCertificateContext(pCert);
  8620. }
  8621. return (hr);
  8622. TRACE_ERROR(CertDuplicateCertificateContextError)
  8623. TRACE_ERROR(VerifyPrivateKeyArchiveCertificateError)
  8624. }
  8625. PCCERT_CONTEXT STDMETHODCALLTYPE
  8626. CCEnroll::GetPrivateKeyArchiveCertificate(void)
  8627. {
  8628. PCCERT_CONTEXT pCert = NULL;
  8629. EnterCriticalSection(&m_csXEnroll);
  8630. if (NULL != m_PrivateKeyArchiveCertificate)
  8631. {
  8632. pCert = CertDuplicateCertificateContext(m_PrivateKeyArchiveCertificate);
  8633. }
  8634. LeaveCriticalSection(&m_csXEnroll);
  8635. return pCert;
  8636. }
  8637. HRESULT STDMETHODCALLTYPE
  8638. CCEnroll::binaryBlobToString(
  8639. IN LONG Flags,
  8640. IN PCRYPT_DATA_BLOB pblobBinary,
  8641. OUT LPWSTR *ppwszString)
  8642. {
  8643. HRESULT hr;
  8644. WCHAR *pwszEncoded = NULL;
  8645. DWORD dwEncoded = 0;
  8646. while (TRUE)
  8647. {
  8648. if (!MyCryptBinaryToStringW(
  8649. pblobBinary->pbData,
  8650. pblobBinary->cbData,
  8651. Flags,
  8652. pwszEncoded,
  8653. &dwEncoded))
  8654. {
  8655. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8656. goto MyCryptBinaryToStringError;
  8657. }
  8658. if (NULL != pwszEncoded)
  8659. {
  8660. //done
  8661. break;
  8662. }
  8663. //dwEncoded includes null terminator
  8664. pwszEncoded = (WCHAR*)MyCoTaskMemAlloc(dwEncoded * sizeof(WCHAR));
  8665. if (NULL == pwszEncoded)
  8666. {
  8667. hr = E_OUTOFMEMORY;
  8668. goto MyCoTaskMemAllocError;
  8669. }
  8670. }
  8671. *ppwszString = pwszEncoded;
  8672. pwszEncoded = NULL;
  8673. hr = S_OK;
  8674. ErrorReturn:
  8675. if (NULL != pwszEncoded)
  8676. {
  8677. MyCoTaskMemFree(pwszEncoded);
  8678. }
  8679. return hr;
  8680. TRACE_ERROR(MyCoTaskMemAllocError)
  8681. TRACE_ERROR(MyCryptBinaryToStringError)
  8682. }
  8683. HRESULT STDMETHODCALLTYPE
  8684. CCEnroll::stringToBinaryBlob(
  8685. IN LONG Flags,
  8686. IN LPCWSTR pwszString,
  8687. OUT PCRYPT_DATA_BLOB pblobBinary,
  8688. OUT LONG *pdwSkip,
  8689. OUT LONG *pdwFlags)
  8690. {
  8691. HRESULT hr;
  8692. size_t nLength = wcslen(pwszString);
  8693. if (nLength*sizeof(WCHAR) > (DWORD)-1)
  8694. goto InvalidArgError;
  8695. //init
  8696. pblobBinary->pbData = NULL;
  8697. pblobBinary->cbData = 0;
  8698. while (TRUE)
  8699. {
  8700. if (!MyCryptStringToBinaryW(
  8701. pwszString,
  8702. (DWORD)nLength,
  8703. Flags,
  8704. pblobBinary->pbData,
  8705. &pblobBinary->cbData,
  8706. (DWORD*)pdwSkip,
  8707. (DWORD*)pdwFlags))
  8708. {
  8709. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8710. goto MyCryptStringToBinaryWError;
  8711. }
  8712. if (NULL != pblobBinary->pbData)
  8713. {
  8714. //done
  8715. break;
  8716. }
  8717. pblobBinary->pbData = (BYTE*)MyCoTaskMemAlloc(pblobBinary->cbData);
  8718. if (NULL == pblobBinary->pbData)
  8719. {
  8720. hr = E_OUTOFMEMORY;
  8721. goto MyCoTaskMemAllocError;
  8722. }
  8723. }
  8724. hr = S_OK;
  8725. ErrorReturn:
  8726. return hr;
  8727. SET_HRESULT(InvalidArgError, E_INVALIDARG);
  8728. TRACE_ERROR(MyCryptStringToBinaryWError)
  8729. TRACE_ERROR(MyCoTaskMemAllocError)
  8730. }
  8731. HRESULT STDMETHODCALLTYPE
  8732. CCEnroll::addExtensionToRequestWStr(
  8733. IN LONG Flags,
  8734. IN LPCWSTR pwszName,
  8735. IN PCRYPT_DATA_BLOB pblobValue)
  8736. {
  8737. HRESULT hr = S_OK;
  8738. CERT_EXTENSION ext;
  8739. CERT_EXTENSION *pExt = NULL; //enum 1st
  8740. CHAR *pszName = NULL;
  8741. //convert wsz oid to sz oid
  8742. hr = xeWSZToSZ(pwszName, &pszName);
  8743. if (S_OK != hr)
  8744. {
  8745. goto error;
  8746. }
  8747. while (NULL != (pExt = EnumStackExtension(pExt, TRUE)))
  8748. {
  8749. if (0 == strcmp(pszName, pExt->pszObjId))
  8750. {
  8751. //already had the extension, can't have more than 1
  8752. hr = MY_HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  8753. goto error;
  8754. }
  8755. }
  8756. //check to see if it is key usage extension
  8757. if (0 == strcmp(pszName, szOID_KEY_USAGE))
  8758. {
  8759. EnterCriticalSection(&m_csXEnroll);
  8760. m_fUseClientKeyUsage = TRUE;
  8761. LeaveCriticalSection(&m_csXEnroll);
  8762. }
  8763. ZeroMemory(&ext, sizeof(ext));
  8764. ext.fCritical = Flags;
  8765. ext.pszObjId = pszName;
  8766. ext.Value = *pblobValue;
  8767. if(!CopyAndPushStackExtension(&ext, TRUE))
  8768. {
  8769. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8770. }
  8771. error:
  8772. if (NULL != pszName)
  8773. {
  8774. MyCoTaskMemFree(pszName);
  8775. }
  8776. return hr;
  8777. }
  8778. HRESULT STDMETHODCALLTYPE
  8779. CCEnroll::addAttributeToRequestWStr(
  8780. IN LONG /*Flags*/,
  8781. IN LPCWSTR pwszName,
  8782. IN PCRYPT_DATA_BLOB pblobValue)
  8783. {
  8784. HRESULT hr = S_OK;
  8785. CRYPT_ATTR_BLOB attrBlob;
  8786. CRYPT_ATTRIBUTE attr;
  8787. CHAR *pszName = NULL;
  8788. //convert wsz oid to sz oid
  8789. hr = xeWSZToSZ(pwszName, &pszName);
  8790. if (S_OK != hr)
  8791. {
  8792. goto error;
  8793. }
  8794. ZeroMemory(&attr, sizeof(attr));
  8795. attrBlob = *pblobValue;
  8796. attr.pszObjId = pszName;
  8797. attr.cValue = 1;
  8798. attr.rgValue = &attrBlob;
  8799. if(!CopyAndPushStackAttribute(&attr, TRUE))
  8800. {
  8801. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8802. }
  8803. error:
  8804. if (NULL != pszName)
  8805. {
  8806. MyCoTaskMemFree(pszName);
  8807. }
  8808. return hr;
  8809. }
  8810. HRESULT STDMETHODCALLTYPE
  8811. CCEnroll::addNameValuePairToRequestWStr(
  8812. IN LONG /*Flags*/,
  8813. IN LPCWSTR pwszName,
  8814. IN LPCWSTR pwszValue)
  8815. {
  8816. HRESULT hr = S_OK;
  8817. assert(pwszName != NULL && pwszValue != NULL);
  8818. CRYPT_ENROLLMENT_NAME_VALUE_PAIR nameValuePair =
  8819. {const_cast<LPWSTR>(pwszName), const_cast<LPWSTR>(pwszValue)};
  8820. CRYPT_ATTR_BLOB blobAttr;
  8821. CRYPT_ATTRIBUTE attr = {szOID_ENROLLMENT_NAME_VALUE_PAIR, 1, &blobAttr};
  8822. memset(&blobAttr, 0, sizeof(CRYPT_ATTR_BLOB));
  8823. hr = xeEncodeNameValuePair(
  8824. &nameValuePair,
  8825. &blobAttr.pbData,
  8826. &blobAttr.cbData);
  8827. if (S_OK != hr)
  8828. {
  8829. goto error;
  8830. }
  8831. if(!CopyAndPushStackAttribute(&attr, TRUE))
  8832. {
  8833. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8834. }
  8835. error:
  8836. if (NULL != blobAttr.pbData)
  8837. {
  8838. MyCoTaskMemFree(blobAttr.pbData);
  8839. }
  8840. return hr;
  8841. }
  8842. HRESULT STDMETHODCALLTYPE CCEnroll::addBlobPropertyToCertificateWStr(
  8843. IN LONG lPropertyId,
  8844. IN LONG lFlags,
  8845. IN PCRYPT_DATA_BLOB pBlobProp)
  8846. {
  8847. HRESULT hr;
  8848. PPROP_STACK pProp;
  8849. PPROP_STACK pPropEle = NULL;
  8850. EnterCriticalSection(&m_csXEnroll);
  8851. if (NULL == pBlobProp ||
  8852. NULL == pBlobProp->pbData ||
  8853. 0 == pBlobProp->cbData)
  8854. {
  8855. hr = MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  8856. goto InvalidParameterError;
  8857. }
  8858. // Don't allow arbitrary properties to be set on the request from a script
  8859. // (could be a security risk, we should only allow a small set)
  8860. if (0 != m_dwEnabledSafteyOptions && !IsDesiredProperty(lPropertyId))
  8861. {
  8862. hr = MY_HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  8863. goto InvalidParameterError;
  8864. }
  8865. //check if the same property exists
  8866. pProp = EnumStackProperty(NULL);
  8867. while (NULL != pProp)
  8868. {
  8869. if (pProp->lPropId == lPropertyId)
  8870. {
  8871. //exists already
  8872. hr = MY_HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  8873. goto PropertyExistError;
  8874. }
  8875. pProp = EnumStackProperty(pProp);
  8876. }
  8877. pPropEle = (PPROP_STACK)LocalAlloc(LMEM_ZEROINIT, sizeof(PROP_STACK));
  8878. if (NULL == pPropEle)
  8879. {
  8880. hr = E_OUTOFMEMORY;
  8881. goto OutOfMemoryError;
  8882. }
  8883. pPropEle->lPropId = lPropertyId;
  8884. pPropEle->lFlags = lFlags;
  8885. pPropEle->prop.pbData = (BYTE*)LocalAlloc(LMEM_FIXED, pBlobProp->cbData);
  8886. if (NULL == pPropEle->prop.pbData)
  8887. {
  8888. hr = E_OUTOFMEMORY;
  8889. goto OutOfMemoryError;
  8890. }
  8891. CopyMemory(pPropEle->prop.pbData, pBlobProp->pbData, pBlobProp->cbData);
  8892. pPropEle->prop.cbData = pBlobProp->cbData;
  8893. //put into stack
  8894. pPropEle->pNext = m_pPropStack;
  8895. m_pPropStack = pPropEle; //assign m_pPropStack
  8896. m_cPropStack++; //increment of m_cPropStack
  8897. pPropEle = NULL;
  8898. hr = S_OK;
  8899. ErrorReturn:
  8900. if (NULL != pPropEle)
  8901. {
  8902. if (NULL != pPropEle->prop.pbData)
  8903. {
  8904. LocalFree(pPropEle->prop.pbData);
  8905. }
  8906. LocalFree(pPropEle);
  8907. }
  8908. LeaveCriticalSection(&m_csXEnroll);
  8909. return hr;
  8910. TRACE_ERROR(InvalidParameterError)
  8911. TRACE_ERROR(PropertyExistError)
  8912. TRACE_ERROR(OutOfMemoryError)
  8913. }
  8914. PPROP_STACK
  8915. CCEnroll::EnumStackProperty(PPROP_STACK pProp)
  8916. {
  8917. EnterCriticalSection(&m_csXEnroll);
  8918. if(NULL == pProp)
  8919. {
  8920. //1st one
  8921. pProp = m_pPropStack;
  8922. }
  8923. else
  8924. {
  8925. pProp = pProp->pNext;
  8926. }
  8927. LeaveCriticalSection(&m_csXEnroll);
  8928. return pProp;
  8929. }
  8930. HRESULT STDMETHODCALLTYPE CCEnroll::resetBlobProperties()
  8931. {
  8932. PPROP_STACK pPropEle;
  8933. PPROP_STACK pPropNext;
  8934. EnterCriticalSection(&m_csXEnroll);
  8935. pPropEle = m_pPropStack;
  8936. while (NULL != pPropEle)
  8937. {
  8938. //save it to temp
  8939. pPropNext = EnumStackProperty(pPropEle);
  8940. //free the current ele
  8941. if (NULL != pPropEle->prop.pbData)
  8942. {
  8943. LocalFree(pPropEle->prop.pbData);
  8944. }
  8945. LocalFree(pPropEle);
  8946. pPropEle = pPropNext;
  8947. }
  8948. m_pPropStack = NULL;
  8949. m_cPropStack = 0;
  8950. LeaveCriticalSection(&m_csXEnroll);
  8951. return S_OK;
  8952. }
  8953. HRESULT
  8954. CCEnroll::GetKeyArchivePKCS7(
  8955. OUT CRYPT_ATTR_BLOB *pBlobKeyArchivePKCS7)
  8956. {
  8957. HRESULT hr;
  8958. HCRYPTPROV hProv;
  8959. HCRYPTKEY hKey = NULL;
  8960. BYTE *pBlobPrivateKey = NULL;
  8961. DWORD cBlobPrivateKey = 0;
  8962. CRYPT_ENCRYPT_MESSAGE_PARA cemp;
  8963. ALG_ID algId[] = {CALG_3DES, CALG_RC4, CALG_RC2, ALG_TYPE_ANY};
  8964. CRYPT_OID_INFO const *pOidInfo = NULL;
  8965. DWORD i = 0;
  8966. //init
  8967. pBlobKeyArchivePKCS7->pbData = NULL;
  8968. pBlobKeyArchivePKCS7->cbData = 0;
  8969. EnterCriticalSection(&m_csXEnroll);
  8970. //make sure key archival cert is set
  8971. assert(NULL != m_PrivateKeyArchiveCertificate);
  8972. PCCERT_CONTEXT apCert[] = {m_PrivateKeyArchiveCertificate};
  8973. //get user private key
  8974. hProv = GetProv(0); //existing key container handle
  8975. if (NULL == hProv)
  8976. {
  8977. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8978. goto CryptAcquireContextError;
  8979. }
  8980. if (NULL == m_hCachedKey)
  8981. {
  8982. //likely used existing key
  8983. if(!CryptGetUserKey(
  8984. hProv,
  8985. m_keyProvInfo.dwKeySpec,
  8986. &hKey))
  8987. {
  8988. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  8989. goto CryptGetUserKeyError;
  8990. }
  8991. }
  8992. //export private key
  8993. while (TRUE)
  8994. {
  8995. if (!CryptExportKey(
  8996. NULL != hKey ? hKey : m_hCachedKey,
  8997. NULL, //don't encrypt
  8998. PRIVATEKEYBLOB,
  8999. 0,
  9000. pBlobPrivateKey,
  9001. &cBlobPrivateKey))
  9002. {
  9003. //map to xenroll error
  9004. hr = XENROLL_E_KEY_NOT_EXPORTABLE;
  9005. goto CryptExportKeyError;
  9006. }
  9007. if (NULL != pBlobPrivateKey)
  9008. {
  9009. //done
  9010. break;
  9011. }
  9012. pBlobPrivateKey = (BYTE*)MyCoTaskMemAlloc(cBlobPrivateKey);
  9013. if (NULL == pBlobPrivateKey)
  9014. {
  9015. hr = E_OUTOFMEMORY;
  9016. goto OutOfMemoryError;
  9017. }
  9018. }
  9019. if (NULL == m_hCachedKey)
  9020. {
  9021. //it could be csp not supporting CRYPT_ARCHIVABLE
  9022. //got private key, now let's take care of key permission
  9023. if (0x0 == (m_dwGenKeyFlags & CRYPT_EXPORTABLE))
  9024. {
  9025. // user didn't ask exportable, turn it off
  9026. DWORD dwFlags = 0;
  9027. DWORD dwSize = sizeof(dwFlags);
  9028. if (!CryptGetKeyParam(
  9029. hKey,
  9030. KP_PERMISSIONS,
  9031. (BYTE*)&dwFlags,
  9032. &dwSize,
  9033. 0))
  9034. {
  9035. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9036. goto CryptGetKeyParamError;
  9037. }
  9038. #if DBG
  9039. assert(dwSize = sizeof(dwFlags));
  9040. // make sure was on
  9041. assert(0x0 != (dwFlags & CRYPT_EXPORT));
  9042. #endif
  9043. //turn off exportable
  9044. dwFlags = dwFlags & (~CRYPT_EXPORT);
  9045. if (!CryptSetKeyParam(
  9046. hKey,
  9047. KP_PERMISSIONS,
  9048. (BYTE*)&dwFlags,
  9049. 0))
  9050. {
  9051. //hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9052. //goto CryptSetKeyParamError;
  9053. hr = S_OK; //UNDONE, even ms csps have problem with this
  9054. }
  9055. }
  9056. }
  9057. //prepare for encryption
  9058. ZeroMemory(&cemp, sizeof(cemp)); //avoid 0 assignment
  9059. cemp.cbSize = sizeof(cemp);
  9060. cemp.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
  9061. hr = S_OK; //critical init for double while loop
  9062. while (ALG_TYPE_ANY != algId[i])
  9063. {
  9064. pOidInfo = xeCryptFindOIDInfo(
  9065. CRYPT_OID_INFO_ALGID_KEY,
  9066. &algId[i],
  9067. CRYPT_ENCRYPT_ALG_OID_GROUP_ID);
  9068. if (NULL != pOidInfo)
  9069. {
  9070. cemp.ContentEncryptionAlgorithm.pszObjId =
  9071. const_cast<char *>(pOidInfo->pszOID);
  9072. //encryt into pkcs7
  9073. while (TRUE)
  9074. {
  9075. if (!CryptEncryptMessage(
  9076. &cemp,
  9077. sizeof(apCert)/sizeof(apCert[0]),
  9078. apCert,
  9079. pBlobPrivateKey,
  9080. cBlobPrivateKey,
  9081. pBlobKeyArchivePKCS7->pbData,
  9082. &pBlobKeyArchivePKCS7->cbData))
  9083. {
  9084. //save the 1st error code
  9085. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9086. #ifdef DBG
  9087. assert(NULL == pBlobKeyArchivePKCS7->pbData);
  9088. #endif
  9089. break; //break inner while loop
  9090. }
  9091. if (NULL != pBlobKeyArchivePKCS7->pbData)
  9092. {
  9093. //done, got encrypted blob
  9094. //ignore error from previous alg tries
  9095. hr = S_OK;
  9096. break;
  9097. }
  9098. pBlobKeyArchivePKCS7->pbData = (BYTE*)MyCoTaskMemAlloc(
  9099. pBlobKeyArchivePKCS7->cbData);
  9100. if (NULL == pBlobKeyArchivePKCS7->pbData)
  9101. {
  9102. hr = E_OUTOFMEMORY;
  9103. goto OutOfMemoryError;
  9104. }
  9105. }
  9106. if (S_OK == hr)
  9107. {
  9108. //done, out of outer while loop
  9109. break;
  9110. }
  9111. }
  9112. ++i;
  9113. }
  9114. if (NULL == pOidInfo)
  9115. {
  9116. hr = CRYPT_E_NOT_FOUND;
  9117. goto CryptElemNotFoundError;
  9118. }
  9119. if (S_OK != hr)
  9120. {
  9121. goto CryptEncryptMessageError;
  9122. }
  9123. hr = S_OK;
  9124. ErrorReturn:
  9125. //now let's destroy cached key handle
  9126. if (NULL != m_hCachedKey)
  9127. {
  9128. CryptDestroyKey(m_hCachedKey);
  9129. m_hCachedKey = NULL; //critical to reset
  9130. }
  9131. //note, do above before leaving critical section
  9132. LeaveCriticalSection(&m_csXEnroll);
  9133. if (NULL != pBlobPrivateKey)
  9134. {
  9135. SecureZeroMemory(pBlobPrivateKey, cBlobPrivateKey);
  9136. MyCoTaskMemFree(pBlobPrivateKey);
  9137. }
  9138. if (NULL != hKey)
  9139. {
  9140. CryptDestroyKey(hKey);
  9141. }
  9142. return hr;
  9143. TRACE_ERROR(CryptEncryptMessageError)
  9144. TRACE_ERROR(CryptAcquireContextError)
  9145. TRACE_ERROR(CryptGetUserKeyError)
  9146. TRACE_ERROR(CryptExportKeyError)
  9147. TRACE_ERROR(OutOfMemoryError)
  9148. TRACE_ERROR(CryptElemNotFoundError)
  9149. //TRACE_ERROR(CryptSetKeyParamError)
  9150. TRACE_ERROR(CryptGetKeyParamError)
  9151. }
  9152. HRESULT
  9153. GetKeyProvInfoFromCert(
  9154. IN PCCERT_CONTEXT pCert,
  9155. OUT DWORD *pdwKeySpec,
  9156. OUT HCRYPTPROV *phProv)
  9157. {
  9158. HRESULT hr;
  9159. CRYPT_KEY_PROV_INFO *pKeyProvInfo = NULL;
  9160. DWORD cb = 0;
  9161. HCRYPTPROV hProv = NULL;
  9162. if (NULL == pCert || NULL == phProv || NULL == pdwKeySpec)
  9163. {
  9164. hr = E_INVALIDARG;
  9165. goto InvalidArgError;
  9166. }
  9167. while (TRUE)
  9168. {
  9169. if(!CertGetCertificateContextProperty(
  9170. pCert,
  9171. CERT_KEY_PROV_INFO_PROP_ID,
  9172. pKeyProvInfo,
  9173. &cb))
  9174. {
  9175. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9176. goto CertGetCertificateContextPropertyError;
  9177. }
  9178. if (NULL != pKeyProvInfo)
  9179. {
  9180. //got it, done
  9181. break;
  9182. }
  9183. pKeyProvInfo = (CRYPT_KEY_PROV_INFO*)LocalAlloc(LMEM_FIXED, cb);
  9184. if (NULL == pKeyProvInfo)
  9185. {
  9186. hr = E_OUTOFMEMORY;
  9187. goto OutOfMemoryError;
  9188. }
  9189. }
  9190. if (!CryptAcquireContextU(
  9191. &hProv,
  9192. pKeyProvInfo->pwszContainerName,
  9193. pKeyProvInfo->pwszProvName,
  9194. pKeyProvInfo->dwProvType,
  9195. pKeyProvInfo->dwFlags))
  9196. {
  9197. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9198. goto CryptAcquireContextUError;
  9199. }
  9200. *phProv = hProv;
  9201. hProv = NULL;
  9202. *pdwKeySpec = pKeyProvInfo->dwKeySpec;
  9203. hr = S_OK;
  9204. ErrorReturn:
  9205. if (NULL != pKeyProvInfo)
  9206. {
  9207. LocalFree(pKeyProvInfo);
  9208. }
  9209. if (NULL != hProv)
  9210. {
  9211. CryptReleaseContext(hProv, 0);
  9212. }
  9213. return hr;
  9214. TRACE_ERROR(CryptAcquireContextUError)
  9215. TRACE_ERROR(OutOfMemoryError)
  9216. TRACE_ERROR(CertGetCertificateContextPropertyError)
  9217. TRACE_ERROR(InvalidArgError)
  9218. }
  9219. HRESULT
  9220. xeCreateKeyArchivalHashAttribute(
  9221. IN CRYPT_HASH_BLOB *pBlobKAHash,
  9222. OUT CRYPT_ATTR_BLOB *pBlobKAAttr)
  9223. {
  9224. HRESULT hr;
  9225. BYTE *pbData = NULL;
  9226. DWORD cbData = 0;
  9227. while (TRUE)
  9228. {
  9229. if(!CryptEncodeObject(
  9230. CRYPT_ASN_ENCODING,
  9231. X509_OCTET_STRING,
  9232. (void*)pBlobKAHash,
  9233. pbData,
  9234. &cbData))
  9235. {
  9236. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9237. goto CryptEncodeObjectError;
  9238. }
  9239. if (NULL != pbData)
  9240. {
  9241. //done
  9242. break;
  9243. }
  9244. pbData = (BYTE*)LocalAlloc(LMEM_FIXED, cbData);
  9245. if (NULL == pbData)
  9246. {
  9247. hr = E_OUTOFMEMORY;
  9248. goto LocalAllocError;
  9249. }
  9250. }
  9251. pBlobKAAttr->pbData = pbData;
  9252. pBlobKAAttr->cbData = cbData;
  9253. pbData = NULL;
  9254. hr = S_OK;
  9255. ErrorReturn:
  9256. if (NULL != pbData)
  9257. {
  9258. LocalFree(pbData);
  9259. }
  9260. return hr;
  9261. TRACE_ERROR(CryptEncodeObjectError)
  9262. TRACE_ERROR(LocalAllocError)
  9263. }
  9264. HRESULT STDMETHODCALLTYPE
  9265. CCEnroll::createRequestWStr(
  9266. IN LONG Flags,
  9267. IN LPCWSTR pwszDNName,
  9268. IN LPCWSTR pwszUsage,
  9269. OUT PCRYPT_DATA_BLOB pblobRequest)
  9270. {
  9271. HRESULT hr;
  9272. CRYPT_DATA_BLOB blobPKCS10;
  9273. CRYPT_ATTR_BLOB blobKeyArchivePKCS7;
  9274. ALG_ID rgAlg[2];
  9275. PCCRYPT_OID_INFO pOidInfo;
  9276. CERT_EXTENSION *rgExt = NULL;
  9277. DWORD cExt = 0;
  9278. CERT_EXTENSION *pExt = NULL; //for enum 1st
  9279. CRYPT_ATTRIBUTE *rgAttr = NULL;
  9280. DWORD cAttr = 0;
  9281. CRYPT_ATTRIBUTE *pAttr = NULL; //for enum 1st
  9282. CRYPT_ATTRIBUTES rgAttributes;
  9283. CRYPT_ATTRIBUTE *rgUnauthAttr = NULL; //init
  9284. DWORD cUnauthAttr = 0; //init
  9285. DWORD cb;
  9286. HCRYPTPROV hProvSigner = NULL;
  9287. DWORD dwKeySpecSigner = 0;
  9288. PCCERT_CONTEXT pCertSigner = NULL; //just init, no free
  9289. HCRYPTPROV hRequestProv = NULL;
  9290. BYTE *pbSubjectKeyHash = NULL;
  9291. DWORD cbSubjectKeyHash = 0;
  9292. CRYPT_HASH_BLOB blobKAHash;
  9293. CRYPT_ATTR_BLOB blobKAHashAttr;
  9294. CRYPT_ATTRIBUTE attrKAHash =
  9295. {szOID_ENCRYPTED_KEY_HASH, 1, &blobKAHashAttr};
  9296. ZeroMemory(&blobPKCS10, sizeof(blobPKCS10));
  9297. ZeroMemory(&blobKeyArchivePKCS7, sizeof(blobKeyArchivePKCS7));
  9298. ZeroMemory(&blobKAHash, sizeof(blobKAHash));
  9299. ZeroMemory(&blobKAHashAttr, sizeof(blobKAHashAttr));
  9300. EnterCriticalSection(&m_csXEnroll);
  9301. // BUG 533202: should block key archival when re-using key (from script)
  9302. if (0 != m_dwEnabledSafteyOptions && NULL != m_PrivateKeyArchiveCertificate && m_fUseExistingKey) {
  9303. hr = E_ACCESSDENIED;
  9304. goto AccessDeniedError;
  9305. }
  9306. m_fNewRequestMethod = TRUE; //critical
  9307. m_fOID_V2 = TRUE;
  9308. m_fCMCFormat = FALSE;
  9309. m_fHonorIncludeSubjectKeyID = FALSE;
  9310. switch (Flags)
  9311. {
  9312. case XECR_CMC:
  9313. {
  9314. if (NULL != m_pCertContextRenewal &&
  9315. NULL != m_pCertContextSigner)
  9316. {
  9317. //don't support both on yet
  9318. hr = MY_HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  9319. goto NotSupportedError;
  9320. }
  9321. m_fCMCFormat = TRUE;
  9322. m_fHonorIncludeSubjectKeyID = TRUE;
  9323. // create pkcs 10 first
  9324. hr = createPKCS10WStr(
  9325. pwszDNName,
  9326. pwszUsage, //wszPurpose,
  9327. &blobPKCS10);
  9328. if(S_OK != hr)
  9329. {
  9330. goto createPKCS10WStrError;
  9331. }
  9332. //set it back
  9333. m_fCMCFormat = FALSE;
  9334. //get all extensions
  9335. cb = CountStackExtension(TRUE) * sizeof(CERT_EXTENSION);
  9336. if (0 < cb)
  9337. {
  9338. rgExt = (CERT_EXTENSION*)LocalAlloc(LMEM_FIXED, cb);
  9339. if (NULL == rgExt)
  9340. {
  9341. hr = E_OUTOFMEMORY;
  9342. goto OutOfMemoryError;
  9343. }
  9344. ZeroMemory(rgExt, cb);
  9345. while(NULL != (pExt = EnumStackExtension(pExt, TRUE)))
  9346. {
  9347. rgExt[cExt] = *pExt;
  9348. cExt++;
  9349. }
  9350. }
  9351. //get all attributes including namevalue pair
  9352. cb = CountStackAttribute(TRUE) * sizeof(CRYPT_ATTRIBUTE);
  9353. if (NULL != m_PrivateKeyArchiveCertificate)
  9354. {
  9355. //add one more attribute to hold encrypted key hash
  9356. cb += sizeof(CRYPT_ATTRIBUTE);
  9357. }
  9358. if (0 < cb)
  9359. {
  9360. rgAttr = (CRYPT_ATTRIBUTE*)LocalAlloc(LMEM_FIXED, cb);
  9361. if (NULL == rgAttr)
  9362. {
  9363. hr = E_OUTOFMEMORY;
  9364. goto OutOfMemoryError;
  9365. }
  9366. ZeroMemory(rgAttr, cb);
  9367. while(NULL != (pAttr = EnumStackAttribute(pAttr, TRUE)))
  9368. {
  9369. rgAttr[cAttr] = *pAttr;
  9370. cAttr++;
  9371. }
  9372. rgAttributes.rgAttr = rgAttr;
  9373. rgAttributes.cAttr = cAttr;
  9374. }
  9375. if (NULL != m_PrivateKeyArchiveCertificate)
  9376. {
  9377. hr = GetKeyArchivePKCS7(&blobKeyArchivePKCS7);
  9378. if (S_OK != hr)
  9379. {
  9380. goto GetKeyArchivePKCS7Error;
  9381. }
  9382. rgUnauthAttr = (CRYPT_ATTRIBUTE*)LocalAlloc(LMEM_FIXED,
  9383. sizeof(CRYPT_ATTRIBUTE));
  9384. if (NULL == rgUnauthAttr)
  9385. {
  9386. hr = E_OUTOFMEMORY;
  9387. goto OutOfMemoryError;
  9388. }
  9389. rgUnauthAttr->pszObjId = szOID_ARCHIVED_KEY_ATTR;
  9390. rgUnauthAttr->cValue = 1;
  9391. rgUnauthAttr->rgValue = &blobKeyArchivePKCS7;
  9392. ++cUnauthAttr;
  9393. //if key archival cert is set, should save the hash
  9394. //of the encrypted private key
  9395. hr = myCalculateKeyArchivalHash(
  9396. blobKeyArchivePKCS7.pbData,
  9397. blobKeyArchivePKCS7.cbData,
  9398. &blobKAHash.pbData,
  9399. &blobKAHash.cbData);
  9400. if (S_OK != hr)
  9401. {
  9402. goto myCalculateKeyArchivalHashError;
  9403. }
  9404. if (!CertSetCertificateContextProperty(
  9405. m_pCertContextPendingRequest, //use pending cert
  9406. CERT_ARCHIVED_KEY_HASH_PROP_ID,
  9407. 0,
  9408. &blobKAHash))
  9409. {
  9410. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9411. goto CertSetCertificateContextPropertyError;
  9412. }
  9413. hr = xeCreateKeyArchivalHashAttribute(
  9414. &blobKAHash,
  9415. &blobKAHashAttr);
  9416. if (S_OK != hr)
  9417. {
  9418. goto xeCreateKeyArchivalHashAttributeError;
  9419. }
  9420. //add this attribute into the array
  9421. rgAttr[cAttr] = attrKAHash;
  9422. cAttr++;
  9423. rgAttributes.rgAttr = rgAttr;
  9424. rgAttributes.cAttr = cAttr;
  9425. }
  9426. //client may set m_HashAlgId but it is not guaranteed
  9427. //GetCapiHashAndSigAlgId will determine which one
  9428. //is actually used
  9429. if (!GetCapiHashAndSigAlgId(rgAlg))
  9430. {
  9431. hr = NTE_BAD_ALGID;
  9432. goto GetCapiHashAndSigAlgIdError;
  9433. }
  9434. pOidInfo = xeCryptFindOIDInfo(
  9435. CRYPT_OID_INFO_ALGID_KEY,
  9436. (void*)rgAlg, //point to rgAlg[0]
  9437. CRYPT_HASH_ALG_OID_GROUP_ID);
  9438. if (NULL == pOidInfo)
  9439. {
  9440. goto xeCryptFindOIDInfoError;
  9441. }
  9442. if (NULL != m_pCertContextRenewal)
  9443. {
  9444. pCertSigner = m_pCertContextRenewal;
  9445. }
  9446. if (NULL != m_pCertContextSigner)
  9447. {
  9448. pCertSigner = m_pCertContextSigner;
  9449. }
  9450. if (NULL != pCertSigner)
  9451. {
  9452. //get signer key prov info
  9453. hr = GetKeyProvInfoFromCert(
  9454. pCertSigner,
  9455. &dwKeySpecSigner,
  9456. &hProvSigner);
  9457. if (S_OK != hr)
  9458. {
  9459. goto GetKeyProvInfoFromCertError;
  9460. }
  9461. }
  9462. //this is CMC, honor anyway
  9463. if (m_fIncludeSubjectKeyID)
  9464. {
  9465. hr = myGetPublicKeyHash(
  9466. NULL,
  9467. m_pPublicKeyInfo,
  9468. &pbSubjectKeyHash,
  9469. &cbSubjectKeyHash);
  9470. if (S_OK != hr)
  9471. {
  9472. goto myGetPublicKeyHashError;
  9473. }
  9474. }
  9475. hRequestProv = GetProv(0);
  9476. if (NULL == hRequestProv)
  9477. {
  9478. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9479. goto GetProvError;
  9480. }
  9481. //ok, now call cmc create
  9482. hr = BuildCMCRequest(
  9483. m_lClientId,
  9484. FALSE, //fNestedCMCRequest
  9485. blobPKCS10.pbData,
  9486. blobPKCS10.cbData,
  9487. rgExt,
  9488. cExt,
  9489. (0 != cAttr) ? &rgAttributes : NULL,
  9490. (0 != cAttr) ? 1 : 0,
  9491. rgUnauthAttr,
  9492. cUnauthAttr,
  9493. pbSubjectKeyHash,
  9494. cbSubjectKeyHash,
  9495. hRequestProv,
  9496. m_keyProvInfo.dwKeySpec,
  9497. pOidInfo->pszOID,
  9498. pCertSigner,
  9499. hProvSigner,
  9500. dwKeySpecSigner,
  9501. NULL, //pOidInfo->pszOID, //this seems to me not necessary because we passed the cert context
  9502. &pblobRequest->pbData,
  9503. &pblobRequest->cbData);
  9504. if (S_OK != hr)
  9505. {
  9506. goto BuildCMCRequestError;
  9507. }
  9508. }
  9509. break;
  9510. case XECR_PKCS7:
  9511. if ((NULL == m_pCertContextRenewal &&
  9512. NULL == m_pCertContextSigner) ||
  9513. NULL != m_PrivateKeyArchiveCertificate)
  9514. {
  9515. //renew cert is not set, can't make it pkcs7
  9516. //pkcs7 can't support key archival
  9517. hr = E_INVALIDARG;
  9518. goto InvalidArgError;
  9519. }
  9520. // old method will return pkcs7
  9521. hr = createPKCS10WStr(
  9522. pwszDNName,
  9523. pwszUsage, //wszPurpose,
  9524. pblobRequest);
  9525. if(S_OK != hr)
  9526. {
  9527. goto createPKCS10WStrError;
  9528. }
  9529. break;
  9530. case XECR_PKCS10_V1_5:
  9531. m_fOID_V2 = FALSE;
  9532. //fall through
  9533. case XECR_PKCS10_V2_0:
  9534. if (NULL != m_PrivateKeyArchiveCertificate)
  9535. {
  9536. //pkcs10 can't support key archival
  9537. hr = E_INVALIDARG;
  9538. goto InvalidArgError;
  9539. }
  9540. m_fHonorRenew = FALSE; //avoid return pkcs7
  9541. //for new PKCS10 we allow include subject key id extension
  9542. m_fHonorIncludeSubjectKeyID = TRUE;
  9543. // call old method
  9544. hr = createPKCS10WStr(
  9545. pwszDNName,
  9546. pwszUsage, //wszPurpose,
  9547. pblobRequest);
  9548. if(S_OK != hr)
  9549. {
  9550. goto createPKCS10WStrError;
  9551. }
  9552. break;
  9553. default:
  9554. hr = E_INVALIDARG;
  9555. goto InvalidArgError;
  9556. break;
  9557. }
  9558. //in all cases, we called createPKCS10WStr
  9559. if(m_wszPVKFileName[0] != 0 && !m_fUseExistingKey)
  9560. {
  9561. //we hold on this until possible cmc is created
  9562. GetProv(CRYPT_DELETEKEYSET);
  9563. }
  9564. hr = S_OK;
  9565. ErrorReturn:
  9566. m_fNewRequestMethod = FALSE; //critical
  9567. m_fOID_V2 = FALSE; //critical for backward compatiability
  9568. m_fHonorRenew = TRUE; //critical
  9569. m_fHonorIncludeSubjectKeyID = TRUE; //critical for backward compt.
  9570. LeaveCriticalSection(&m_csXEnroll);
  9571. if (NULL != rgExt)
  9572. {
  9573. LocalFree(rgExt);
  9574. }
  9575. if (NULL != rgAttr)
  9576. {
  9577. LocalFree(rgAttr);
  9578. }
  9579. if (NULL != rgUnauthAttr)
  9580. {
  9581. LocalFree(rgUnauthAttr);
  9582. }
  9583. if (NULL != blobKeyArchivePKCS7.pbData)
  9584. {
  9585. MyCoTaskMemFree(blobKeyArchivePKCS7.pbData);
  9586. }
  9587. if (NULL != blobPKCS10.pbData)
  9588. {
  9589. MyCoTaskMemFree(blobPKCS10.pbData);
  9590. }
  9591. if (NULL != hProvSigner)
  9592. {
  9593. CryptReleaseContext(hProvSigner, 0);
  9594. }
  9595. if (NULL != pbSubjectKeyHash)
  9596. {
  9597. LocalFree(pbSubjectKeyHash);
  9598. }
  9599. if (NULL != blobKAHash.pbData)
  9600. {
  9601. LocalFree(blobKAHash.pbData);
  9602. }
  9603. if (NULL != blobKAHashAttr.pbData)
  9604. {
  9605. LocalFree(blobKAHashAttr.pbData);
  9606. }
  9607. return hr;
  9608. TRACE_ERROR(AccessDeniedError);
  9609. TRACE_ERROR(createPKCS10WStrError)
  9610. TRACE_ERROR(BuildCMCRequestError)
  9611. TRACE_ERROR(InvalidArgError)
  9612. TRACE_ERROR(GetCapiHashAndSigAlgIdError)
  9613. TRACE_ERROR(GetKeyArchivePKCS7Error)
  9614. TRACE_ERROR(xeCryptFindOIDInfoError)
  9615. TRACE_ERROR(OutOfMemoryError)
  9616. TRACE_ERROR(GetKeyProvInfoFromCertError)
  9617. TRACE_ERROR(NotSupportedError)
  9618. TRACE_ERROR(GetProvError)
  9619. TRACE_ERROR(myGetPublicKeyHashError)
  9620. TRACE_ERROR(CertSetCertificateContextPropertyError)
  9621. TRACE_ERROR(myCalculateKeyArchivalHashError)
  9622. TRACE_ERROR(xeCreateKeyArchivalHashAttributeError)
  9623. }
  9624. HRESULT
  9625. CCEnroll::BlobToBstring(
  9626. IN CRYPT_DATA_BLOB *pBlob,
  9627. IN DWORD dwFlag,
  9628. OUT BSTR *pBString)
  9629. {
  9630. HRESULT hr;
  9631. WCHAR *pwszB64;
  9632. DWORD cch;
  9633. //init
  9634. *pBString = NULL;
  9635. // BASE64 encode blob
  9636. pwszB64 = NULL;
  9637. cch = 0;
  9638. while (TRUE)
  9639. {
  9640. if (!MyCryptBinaryToStringW(
  9641. pBlob->pbData,
  9642. pBlob->cbData,
  9643. dwFlag,
  9644. pwszB64,
  9645. &cch))
  9646. {
  9647. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9648. goto MyCryptBinaryToStringWError;
  9649. }
  9650. if (NULL != pwszB64)
  9651. {
  9652. //got it, done
  9653. break;
  9654. }
  9655. pwszB64 = (WCHAR *)LocalAlloc(LMEM_FIXED, cch * sizeof(WCHAR));
  9656. if (NULL == pwszB64)
  9657. {
  9658. hr = E_OUTOFMEMORY;
  9659. goto OutOfMemoryError;
  9660. }
  9661. }
  9662. // SysAllocStringLen
  9663. *pBString = SysAllocStringLen(pwszB64, cch);
  9664. if(NULL == *pBString)
  9665. {
  9666. SetLastError(ERROR_OUTOFMEMORY);
  9667. hr = E_OUTOFMEMORY;
  9668. goto SysAllocStringLenError;
  9669. }
  9670. hr = S_OK;
  9671. ErrorReturn:
  9672. if (NULL != pwszB64)
  9673. {
  9674. LocalFree(pwszB64);
  9675. }
  9676. return(hr);
  9677. TRACE_ERROR(MyCryptBinaryToStringWError)
  9678. TRACE_ERROR(SysAllocStringLenError)
  9679. TRACE_ERROR(OutOfMemoryError)
  9680. }
  9681. HRESULT
  9682. CCEnroll::BstringToBlob(
  9683. IN BSTR bString,
  9684. OUT CRYPT_DATA_BLOB *pBlob)
  9685. {
  9686. HRESULT hr;
  9687. assert(NULL != pBlob);
  9688. //init
  9689. pBlob->pbData = NULL;
  9690. pBlob->cbData = 0;
  9691. while (TRUE)
  9692. {
  9693. if (!MyCryptStringToBinaryW(
  9694. (LPCWSTR)bString,
  9695. SysStringLen(bString),
  9696. CRYPT_STRING_ANY,
  9697. pBlob->pbData,
  9698. &pBlob->cbData,
  9699. NULL,
  9700. NULL))
  9701. {
  9702. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9703. goto MyCryptStringToBinaryWError;
  9704. }
  9705. if (NULL != pBlob->pbData)
  9706. {
  9707. break; //done
  9708. }
  9709. pBlob->pbData = (BYTE*)MyCoTaskMemAlloc(pBlob->cbData);
  9710. if (NULL == pBlob->pbData)
  9711. {
  9712. hr = E_OUTOFMEMORY;
  9713. goto MyCoTaskMemAllocError;
  9714. }
  9715. }
  9716. hr = S_OK;
  9717. ErrorReturn:
  9718. return(hr);
  9719. TRACE_ERROR(MyCoTaskMemAllocError)
  9720. TRACE_ERROR(MyCryptStringToBinaryWError)
  9721. }
  9722. HRESULT
  9723. CCEnroll::createRequestWStrBStr(
  9724. IN LONG Flags,
  9725. IN LPCWSTR pwszDNName,
  9726. IN LPCWSTR pwszUsage,
  9727. IN DWORD dwFlag,
  9728. OUT BSTR __RPC_FAR *pbstrRequest)
  9729. {
  9730. HRESULT hr;
  9731. CRYPT_DATA_BLOB blobRequest;
  9732. memset(&blobRequest, 0, sizeof(blobRequest));
  9733. hr = createRequestWStr(Flags, pwszDNName, pwszUsage, &blobRequest);
  9734. if (S_OK != hr)
  9735. {
  9736. goto createRequestWStrError;
  9737. }
  9738. // convert to bstr
  9739. hr = BlobToBstring(&blobRequest, dwFlag, pbstrRequest);
  9740. if (S_OK != hr)
  9741. {
  9742. goto BlobToBstringError;
  9743. }
  9744. hr = S_OK;
  9745. ErrorReturn:
  9746. if(NULL != blobRequest.pbData)
  9747. {
  9748. MyCoTaskMemFree(blobRequest.pbData);
  9749. }
  9750. return(hr);
  9751. TRACE_ERROR(createRequestWStrError)
  9752. TRACE_ERROR(BlobToBstringError)
  9753. }
  9754. HRESULT
  9755. CCEnroll::BStringToFile(
  9756. IN BSTR bString,
  9757. IN LPCWSTR pwszFileName)
  9758. {
  9759. HRESULT hr;
  9760. HANDLE hFile = NULL;
  9761. DWORD cb = 0;
  9762. LPSTR sz = NULL;
  9763. size_t nLength;
  9764. sz = MBFromWide(bString);
  9765. if(NULL == sz)
  9766. {
  9767. hr = E_OUTOFMEMORY;
  9768. goto MBFromWideError;
  9769. }
  9770. nLength = strlen(sz);
  9771. if (nLength > (DWORD)-1)
  9772. goto InvalidArgError;
  9773. // open the file
  9774. hFile = CreateFileSafely(pwszFileName);
  9775. if (NULL == hFile)
  9776. {
  9777. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9778. goto CreateFileFileSafelyError;
  9779. }
  9780. // write the pkcs10
  9781. if(!WriteFile(
  9782. hFile,
  9783. sz,
  9784. (DWORD)nLength,
  9785. &cb,
  9786. NULL))
  9787. {
  9788. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  9789. goto WriteFileError;
  9790. }
  9791. hr = S_OK;
  9792. ErrorReturn:
  9793. if(NULL != hFile)
  9794. {
  9795. CloseHandle(hFile);
  9796. }
  9797. if(NULL != sz)
  9798. {
  9799. MyCoTaskMemFree(sz);
  9800. }
  9801. return(hr);
  9802. TRACE_ERROR(CreateFileFileSafelyError)
  9803. SET_HRESULT(InvalidArgError, E_INVALIDARG);
  9804. TRACE_ERROR(MBFromWideError)
  9805. TRACE_ERROR(WriteFileError)
  9806. }
  9807. HRESULT STDMETHODCALLTYPE
  9808. CCEnroll::createFileRequestWStr(
  9809. IN LONG Flags,
  9810. IN LPCWSTR pwszDNName,
  9811. IN LPCWSTR pwszUsage,
  9812. IN LPCWSTR pwszRequestFileName)
  9813. {
  9814. HRESULT hr;
  9815. BSTR bstrRequest = NULL;
  9816. // get the Request
  9817. hr = createRequestWStrBStr(
  9818. Flags,
  9819. pwszDNName,
  9820. pwszUsage,
  9821. CRYPT_STRING_BASE64REQUESTHEADER,
  9822. &bstrRequest);
  9823. if(S_OK != hr)
  9824. {
  9825. goto createRequestWStrBStrError;
  9826. }
  9827. // save it to file
  9828. hr = BStringToFile(bstrRequest, pwszRequestFileName);
  9829. if (S_OK != hr)
  9830. {
  9831. goto BStringToFileError;
  9832. }
  9833. hr = S_OK;
  9834. ErrorReturn:
  9835. if(NULL != bstrRequest)
  9836. {
  9837. SysFreeString(bstrRequest);
  9838. }
  9839. return(hr);
  9840. TRACE_ERROR(createRequestWStrBStrError)
  9841. TRACE_ERROR(BStringToFileError)
  9842. }
  9843. HRESULT STDMETHODCALLTYPE
  9844. CCEnroll::acceptResponseBlob(
  9845. IN PCRYPT_DATA_BLOB pblobResponse)
  9846. {
  9847. HRESULT hr_old = S_OK;
  9848. HRESULT hr;
  9849. XCMCRESPONSE *prgResponse = NULL;
  9850. DWORD cResponse = 0;
  9851. EnterCriticalSection(&m_csXEnroll);
  9852. //check in parameter
  9853. if (NULL == pblobResponse)
  9854. {
  9855. hr = E_POINTER;
  9856. goto NullPointerError;
  9857. }
  9858. if (NULL == pblobResponse->pbData ||
  9859. 0 == pblobResponse->cbData)
  9860. {
  9861. hr = E_INVALIDARG;
  9862. goto InvalidArgError;
  9863. }
  9864. //make sure init archived key hash
  9865. ZeroMemory(&m_blobResponseKAHash, sizeof(m_blobResponseKAHash));
  9866. hr_old = ParseCMCResponse(
  9867. pblobResponse->pbData,
  9868. pblobResponse->cbData,
  9869. NULL,
  9870. &prgResponse,
  9871. &cResponse);
  9872. //note, if for any reasons above failed, try pkcs7
  9873. if (S_OK == hr_old)
  9874. {
  9875. if (1 < cResponse)
  9876. {
  9877. //not supported yet
  9878. hr = MY_HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
  9879. goto NotSupportedError;
  9880. }
  9881. #if DBG
  9882. //make sure not zero, should be 1
  9883. assert(1 == cResponse);
  9884. #endif //DBG
  9885. //check response status
  9886. if (CMC_STATUS_SUCCESS != prgResponse->StatusInfo.dwStatus)
  9887. {
  9888. hr = prgResponse->StatusInfo.dwStatus; //take status error
  9889. goto CMCResponseStatusError;
  9890. }
  9891. //some code here to get encrypted archived key hash from the response
  9892. //and make m_blobResponseKAHash point to the hash data
  9893. if (NULL != prgResponse->pbEncryptedKeyHash)
  9894. {
  9895. m_blobResponseKAHash.pbData = prgResponse->pbEncryptedKeyHash;
  9896. m_blobResponseKAHash.cbData = prgResponse->cbEncryptedKeyHash;
  9897. }
  9898. }
  9899. //note, hr_old may not be S_OK, accept the response as pkcs7
  9900. hr = acceptPKCS7Blob(pblobResponse);
  9901. if (S_OK != hr)
  9902. {
  9903. if (S_OK != hr_old)
  9904. {
  9905. //return old error instead of new one
  9906. hr = hr_old;
  9907. }
  9908. goto acceptPKCS7BlobError;
  9909. }
  9910. hr = S_OK;
  9911. ErrorReturn:
  9912. //reset hash to zero
  9913. ZeroMemory(&m_blobResponseKAHash, sizeof(m_blobResponseKAHash));
  9914. LeaveCriticalSection(&m_csXEnroll);
  9915. if (NULL != prgResponse)
  9916. {
  9917. FreeCMCResponse(prgResponse, cResponse);
  9918. }
  9919. return hr;
  9920. TRACE_ERROR(acceptPKCS7BlobError)
  9921. TRACE_ERROR(CMCResponseStatusError)
  9922. TRACE_ERROR(NotSupportedError)
  9923. TRACE_ERROR(InvalidArgError)
  9924. TRACE_ERROR(NullPointerError)
  9925. }
  9926. HRESULT STDMETHODCALLTYPE
  9927. CCEnroll::acceptFileResponseWStr(
  9928. IN LPCWSTR pwszResponseFileName)
  9929. {
  9930. HRESULT hr;
  9931. CRYPT_DATA_BLOB blob;
  9932. ZeroMemory(&blob, sizeof(blob));
  9933. hr = xeStringToBinaryFromFile(
  9934. pwszResponseFileName,
  9935. &blob.pbData,
  9936. &blob.cbData,
  9937. CRYPT_STRING_ANY);
  9938. if (S_OK != hr)
  9939. {
  9940. goto xeStringToBinaryFromFileError;
  9941. }
  9942. // accept the blob
  9943. hr = acceptResponseBlob(&blob);
  9944. ErrorReturn:
  9945. if (NULL != blob.pbData)
  9946. {
  9947. LocalFree(blob.pbData);
  9948. }
  9949. return(hr);
  9950. TRACE_ERROR(xeStringToBinaryFromFileError)
  9951. }
  9952. HRESULT STDMETHODCALLTYPE
  9953. CCEnroll::getCertContextFromResponseBlob(
  9954. IN PCRYPT_DATA_BLOB pblobResponse,
  9955. OUT PCCERT_CONTEXT *ppCertContext)
  9956. {
  9957. HRESULT hr;
  9958. if (NULL == ppCertContext)
  9959. {
  9960. hr = E_POINTER;
  9961. goto NullPointerError;
  9962. }
  9963. //???should check response status?
  9964. //response is already in pkcs7
  9965. hr = GetEndEntityCert(pblobResponse, FALSE, ppCertContext);
  9966. if (S_OK != hr)
  9967. {
  9968. goto GetEndEntityCertError;
  9969. }
  9970. hr = S_OK;
  9971. ErrorReturn:
  9972. return hr;
  9973. TRACE_ERROR(NullPointerError)
  9974. TRACE_ERROR(GetEndEntityCertError)
  9975. }
  9976. HRESULT STDMETHODCALLTYPE
  9977. CCEnroll::getCertContextFromFileResponseWStr(
  9978. IN LPCWSTR pwszResponseFileName,
  9979. OUT PCCERT_CONTEXT *ppCertContext)
  9980. {
  9981. HRESULT hr;
  9982. CRYPT_DATA_BLOB blobResponse;
  9983. ZeroMemory(&blobResponse, sizeof(blobResponse));
  9984. // could be any form, binary or base64
  9985. hr = xeStringToBinaryFromFile(
  9986. pwszResponseFileName,
  9987. &blobResponse.pbData,
  9988. &blobResponse.cbData,
  9989. CRYPT_STRING_ANY);
  9990. if (S_OK != hr)
  9991. {
  9992. goto xeStringToBinaryFromFileError;
  9993. }
  9994. hr = getCertContextFromResponseBlob(
  9995. &blobResponse,
  9996. ppCertContext);
  9997. if (S_OK != hr)
  9998. {
  9999. goto getCertContextFromResponseBlobError;
  10000. }
  10001. hr = S_OK;
  10002. ErrorReturn:
  10003. if (NULL != blobResponse.pbData)
  10004. {
  10005. LocalFree(blobResponse.pbData);
  10006. }
  10007. return hr;
  10008. TRACE_ERROR(xeStringToBinaryFromFileError)
  10009. TRACE_ERROR(getCertContextFromResponseBlobError)
  10010. }
  10011. HRESULT STDMETHODCALLTYPE
  10012. CCEnroll::createPFXWStr(
  10013. IN LPCWSTR pwszPassword,
  10014. OUT PCRYPT_DATA_BLOB pblobPFX)
  10015. {
  10016. HRESULT hr;
  10017. HCERTSTORE hMemStore = NULL;
  10018. DWORD i;
  10019. CERT_CHAIN_CONTEXT const *pCertChainContext = NULL;
  10020. CERT_CHAIN_PARA CertChainPara;
  10021. CERT_SIMPLE_CHAIN *pSimpleChain;
  10022. EnterCriticalSection(&m_csXEnroll);
  10023. if (NULL == pblobPFX)
  10024. {
  10025. goto EPointerError;
  10026. }
  10027. if (NULL == m_pCertContextStatic)
  10028. {
  10029. hr = E_UNEXPECTED;
  10030. goto UnexpectedError;
  10031. }
  10032. // create a memory store for cert and chain
  10033. hMemStore = CertOpenStore(
  10034. CERT_STORE_PROV_MEMORY,
  10035. X509_ASN_ENCODING,
  10036. NULL,
  10037. 0,
  10038. NULL);
  10039. if (NULL == hMemStore)
  10040. {
  10041. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10042. goto CertOpenStoreError;
  10043. }
  10044. ZeroMemory(&CertChainPara, sizeof(CertChainPara));
  10045. CertChainPara.cbSize = sizeof(CertChainPara);
  10046. // try to build cert and chain
  10047. if (!MyCertGetCertificateChain(
  10048. HCCE_CURRENT_USER,
  10049. m_pCertContextStatic,
  10050. NULL,
  10051. NULL,
  10052. &CertChainPara,
  10053. 0,
  10054. NULL,
  10055. &pCertChainContext))
  10056. {
  10057. //use 1st hr error
  10058. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10059. //try local machine
  10060. if (!MyCertGetCertificateChain(
  10061. HCCE_LOCAL_MACHINE,
  10062. m_pCertContextStatic,
  10063. NULL,
  10064. NULL,
  10065. &CertChainPara,
  10066. 0,
  10067. NULL,
  10068. &pCertChainContext))
  10069. {
  10070. //still use 1st hr
  10071. goto MyCertGetCertificateChainError;
  10072. }
  10073. }
  10074. // make sure there is at least 1 simple chain
  10075. if (0 == pCertChainContext->cChain)
  10076. {
  10077. hr = MY_HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  10078. goto NoCertificateChainError;
  10079. }
  10080. //add chain to memory store
  10081. pSimpleChain = pCertChainContext->rgpChain[0];
  10082. for (i = 0; i < pSimpleChain->cElement; i++)
  10083. {
  10084. if (!CertAddCertificateContextToStore(
  10085. hMemStore,
  10086. pSimpleChain->rgpElement[i]->pCertContext,
  10087. CERT_STORE_ADD_REPLACE_EXISTING,
  10088. NULL))
  10089. {
  10090. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10091. goto CertAddCertificateContextToStoreError;
  10092. }
  10093. }
  10094. pblobPFX->pbData = NULL;
  10095. while (TRUE)
  10096. {
  10097. if (!PFXExportCertStore(
  10098. hMemStore,
  10099. pblobPFX,
  10100. pwszPassword,
  10101. EXPORT_PRIVATE_KEYS | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
  10102. {
  10103. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10104. goto PFXExportCertStoreError;
  10105. }
  10106. if (NULL != pblobPFX->pbData)
  10107. {
  10108. //got it, done
  10109. break;
  10110. }
  10111. pblobPFX->pbData = (BYTE*)MyCoTaskMemAlloc(pblobPFX->cbData);
  10112. if (NULL == pblobPFX->pbData)
  10113. {
  10114. hr = E_OUTOFMEMORY;
  10115. goto MyCoTaskMemAllocError;
  10116. }
  10117. }
  10118. hr = S_OK;
  10119. ErrorReturn:
  10120. LeaveCriticalSection(&m_csXEnroll);
  10121. if (pCertChainContext != NULL)
  10122. {
  10123. MyCertFreeCertificateChain(pCertChainContext);
  10124. }
  10125. if (NULL != hMemStore)
  10126. {
  10127. CertCloseStore(hMemStore, CERT_CLOSE_STORE_CHECK_FLAG);
  10128. }
  10129. return hr;
  10130. TRACE_ERROR(UnexpectedError)
  10131. TRACE_ERROR(CertOpenStoreError)
  10132. TRACE_ERROR(PFXExportCertStoreError)
  10133. TRACE_ERROR(MyCoTaskMemAllocError)
  10134. TRACE_ERROR(CertAddCertificateContextToStoreError)
  10135. TRACE_ERROR(NoCertificateChainError)
  10136. TRACE_ERROR(MyCertGetCertificateChainError)
  10137. SET_HRESULT(EPointerError, E_POINTER)
  10138. }
  10139. HRESULT
  10140. CCEnroll::createPFXWStrBStr(
  10141. IN LPCWSTR pwszPassword,
  10142. OUT BSTR __RPC_FAR *pbstrPFX)
  10143. {
  10144. HRESULT hr;
  10145. CRYPT_DATA_BLOB blobPFX;
  10146. memset(&blobPFX, 0, sizeof(CRYPT_DATA_BLOB));
  10147. hr = createPFXWStr(pwszPassword, &blobPFX);
  10148. if (S_OK != hr)
  10149. {
  10150. goto createPFXWStrError;
  10151. }
  10152. // convert pfx to bstr
  10153. hr = BlobToBstring(&blobPFX, CRYPT_STRING_BASE64, pbstrPFX);
  10154. if (S_OK != hr)
  10155. {
  10156. goto BlobToBstringError;
  10157. }
  10158. hr = S_OK;
  10159. ErrorReturn:
  10160. if(NULL != blobPFX.pbData)
  10161. {
  10162. MyCoTaskMemFree(blobPFX.pbData);
  10163. }
  10164. return(hr);
  10165. TRACE_ERROR(createPFXWStrError)
  10166. TRACE_ERROR(BlobToBstringError)
  10167. }
  10168. HRESULT STDMETHODCALLTYPE
  10169. CCEnroll::createFilePFXWStr(
  10170. IN LPCWSTR pwszPassword,
  10171. IN LPCWSTR pwszPFXFileName)
  10172. {
  10173. HRESULT hr;
  10174. HANDLE hFile = NULL;
  10175. DWORD cb = 0;
  10176. CRYPT_DATA_BLOB blobPFX;
  10177. memset(&blobPFX, 0, sizeof(CRYPT_DATA_BLOB));
  10178. hr = createPFXWStr(pwszPassword, &blobPFX);
  10179. if (S_OK != hr)
  10180. {
  10181. goto createPFXWStrError;
  10182. }
  10183. // open the file
  10184. hFile = CreateFileSafely(pwszPFXFileName);
  10185. if (NULL == hFile)
  10186. {
  10187. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10188. goto CreateFileFileSafelyError;
  10189. }
  10190. // write the pkcs10
  10191. if(!WriteFile(
  10192. hFile,
  10193. blobPFX.pbData,
  10194. blobPFX.cbData,
  10195. &cb,
  10196. NULL))
  10197. {
  10198. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10199. goto WriteFileError;
  10200. }
  10201. hr = S_OK;
  10202. ErrorReturn:
  10203. if(NULL != hFile)
  10204. {
  10205. CloseHandle(hFile);
  10206. }
  10207. if(NULL != blobPFX.pbData)
  10208. {
  10209. MyCoTaskMemFree(blobPFX.pbData);
  10210. }
  10211. return(hr);
  10212. TRACE_ERROR(createPFXWStrError)
  10213. TRACE_ERROR(CreateFileFileSafelyError)
  10214. TRACE_ERROR(WriteFileError)
  10215. }
  10216. HRESULT STDMETHODCALLTYPE
  10217. CCEnroll::setPendingRequestInfoWStr(
  10218. IN LONG lRequestID,
  10219. IN LPCWSTR pwszCADNS,
  10220. IN LPCWSTR pwszCAName,
  10221. IN LPCWSTR pwszFriendlyName
  10222. )
  10223. {
  10224. //------------------------------------------------------------
  10225. //
  10226. // Define locally-scoped helper functions:
  10227. //
  10228. //------------------------------------------------------------
  10229. CEnrollLocalScope(SetPendingRequestInfoHelper):
  10230. // Finds the appropriate cert context to set pending info on using the following algorithm:
  10231. // 1) If a hash value HAS NOT been specified, use the cached cert request.
  10232. // 2) If a hash value HAS been specified, search the request store for a cert with an equivalent
  10233. // hash value and return it. If no such cert can be found, return an error code.
  10234. HRESULT GetPendingRequestCertContext(IN HCERTSTORE hStoreRequest,
  10235. IN CRYPT_DATA_BLOB hashBlob,
  10236. IN PCCERT_CONTEXT pCertContextCachedPendingRequest,
  10237. OUT PCCERT_CONTEXT *pCertContextPendingRequest)
  10238. {
  10239. EquivalentHashCertContextFilter filter(hashBlob);
  10240. if (hashBlob.pbData == NULL)
  10241. {
  10242. // We haven't specified a particular context, use the one we've cached.
  10243. *pCertContextPendingRequest = CertDuplicateCertificateContext(pCertContextCachedPendingRequest);
  10244. return S_OK;
  10245. }
  10246. else
  10247. {
  10248. // Returns the first certificate in the request store with a hash matching
  10249. // pHashBlob.
  10250. return FilteredCertEnumCertificatesInStore
  10251. (hStoreRequest, NULL, &filter, pCertContextPendingRequest);
  10252. }
  10253. }
  10254. DWORD GetPendingInfoBlobSize(IN LONG lRequestID,
  10255. IN LPCWSTR pwszCADNS,
  10256. IN LPCWSTR pwszCAName,
  10257. IN LPCWSTR pwszFriendlyName)
  10258. {
  10259. assert(pwszCADNS != NULL && pwszCAName != NULL && pwszFriendlyName != NULL);
  10260. return (DWORD)(sizeof(lRequestID) + // Request ID
  10261. sizeof(DWORD) + // wcslen(pwszCADNS)
  10262. sizeof(WCHAR) * (wcslen(pwszCADNS) + 1) + // pwszCADNS
  10263. sizeof(DWORD) + // wcslen(pwszCAName)
  10264. sizeof(WCHAR) * (wcslen(pwszCAName) + 1) + // pwszCAName
  10265. sizeof(DWORD) + // wcslen(pwszFriendlyName)
  10266. sizeof(WCHAR) * (wcslen(pwszFriendlyName) + 1) // pwszFriendlyName
  10267. );
  10268. }
  10269. // Combines the supplied pending request information into a CRYPT_DATA_BLOB
  10270. // See wincrypt.h for the format.
  10271. void MakePendingInfoBlob(IN LONG lRequestID,
  10272. IN LPCWSTR pwszCADNS,
  10273. IN LPCWSTR pwszCAName,
  10274. IN LPCWSTR pwszFriendlyName,
  10275. OUT CRYPT_DATA_BLOB pendingInfoBlob)
  10276. {
  10277. LPBYTE pbBlob;
  10278. // None of the inputs should be NULL.
  10279. assert(pwszCADNS != NULL && pwszCAName != NULL && pwszFriendlyName != NULL);
  10280. // Declare an array of the strings we wish to write to the pending info blob
  10281. struct StringsToWrite {
  10282. DWORD cc;
  10283. LPCWSTR pwsz;
  10284. } rgStrings[] = {
  10285. { (DWORD)wcslen(pwszCADNS) + 1, pwszCADNS },
  10286. { (DWORD)wcslen(pwszCAName) + 1, pwszCAName },
  10287. { (DWORD)wcslen(pwszFriendlyName) + 1, pwszFriendlyName }
  10288. };
  10289. // Write the request ID to the blob
  10290. pbBlob = pendingInfoBlob.pbData;
  10291. memcpy(pbBlob, &lRequestID, sizeof(lRequestID));
  10292. pbBlob += sizeof(lRequestID);
  10293. // Write all strings to the blob
  10294. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStrings); dwIndex++)
  10295. {
  10296. memcpy(pbBlob, &rgStrings[dwIndex].cc, sizeof(rgStrings[dwIndex].cc));
  10297. pbBlob += sizeof(rgStrings[dwIndex].cc);
  10298. memcpy(pbBlob, rgStrings[dwIndex].pwsz, rgStrings[dwIndex].cc * sizeof(WCHAR));
  10299. pbBlob += rgStrings[dwIndex].cc * sizeof(WCHAR);
  10300. }
  10301. assert(pbBlob == (pendingInfoBlob.pbData + pendingInfoBlob.cbData));
  10302. }
  10303. CEnrollEndLocalScope;
  10304. //------------------------------------------------------------
  10305. //
  10306. // Begin procedure body.
  10307. //
  10308. //------------------------------------------------------------
  10309. CRYPT_DATA_BLOB pendingInfoBlob;
  10310. HCERTSTORE hStoreRequest;
  10311. HRESULT hr = S_OK;
  10312. PCCERT_CONTEXT pCertContextPendingRequest = NULL;
  10313. ZeroMemory(&pendingInfoBlob, sizeof(pendingInfoBlob));
  10314. EnterCriticalSection(&m_csXEnroll);
  10315. // Input validation:
  10316. if (lRequestID < 0 || pwszCADNS == NULL || pwszCAName == NULL)
  10317. goto InvalidArgErr;
  10318. // NULL is a valid value for pwszFriendlyName. If friendly name is NULL, replace with the empty string:
  10319. if (pwszFriendlyName == NULL) { pwszFriendlyName = L""; }
  10320. if (NULL == (hStoreRequest = GetStore(StoreREQUEST)) )
  10321. goto GetStoreErr;
  10322. // Use our locally-scoped helper function to acquire the appropriate certificate context.
  10323. if (S_OK != (hr = local.GetPendingRequestCertContext
  10324. (hStoreRequest,
  10325. m_hashBlobPendingRequest,
  10326. m_pCertContextPendingRequest,
  10327. &pCertContextPendingRequest)))
  10328. goto GetPendingRequestCertContextErr;
  10329. // Allocate memory for our pending info blob:
  10330. pendingInfoBlob.cbData = local.GetPendingInfoBlobSize
  10331. (lRequestID,
  10332. pwszCADNS,
  10333. pwszCAName,
  10334. pwszFriendlyName);
  10335. pendingInfoBlob.pbData = (LPBYTE)LocalAlloc(LPTR, pendingInfoBlob.cbData);
  10336. if (NULL == pendingInfoBlob.pbData)
  10337. goto MemoryErr;
  10338. // Combine our arguments into a "pending info" blob.
  10339. local.MakePendingInfoBlob
  10340. (lRequestID,
  10341. pwszCADNS,
  10342. pwszCAName,
  10343. pwszFriendlyName,
  10344. pendingInfoBlob);
  10345. // Use our pending info blob to assign the certificate context property.
  10346. if (!CertSetCertificateContextProperty
  10347. (pCertContextPendingRequest,
  10348. CERT_ENROLLMENT_PROP_ID,
  10349. 0,
  10350. &pendingInfoBlob))
  10351. {
  10352. // Failed to set the context property.
  10353. goto CertSetCertificateContextPropertyErr;
  10354. }
  10355. // We've completed successfully.
  10356. hr = S_OK;
  10357. CommonReturn:
  10358. if (NULL != pendingInfoBlob.pbData) { LocalFree(pendingInfoBlob.pbData); }
  10359. if (NULL != pCertContextPendingRequest) { CertFreeCertificateContext(pCertContextPendingRequest); }
  10360. LeaveCriticalSection(&m_csXEnroll);
  10361. return hr;
  10362. ErrorReturn:
  10363. goto CommonReturn;
  10364. SET_HRESULT(CertSetCertificateContextPropertyErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10365. SET_HRESULT(GetPendingRequestCertContextErr, hr);
  10366. SET_HRESULT(GetStoreErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10367. SET_HRESULT(InvalidArgErr, E_INVALIDARG);
  10368. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  10369. }
  10370. //--------------------------------------------------------------------------------
  10371. //
  10372. // THIS METHOD IS NOT SAFE FOR SCRIPTING
  10373. //
  10374. //--------------------------------------------------------------------------------
  10375. HRESULT STDMETHODCALLTYPE
  10376. CCEnroll::enumPendingRequestWStr(
  10377. IN LONG lIndex,
  10378. IN LONG lDesiredProperty,
  10379. OUT LPVOID ppProperty
  10380. )
  10381. {
  10382. //------------------------------------------------------------
  10383. //
  10384. // Define locally scoped helper functions.
  10385. //
  10386. //------------------------------------------------------------
  10387. CEnrollLocalScope(EnumPendingRequestHelper):
  10388. CRYPT_DATA_BLOB dataBlob;
  10389. HRESULT GetContextPropertySimple(PCCERT_CONTEXT pCertContext, DWORD dwPropID)
  10390. {
  10391. BOOL fDone = FALSE;
  10392. dataBlob.pbData = NULL;
  10393. dataBlob.cbData = 0x150;
  10394. do {
  10395. if (dataBlob.pbData != NULL) { LocalFree(dataBlob.pbData); }
  10396. dataBlob.pbData = (LPBYTE)LocalAlloc(LPTR, dataBlob.cbData);
  10397. if (dataBlob.pbData == NULL) { return E_OUTOFMEMORY; }
  10398. if (!CertGetCertificateContextProperty
  10399. (pCertContext,
  10400. dwPropID,
  10401. (LPVOID)dataBlob.pbData,
  10402. &(dataBlob.cbData)))
  10403. {
  10404. if (GetLastError() != ERROR_MORE_DATA)
  10405. return MY_HRESULT_FROM_WIN32(GetLastError());
  10406. }
  10407. else
  10408. {
  10409. fDone = TRUE;
  10410. }
  10411. } while (!fDone);
  10412. return S_OK;
  10413. }
  10414. // Extracts the next packed string from our pending info blob.
  10415. // If pbString is non-NULL, it must be large enough to hold the entire string.
  10416. LPBYTE GetNextString(IN LPBYTE pbBlob, OUT DWORD *pcbSize, OUT LPBYTE pbString) {
  10417. DWORD dwSize;
  10418. memcpy(&dwSize, pbBlob, sizeof(DWORD));
  10419. dwSize *= sizeof(WCHAR); // Convert to count in bytes.
  10420. if (NULL != pcbSize) {
  10421. *pcbSize = dwSize;
  10422. }
  10423. pbBlob += sizeof(DWORD);
  10424. if (NULL != pbString) {
  10425. memcpy(pbString, pbBlob, dwSize);
  10426. }
  10427. pbBlob += dwSize;
  10428. return pbBlob;
  10429. }
  10430. HRESULT getRequestID(PCCERT_CONTEXT pCertContext, long *pplProperty) {
  10431. HRESULT hr;
  10432. if (S_OK == (hr = GetContextPropertySimple(pCertContext, CERT_ENROLLMENT_PROP_ID)))
  10433. *pplProperty = *((long *)dataBlob.pbData);
  10434. return hr;
  10435. }
  10436. HRESULT getCAName(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10437. DWORD dwSize;
  10438. HRESULT hr;
  10439. LPBYTE pb;
  10440. if (S_OK == (hr = GetContextPropertySimple(pCertContext, CERT_ENROLLMENT_PROP_ID)))
  10441. {
  10442. pb = dataBlob.pbData + sizeof(DWORD); // pb points to DNS Name blob
  10443. pb = GetNextString(pb, NULL, NULL); // pb points to CA Name blob
  10444. GetNextString(pb, &dwSize, NULL); // dwSize = size in chars of CA Name
  10445. // If pbData is NULL, we're just doing a size check.
  10446. if (pDataBlobProperty->pbData != NULL)
  10447. {
  10448. if (pDataBlobProperty->cbData < dwSize)
  10449. {
  10450. hr = MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  10451. }
  10452. else
  10453. {
  10454. GetNextString(pb, NULL, pDataBlobProperty->pbData);
  10455. }
  10456. }
  10457. pDataBlobProperty->cbData = dwSize;
  10458. }
  10459. return hr;
  10460. }
  10461. HRESULT getCADNSName(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10462. DWORD dwSize;
  10463. HRESULT hr;
  10464. LPBYTE pb;
  10465. if (S_OK == (hr = GetContextPropertySimple(pCertContext, CERT_ENROLLMENT_PROP_ID)))
  10466. {
  10467. pb = dataBlob.pbData + sizeof(DWORD); // pb points to DNS Name blob
  10468. GetNextString(pb, &dwSize, NULL); // dwSize = size in chars of CA Name
  10469. // If pbData is NULL, we're just doing a size check.
  10470. if (pDataBlobProperty->pbData != NULL)
  10471. {
  10472. if (pDataBlobProperty->cbData < dwSize)
  10473. {
  10474. hr = MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  10475. }
  10476. else
  10477. {
  10478. GetNextString(pb, NULL, pDataBlobProperty->pbData);
  10479. }
  10480. }
  10481. pDataBlobProperty->cbData = dwSize;
  10482. }
  10483. return hr;
  10484. }
  10485. HRESULT getCAFriendlyName(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10486. DWORD dwSize;
  10487. HRESULT hr;
  10488. LPBYTE pb;
  10489. if (S_OK == (hr = GetContextPropertySimple(pCertContext, CERT_ENROLLMENT_PROP_ID)))
  10490. {
  10491. // Set pb to point to the start of the CA name blob
  10492. pb = dataBlob.pbData + sizeof(DWORD); // pb points to DNS Name blob
  10493. pb = GetNextString(pb, NULL, NULL); // pb points to CA Name blob
  10494. pb = GetNextString(pb, NULL, NULL); // pb points to Friendly Name blob
  10495. // dwSize <-- size in chars of CA Name
  10496. GetNextString(pb, &dwSize, NULL);
  10497. // If pbData is NULL, we're just doing a size check.
  10498. if (pDataBlobProperty->pbData != NULL)
  10499. {
  10500. if (pDataBlobProperty->cbData < dwSize)
  10501. {
  10502. hr = MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  10503. }
  10504. else
  10505. {
  10506. GetNextString(pb, NULL, pDataBlobProperty->pbData);
  10507. }
  10508. }
  10509. pDataBlobProperty->cbData = dwSize;
  10510. }
  10511. return hr;
  10512. }
  10513. HRESULT getHash(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10514. HRESULT hr;
  10515. if (S_OK == (hr = GetContextPropertySimple(pCertContext, CERT_HASH_PROP_ID)))
  10516. {
  10517. // If pbData is NULL, we're just doing a size check.
  10518. if (pDataBlobProperty->pbData != NULL)
  10519. {
  10520. if (pDataBlobProperty->cbData < dataBlob.cbData)
  10521. {
  10522. hr = MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  10523. }
  10524. else
  10525. {
  10526. memcpy(pDataBlobProperty->pbData, dataBlob.pbData, dataBlob.cbData);
  10527. }
  10528. }
  10529. pDataBlobProperty->cbData = dataBlob.cbData;
  10530. }
  10531. return hr;
  10532. }
  10533. HRESULT getDate(PCCERT_CONTEXT pCertContext, PFILETIME pftProperty) {
  10534. *pftProperty = pCertContext->pCertInfo->NotAfter;
  10535. return S_OK;
  10536. }
  10537. HRESULT getTemplateName(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10538. CERT_NAME_VALUE *pCertTemplateNameValue = NULL;
  10539. DWORD cbCertTemplateNameValue;
  10540. DWORD cbRequired = 0;
  10541. HRESULT hr = S_OK;
  10542. PCERT_EXTENSION pCertTemplateExtension = NULL;
  10543. if (NULL == (pCertTemplateExtension = CertFindExtension
  10544. (szOID_ENROLL_CERTTYPE_EXTENSION,
  10545. pCertContext->pCertInfo->cExtension,
  10546. pCertContext->pCertInfo->rgExtension)))
  10547. return E_INVALIDARG;
  10548. if (!CryptDecodeObject
  10549. (pCertContext->dwCertEncodingType,
  10550. X509_UNICODE_ANY_STRING,
  10551. pCertTemplateExtension->Value.pbData,
  10552. pCertTemplateExtension->Value.cbData,
  10553. 0,
  10554. NULL,
  10555. &cbCertTemplateNameValue) || (cbCertTemplateNameValue == 0))
  10556. goto CryptDecodeObjectErr;
  10557. pCertTemplateNameValue = (CERT_NAME_VALUE *)LocalAlloc(LPTR, cbCertTemplateNameValue);
  10558. if (NULL == pCertTemplateNameValue)
  10559. goto MemoryErr;
  10560. if (!CryptDecodeObject
  10561. (pCertContext->dwCertEncodingType,
  10562. X509_UNICODE_ANY_STRING,
  10563. pCertTemplateExtension->Value.pbData,
  10564. pCertTemplateExtension->Value.cbData,
  10565. 0,
  10566. (void *)(pCertTemplateNameValue),
  10567. &cbCertTemplateNameValue))
  10568. goto CryptDecodeObjectErr;
  10569. cbRequired = sizeof(WCHAR) * (DWORD)(wcslen((LPWSTR)(pCertTemplateNameValue->Value.pbData)) + 1);
  10570. if (NULL != pDataBlobProperty->pbData)
  10571. {
  10572. // Make sure we've allocated a large enough buffer:
  10573. if (pDataBlobProperty->cbData < cbRequired) { goto MoreDataErr; }
  10574. // Write the template name to the OUT param:
  10575. wcscpy((LPWSTR)pDataBlobProperty->pbData, (LPWSTR)(pCertTemplateNameValue->Value.pbData));
  10576. }
  10577. hr = S_OK;
  10578. CommonReturn:
  10579. // Assign the size of the template name to the cb of the OUT param.
  10580. // This should be done for all code paths.
  10581. pDataBlobProperty->cbData = cbRequired;
  10582. // Free resources:
  10583. if (NULL != pCertTemplateNameValue) { LocalFree(pCertTemplateNameValue); }
  10584. return hr;
  10585. ErrorReturn:
  10586. goto CommonReturn;
  10587. SET_HRESULT(CryptDecodeObjectErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10588. SET_HRESULT(MoreDataErr, MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA));
  10589. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  10590. }
  10591. HRESULT getTemplateOID(PCCERT_CONTEXT pCertContext, PCRYPT_DATA_BLOB pDataBlobProperty) {
  10592. CERT_TEMPLATE_EXT *pCertTemplateExt = NULL;
  10593. DWORD cbCertTemplateExt = 0;
  10594. DWORD cbRequired = 0;
  10595. HRESULT hr;
  10596. LPWSTR pwszOID = NULL;
  10597. PCERT_EXTENSION pCertExtension = NULL;
  10598. if (NULL == (pCertExtension = CertFindExtension
  10599. (szOID_CERTIFICATE_TEMPLATE,
  10600. pCertContext->pCertInfo->cExtension,
  10601. pCertContext->pCertInfo->rgExtension)))
  10602. return E_INVALIDARG;
  10603. if (FALSE == CryptDecodeObject
  10604. (pCertContext->dwCertEncodingType,
  10605. X509_CERTIFICATE_TEMPLATE,
  10606. pCertExtension->Value.pbData,
  10607. pCertExtension->Value.cbData,
  10608. 0,
  10609. NULL,
  10610. &cbCertTemplateExt) || (cbCertTemplateExt == 0))
  10611. goto CryptDecodeObjectErr;
  10612. pCertTemplateExt = (CERT_TEMPLATE_EXT *)LocalAlloc(LPTR, cbCertTemplateExt);
  10613. if (NULL == pCertTemplateExt)
  10614. goto MemoryErr;
  10615. if (FALSE == CryptDecodeObject
  10616. (pCertContext->dwCertEncodingType,
  10617. X509_CERTIFICATE_TEMPLATE,
  10618. pCertExtension->Value.pbData,
  10619. pCertExtension->Value.cbData,
  10620. 0,
  10621. (void *)(pCertTemplateExt),
  10622. &cbCertTemplateExt))
  10623. goto CryptDecodeObjectErr;
  10624. cbRequired = sizeof(WCHAR) * (DWORD)(strlen(pCertTemplateExt->pszObjId) + 1);
  10625. // See if we're just doing a size check:
  10626. if (NULL != pDataBlobProperty->pbData)
  10627. {
  10628. // Make sure we've allocated a large enough buffer:
  10629. if (pDataBlobProperty->cbData < cbRequired) { goto MoreDataErr; }
  10630. // Convert the OID to a LPWSTR:
  10631. pwszOID = WideFromMB(pCertTemplateExt->pszObjId);
  10632. if (NULL == pwszOID)
  10633. goto WideFromMBErr;
  10634. // Write the template OID to the OUT param:
  10635. wcscpy((LPWSTR)pDataBlobProperty->pbData, pwszOID);
  10636. }
  10637. hr = S_OK;
  10638. CommonReturn:
  10639. // Assign the size of the OID to the cb of the OUT param.
  10640. // This should be done for all code paths.
  10641. pDataBlobProperty->cbData = cbRequired;
  10642. // Free resources:
  10643. if (NULL != pCertTemplateExt) { LocalFree(pCertTemplateExt); }
  10644. if (NULL != pwszOID) { MyCoTaskMemFree(pwszOID); }
  10645. return hr;
  10646. ErrorReturn:
  10647. goto CommonReturn;
  10648. SET_HRESULT(CryptDecodeObjectErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10649. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  10650. SET_HRESULT(MoreDataErr, MY_HRESULT_FROM_WIN32(ERROR_MORE_DATA));
  10651. SET_HRESULT(WideFromMBErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10652. }
  10653. HRESULT getVersion(PCCERT_CONTEXT pCertContext, long *plVersion) {
  10654. CERT_TEMPLATE_EXT *pCertTemplateExt = NULL;
  10655. DWORD cbCertTemplateExt = 0;
  10656. HRESULT hr;
  10657. PCERT_EXTENSION pCertExtension = NULL;
  10658. if (NULL == (pCertExtension = CertFindExtension
  10659. (szOID_CERTIFICATE_TEMPLATE,
  10660. pCertContext->pCertInfo->cExtension,
  10661. pCertContext->pCertInfo->rgExtension)))
  10662. return E_INVALIDARG;
  10663. if (FALSE == CryptDecodeObject
  10664. (pCertContext->dwCertEncodingType,
  10665. X509_CERTIFICATE_TEMPLATE,
  10666. pCertExtension->Value.pbData,
  10667. pCertExtension->Value.cbData,
  10668. 0,
  10669. NULL,
  10670. &cbCertTemplateExt) || (cbCertTemplateExt == 0))
  10671. goto CryptDecodeObjectErr;
  10672. pCertTemplateExt = (CERT_TEMPLATE_EXT *)LocalAlloc(LPTR, cbCertTemplateExt);
  10673. if (NULL == pCertTemplateExt)
  10674. goto MemoryErr;
  10675. if (FALSE == CryptDecodeObject
  10676. (pCertContext->dwCertEncodingType,
  10677. X509_CERTIFICATE_TEMPLATE,
  10678. pCertExtension->Value.pbData,
  10679. pCertExtension->Value.cbData,
  10680. 0,
  10681. (void *)(pCertTemplateExt),
  10682. &cbCertTemplateExt))
  10683. goto CryptDecodeObjectErr;
  10684. *plVersion = (long)pCertTemplateExt->dwMajorVersion;
  10685. hr = S_OK;
  10686. CommonReturn:
  10687. // Free resources:
  10688. if (NULL != pCertTemplateExt) { LocalFree(pCertTemplateExt); }
  10689. return hr;
  10690. ErrorReturn:
  10691. goto CommonReturn;
  10692. SET_HRESULT(CryptDecodeObjectErr, MY_HRESULT_FROM_WIN32(GetLastError()));
  10693. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  10694. }
  10695. void InitLocalScope() {
  10696. dataBlob.cbData = 0;
  10697. dataBlob.pbData = NULL;
  10698. }
  10699. void FreeLocalScope() { if (dataBlob.pbData != NULL) { LocalFree(dataBlob.pbData); } }
  10700. CEnrollEndLocalScope;
  10701. //------------------------------------------------------------
  10702. //
  10703. // Begin procedure body.
  10704. //
  10705. //------------------------------------------------------------
  10706. // FIXME: index is 0 based, correct?
  10707. // m_dwLastPendingRequestIndex = 0;
  10708. // m_pCertContextLastEnumerated
  10709. HCERTSTORE hStoreRequest = NULL;
  10710. HRESULT hr = S_OK;
  10711. PCCERT_CONTEXT pCertContext = NULL;
  10712. // Input validiation:
  10713. if (lIndex != XEPR_ENUM_FIRST && (lIndex < 0 || (ppProperty == NULL)))
  10714. return E_INVALIDARG;
  10715. if (0 != m_dwEnabledSafteyOptions) // not safe for scripting
  10716. return E_ACCESSDENIED;
  10717. // Init:
  10718. local.InitLocalScope();
  10719. EnterCriticalSection(&m_csXEnroll);
  10720. if ( NULL == (hStoreRequest = GetStore(StoreREQUEST)) )
  10721. goto ErrorCertOpenRequestStore;
  10722. // If we're passed the ENUM_FIRST flag, reconstruct a snapshot of the request store.
  10723. //
  10724. if (lIndex == XEPR_ENUM_FIRST)
  10725. {
  10726. if (NULL != this->m_pPendingRequestTable) { delete this->m_pPendingRequestTable; }
  10727. this->m_pPendingRequestTable = new PendingRequestTable;
  10728. if (NULL == this->m_pPendingRequestTable)
  10729. goto MemoryErr;
  10730. if (S_OK != (hr = this->m_pPendingRequestTable->construct(hStoreRequest)))
  10731. goto ErrorConstructPendingTable;
  10732. // All done, return.
  10733. goto CommonReturn;
  10734. }
  10735. // We want the lIndex'th element the request store.
  10736. // First, ensure that the enumeration is initialized:
  10737. if (NULL == m_pPendingRequestTable)
  10738. goto PointerErr;
  10739. // Index past the end of the table.
  10740. if (this->m_pPendingRequestTable->size() <= (DWORD)lIndex)
  10741. {
  10742. hr = MY_HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
  10743. goto ErrorReturn;
  10744. }
  10745. pCertContext = (*this->m_pPendingRequestTable)[(DWORD)lIndex];
  10746. switch (lDesiredProperty)
  10747. {
  10748. case XEPR_REQUESTID: hr = local.getRequestID (pCertContext, (long *)ppProperty); break;
  10749. case XEPR_CANAME: hr = local.getCAName (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10750. case XEPR_CAFRIENDLYNAME: hr = local.getCAFriendlyName (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10751. case XEPR_CADNS: hr = local.getCADNSName (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10752. case XEPR_DATE: hr = local.getDate (pCertContext, (PFILETIME)ppProperty); break;
  10753. case XEPR_V1TEMPLATENAME: hr = local.getTemplateName (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10754. case XEPR_V2TEMPLATEOID: hr = local.getTemplateOID (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10755. case XEPR_VERSION: hr = local.getVersion (pCertContext, (long *)ppProperty); break;
  10756. case XEPR_HASH: hr = local.getHash (pCertContext, (PCRYPT_DATA_BLOB)ppProperty); break;
  10757. default:
  10758. hr = E_INVALIDARG;
  10759. }
  10760. CommonReturn:
  10761. local.FreeLocalScope();
  10762. LeaveCriticalSection(&m_csXEnroll);
  10763. return hr;
  10764. ErrorReturn:
  10765. goto CommonReturn;
  10766. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  10767. SET_HRESULT(PointerErr, E_POINTER);
  10768. TRACE_ERROR(ErrorCertOpenRequestStore);
  10769. TRACE_ERROR(ErrorConstructPendingTable);
  10770. }
  10771. HRESULT STDMETHODCALLTYPE
  10772. CCEnroll::removePendingRequestWStr
  10773. (IN CRYPT_DATA_BLOB thumbPrintBlob
  10774. )
  10775. {
  10776. EquivalentHashCertContextFilter equivHashFilter(thumbPrintBlob);
  10777. PendingCertContextFilter pendingCertFilter;
  10778. // combinedFilter now only allows PENDING requests which match the specified thumbprint.
  10779. CompositeCertContextFilter combinedFilter(&equivHashFilter, &pendingCertFilter);
  10780. HCERTSTORE hStoreRequest = NULL;
  10781. HRESULT hr;
  10782. PCCERT_CONTEXT pCertContext = NULL;
  10783. EnterCriticalSection(&m_csXEnroll);
  10784. // Input validation.
  10785. if (NULL == thumbPrintBlob.pbData)
  10786. {
  10787. hr = E_INVALIDARG;
  10788. goto ErrorReturn;
  10789. }
  10790. if ( NULL == (hStoreRequest = GetStore(StoreREQUEST)) )
  10791. {
  10792. hr = E_UNEXPECTED;
  10793. goto ErrorReturn;
  10794. }
  10795. if (S_OK != (hr = FilteredCertEnumCertificatesInStore
  10796. (hStoreRequest,
  10797. NULL,
  10798. &combinedFilter,
  10799. &pCertContext)))
  10800. goto ErrorReturn;
  10801. if (!CertDeleteCertificateFromStore(pCertContext))
  10802. {
  10803. hr = MY_HRESULT_FROM_WIN32(GetLastError());
  10804. // CertDeleteCertificateFromStore *always* deletes the cert context.
  10805. pCertContext = NULL;
  10806. goto ErrorReturn;
  10807. }
  10808. pCertContext = NULL;
  10809. hr = S_OK;
  10810. CommonReturn:
  10811. LeaveCriticalSection(&m_csXEnroll);
  10812. return hr;
  10813. ErrorReturn:
  10814. if (pCertContext != NULL) { CertFreeCertificateContext(pCertContext); }
  10815. goto CommonReturn;
  10816. }
  10817. HRESULT FilteredCertEnumCertificatesInStore(IN HCERTSTORE hStore,
  10818. IN PCCERT_CONTEXT pCertContext,
  10819. IN CertContextFilter *pFilter,
  10820. OUT PCCERT_CONTEXT *pCertContextNext)
  10821. {
  10822. BOOL fFilterResult;
  10823. HRESULT hr = S_OK;
  10824. PCCERT_CONTEXT pCertContextPrev = pCertContext;
  10825. while (NULL != (pCertContext = CertEnumCertificatesInStore(hStore, pCertContextPrev)))
  10826. {
  10827. if (S_OK != (hr = pFilter->accept(pCertContext, &fFilterResult)))
  10828. return hr;
  10829. if (fFilterResult) // We've found the next cert context in the filtered enumeration.
  10830. {
  10831. *pCertContextNext = pCertContext;
  10832. return S_OK;
  10833. }
  10834. pCertContextPrev = pCertContext;
  10835. }
  10836. return MY_HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
  10837. }
  10838. static LPVOID MyLocalAlloc(ULONG cb) {
  10839. return((LPVOID) LocalAlloc(LPTR, (UINT) cb));
  10840. }
  10841. static LPVOID MyLocalRealloc(LPVOID ptr, ULONG cb) {
  10842. return((LPVOID) LocalReAlloc((HLOCAL) ptr, (UINT) cb, LMEM_MOVEABLE));
  10843. }
  10844. static void MyLocalFree(LPVOID ptr) {
  10845. LocalFree((HLOCAL) ptr);
  10846. }
  10847. //
  10848. // From xtan, an explanation of the "no-COM" APIs:
  10849. // "In early time xenroll interface IDs were not in uuid.lib so this
  10850. // was a convenient C interface for people to get xenroll COM interfaces without
  10851. // call CoCreateInstance. It is not in MSDN but it is in SDK headers.
  10852. // I created the same API for consistency when I created ICEnroll4."
  10853. //
  10854. void * WINAPI PGetIEnrollNoCOM(const IID &iid) {
  10855. void * pvoid = NULL;
  10856. IClassFactory * pIClassFactory = NULL;
  10857. HRESULT hr = S_OK;
  10858. MyCoTaskMemAlloc = MyLocalAlloc;
  10859. MyCoTaskMemFree = MyLocalFree;
  10860. MyCoTaskMemRealloc = MyLocalRealloc;
  10861. if( S_OK != (hr = DllGetClassObject(CLSID_CEnroll2, IID_IClassFactory, (void **) &pIClassFactory)) ) {
  10862. pIClassFactory = NULL;
  10863. }
  10864. else if( S_OK != (hr = pIClassFactory->CreateInstance(NULL, iid, &pvoid)) ) {
  10865. pvoid = NULL;
  10866. }
  10867. if(pIClassFactory != NULL) {
  10868. pIClassFactory->Release();
  10869. pIClassFactory = NULL;
  10870. }
  10871. SetLastError(hr);
  10872. return(pvoid);
  10873. }
  10874. IEnroll * WINAPI PIEnrollGetNoCOM(void)
  10875. {
  10876. return( (IEnroll *) PGetIEnrollNoCOM(IID_IEnroll) );
  10877. }
  10878. IEnroll2 * WINAPI PIEnroll2GetNoCOM(void)
  10879. {
  10880. return( (IEnroll2 *) PGetIEnrollNoCOM(IID_IEnroll2) );
  10881. }
  10882. IEnroll4 * WINAPI PIEnroll4GetNoCOM(void)
  10883. {
  10884. return( (IEnroll4 *) PGetIEnrollNoCOM(IID_IEnroll4) );
  10885. }
  10886. HRESULT PendingRequestTable::resize(DWORD dwNewSize)
  10887. {
  10888. TableElem * newTable = NULL;
  10889. if (dwNewSize <= 0)
  10890. return E_INVALIDARG;
  10891. newTable = (TableElem *)LocalAlloc(LPTR, sizeof(TableElem) * dwNewSize);
  10892. if (NULL == newTable)
  10893. return E_OUTOFMEMORY;
  10894. if (NULL != this->table)
  10895. {
  10896. memcpy(newTable, this->table, this->dwElemSize * sizeof(TableElem));
  10897. LocalFree(this->table);
  10898. }
  10899. this->dwElemSize = dwNewSize;
  10900. this->table = newTable;
  10901. return S_OK;
  10902. }
  10903. HRESULT PendingRequestTable::add(TableElem tePendingRequest)
  10904. {
  10905. HRESULT hr;
  10906. if (this->dwElemCount > this->dwElemSize) { return E_UNEXPECTED; }
  10907. else if (this->dwElemCount == this->dwElemSize)
  10908. {
  10909. // Need to allocate more memory:
  10910. DWORD dwNewSize = this->dwElemSize < 100 ? 100 : this->dwElemSize * 2;
  10911. if (S_OK != (hr = this->resize(dwNewSize)))
  10912. return hr;
  10913. }
  10914. this->table[this->dwElemCount++] = tePendingRequest;
  10915. return S_OK;
  10916. }
  10917. PendingRequestTable::PendingRequestTable() : table(NULL), dwElemSize(0), dwElemCount(0)
  10918. { }
  10919. PendingRequestTable::~PendingRequestTable()
  10920. {
  10921. if (NULL != this->table)
  10922. {
  10923. for (DWORD dwIndex = 0; dwIndex < dwElemCount; dwIndex++)
  10924. {
  10925. CertFreeCertificateContext(this->table[dwIndex].pCertContext);
  10926. }
  10927. LocalFree(this->table);
  10928. }
  10929. }
  10930. HRESULT PendingRequestTable::construct(HCERTSTORE hStore)
  10931. {
  10932. HRESULT hr = S_OK;
  10933. PendingCertContextFilter pendingFilter;
  10934. PCCERT_CONTEXT pCertContext = NULL;
  10935. PCCERT_CONTEXT pCertContextPrev = NULL;
  10936. TableElem tePendingRequest;
  10937. // Enumerate all pending cert contexts, and add them to our table:
  10938. for (DWORD dwIndex = 0; TRUE; dwIndex++)
  10939. {
  10940. if (S_OK != (hr = FilteredCertEnumCertificatesInStore
  10941. (hStore,
  10942. pCertContextPrev,
  10943. &pendingFilter,
  10944. &pCertContext)))
  10945. break;
  10946. tePendingRequest.pCertContext = CertDuplicateCertificateContext(pCertContext);
  10947. this->add(tePendingRequest);
  10948. pCertContextPrev = pCertContext;
  10949. }
  10950. return hr == MY_HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND) ? S_OK : hr;
  10951. }