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

454 lines
8.8 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: keyenum.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. //+---------------------------------------------------------------------------
  11. //
  12. // File: keyenum.cpp
  13. //
  14. // Contents: key container and cert store operations
  15. //
  16. // History: 08/97 xtan
  17. //
  18. //----------------------------------------------------------------------------
  19. #include "pch.cpp"
  20. #pragma hdrstop
  21. #include "cscsp.h"
  22. #include "csdisp.h"
  23. #define __dwFILE__ __dwFILE_INITLIB_KEYENUM_CPP__
  24. // Key Enumeration
  25. // move point to top
  26. KEY_LIST*
  27. topKeyList(KEY_LIST *pKeyList)
  28. {
  29. while (pKeyList->last)
  30. {
  31. pKeyList = pKeyList->last;
  32. }
  33. return pKeyList;
  34. }
  35. // move point to end
  36. KEY_LIST*
  37. endKeyList(KEY_LIST *pKeyList)
  38. {
  39. while (pKeyList->next)
  40. {
  41. pKeyList = pKeyList->next;
  42. }
  43. return pKeyList;
  44. }
  45. // add to end
  46. void
  47. addKeyList(KEY_LIST **ppKeyList, KEY_LIST *pKey)
  48. {
  49. KEY_LIST *pKeyList = *ppKeyList;
  50. if (NULL == pKeyList)
  51. {
  52. *ppKeyList = pKey;
  53. }
  54. else
  55. {
  56. // go to end
  57. pKeyList = endKeyList(pKeyList);
  58. // add
  59. pKeyList->next = pKey;
  60. pKey->last = pKeyList;
  61. }
  62. }
  63. KEY_LIST *
  64. newKey(
  65. CHAR *pszName)
  66. {
  67. HRESULT hr = S_OK;
  68. KEY_LIST *pKey = NULL;
  69. if (NULL != pszName)
  70. {
  71. pKey = (KEY_LIST *) LocalAlloc(LMEM_FIXED, sizeof(*pKey));
  72. if (NULL == pKey)
  73. {
  74. hr = E_OUTOFMEMORY;
  75. _JumpError(hr, error, "LocalAlloc");
  76. }
  77. if (!myConvertSzToWsz(&pKey->pwszName, pszName, -1))
  78. {
  79. hr = E_OUTOFMEMORY;
  80. _JumpError(hr, error, "myConvertSzToWsz");
  81. }
  82. pKey->last = NULL;
  83. pKey->next = NULL;
  84. }
  85. error:
  86. if (S_OK != hr)
  87. {
  88. if (NULL != pKey)
  89. {
  90. LocalFree(pKey);
  91. pKey = NULL;
  92. }
  93. SetLastError(hr);
  94. }
  95. return(pKey);
  96. }
  97. void
  98. freeKey(KEY_LIST *pKey)
  99. {
  100. if (pKey)
  101. {
  102. if (pKey->pwszName)
  103. {
  104. LocalFree(pKey->pwszName);
  105. }
  106. LocalFree(pKey);
  107. }
  108. }
  109. VOID
  110. csiFreeKeyList(
  111. IN OUT KEY_LIST *pKeyList)
  112. {
  113. KEY_LIST *pNext;
  114. if (pKeyList)
  115. {
  116. // go top
  117. pKeyList = topKeyList(pKeyList);
  118. do
  119. {
  120. pNext = pKeyList->next;
  121. freeKey(pKeyList);
  122. pKeyList = pNext;
  123. } while (pKeyList);
  124. }
  125. }
  126. HRESULT
  127. csiGetKeyList(
  128. IN DWORD dwProvType,
  129. IN WCHAR const *pwszProvName,
  130. IN BOOL fMachineKeySet,
  131. IN BOOL fSilent,
  132. OUT KEY_LIST **ppKeyList)
  133. {
  134. HCRYPTPROV hProv = NULL;
  135. BYTE *pbData = NULL;
  136. DWORD cbData;
  137. DWORD cb;
  138. DWORD dwFirstKeyFlag;
  139. HRESULT hr;
  140. BOOL bRetVal;
  141. KEY_LIST * pklTravel;
  142. BOOL fFoundDefaultKey;
  143. DWORD dwSilent = fSilent? CRYPT_SILENT : 0;
  144. DWORD dwFlags;
  145. KEY_LIST *pKeyList = NULL;
  146. KEY_LIST *pKey = NULL;
  147. *ppKeyList = NULL;
  148. if (NULL == pwszProvName)
  149. {
  150. // explicitly disallowed because NULL is valid for CryptAcquireContext
  151. hr = E_INVALIDARG;
  152. _JumpError(hr, error, "NULL parm");
  153. }
  154. // get a prov handle for key enum
  155. dwFlags = CRYPT_VERIFYCONTEXT;
  156. while (TRUE)
  157. {
  158. DBGPRINT((
  159. DBG_SS_CERTLIBI,
  160. "myCertSrvCryptAcquireContext(%ws, f=%x, m=%x)\n",
  161. pwszProvName,
  162. dwFlags | dwSilent,
  163. fMachineKeySet));
  164. if (myCertSrvCryptAcquireContext(
  165. &hProv,
  166. NULL,
  167. pwszProvName,
  168. dwProvType,
  169. dwFlags | dwSilent,
  170. fMachineKeySet))
  171. {
  172. break; // Success!
  173. }
  174. hr = myHLastError();
  175. _PrintErrorStr2(hr, "myCertSrvCryptAcquireContext", pwszProvName, hr);
  176. // MITVcsp can't support a verify context, create a dummy container
  177. if ((CRYPT_VERIFYCONTEXT & dwFlags) &&
  178. 0 == wcscmp(pwszProvName, L"MITV Smartcard Crypto Provider V0.2"))
  179. {
  180. dwFlags &= ~CRYPT_VERIFYCONTEXT;
  181. dwFlags |= CRYPT_NEWKEYSET;
  182. continue;
  183. }
  184. // Exchange can't handle fMachineKeySet or CRYPT_SILENT
  185. if ((fMachineKeySet || (CRYPT_SILENT & dwSilent)) &&
  186. NTE_BAD_FLAGS == hr &&
  187. 0 == wcscmp(pwszProvName, L"Microsoft Exchange Cryptographic Provider v1.0"))
  188. {
  189. dwSilent &= ~CRYPT_SILENT;
  190. fMachineKeySet = FALSE;
  191. continue;
  192. }
  193. _JumpErrorStr(hr, error, "myCertSrvCryptAcquireContext", pwszProvName);
  194. }
  195. // Enumerate a key so we can get the maximum buffer size required.
  196. // The first key may be a bad one, so we may have to assume a fixed buffer.
  197. hr = S_OK;
  198. cbData = 0;
  199. bRetVal = CryptGetProvParam(
  200. hProv,
  201. PP_ENUMCONTAINERS,
  202. NULL,
  203. &cbData,
  204. CRYPT_FIRST);
  205. DBGPRINT((
  206. DBG_SS_CERTLIBI,
  207. "CryptGetProvParam(%ws) -> cb=%d, bRet=%d\n",
  208. pwszProvName,
  209. cbData,
  210. bRetVal));
  211. if (!bRetVal)
  212. {
  213. // We'd like to skip the bad key (key container with long name?),
  214. // but we get stuck enumerating the same entry over and over again.
  215. // Guess at the maximum size...
  216. hr = myHLastError();
  217. _PrintErrorStr2(
  218. hr,
  219. "CryptGetProvParam(ignored: use 2 * MAX_PATH)",
  220. pwszProvName,
  221. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS));
  222. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) != hr)
  223. {
  224. cbData = 0;
  225. hr = S_OK;
  226. }
  227. }
  228. if (S_OK == hr)
  229. {
  230. if (0 == cbData)
  231. {
  232. cbData = 2 * MAX_PATH * sizeof(CHAR);
  233. }
  234. // allocate the buffer
  235. pbData = (BYTE *) LocalAlloc(LMEM_FIXED, cbData);
  236. if (NULL == pbData)
  237. {
  238. hr = E_OUTOFMEMORY;
  239. _JumpError(hr, error, "LocalAlloc");
  240. }
  241. // enumerate all the keys for this container
  242. dwFirstKeyFlag = CRYPT_FIRST;
  243. while (TRUE)
  244. {
  245. // get the key name
  246. *pbData = '\0';
  247. cb = cbData;
  248. bRetVal = CryptGetProvParam(
  249. hProv,
  250. PP_ENUMCONTAINERS,
  251. pbData,
  252. &cb,
  253. dwFirstKeyFlag);
  254. DBGPRINT((
  255. DBG_SS_CERTLIBI,
  256. "CryptGetProvParam(pb=%x, f=%d) -> cb=%d->%d, key=%hs, bRet=%d\n",
  257. pbData,
  258. dwFirstKeyFlag,
  259. cbData,
  260. cb,
  261. pbData,
  262. bRetVal));
  263. DBGDUMPHEX((
  264. DBG_SS_CERTLIBI,
  265. 0,
  266. pbData,
  267. strlen((char const *) pbData)));
  268. dwFirstKeyFlag = 0;
  269. if (!bRetVal)
  270. {
  271. hr = myHLastError();
  272. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  273. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  274. {
  275. // no more keys to get
  276. break;
  277. }
  278. else if (NTE_BAD_KEYSET == hr ||
  279. HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr )
  280. {
  281. // skip the bad key (key container with long name?)
  282. _PrintError(hr, "bad key");
  283. continue;
  284. }
  285. _JumpError(hr, error, "CryptGetProvParam");
  286. }
  287. pKey = newKey((CHAR *) pbData);
  288. if (NULL == pKey)
  289. {
  290. hr = E_OUTOFMEMORY;
  291. _JumpError(hr, error, "LocalAlloc");
  292. }
  293. DBGDUMPHEX((
  294. DBG_SS_CERTLIBI,
  295. 0,
  296. (BYTE const *) pKey->pwszName,
  297. sizeof(WCHAR) * wcslen(pKey->pwszName)));
  298. addKeyList(&pKeyList, pKey);
  299. } // <- End of enumeration loop
  300. // clean up:
  301. // free the old buffer
  302. if (NULL != pbData)
  303. {
  304. LocalFree(pbData);
  305. pbData = NULL;
  306. }
  307. }
  308. // release the old context
  309. CryptReleaseContext(hProv, 0);
  310. hProv = NULL;
  311. // get the default key container and make sure it is in the key list
  312. if (!myCertSrvCryptAcquireContext(
  313. &hProv,
  314. NULL,
  315. pwszProvName,
  316. dwProvType,
  317. dwSilent,
  318. fMachineKeySet))
  319. {
  320. hr = myHLastError();
  321. _PrintError2(hr, "myCertSrvCryptAcquireContext", hr);
  322. goto done;
  323. }
  324. // find out its name
  325. cbData = 0;
  326. while (TRUE)
  327. {
  328. if (!CryptGetProvParam(hProv, PP_CONTAINER, pbData, &cbData, 0))
  329. {
  330. hr = myHLastError();
  331. _PrintError2(hr, "CryptGetProvParam", hr);
  332. goto done;
  333. }
  334. if (NULL != pbData)
  335. {
  336. // got it
  337. break;
  338. }
  339. pbData = (BYTE *) LocalAlloc(LMEM_FIXED, cbData);
  340. if (NULL == pbData)
  341. {
  342. hr = E_OUTOFMEMORY;
  343. _JumpError(hr, error, "LocalAlloc");
  344. }
  345. }
  346. // create a (temporary) key structure
  347. pKey = newKey((CHAR *) pbData);
  348. if (NULL == pKey)
  349. {
  350. hr = E_OUTOFMEMORY;
  351. _JumpError(hr, error, "LocalAlloc");
  352. }
  353. // walk the key list and see if this key is there
  354. fFoundDefaultKey = FALSE;
  355. for (pklTravel = pKeyList; NULL != pklTravel; pklTravel = pklTravel->next)
  356. {
  357. if (0 == wcscmp(pKey->pwszName, pklTravel->pwszName))
  358. {
  359. fFoundDefaultKey = TRUE;
  360. break;
  361. }
  362. }
  363. if (fFoundDefaultKey)
  364. {
  365. // we found it - delete the temp structure.
  366. freeKey(pKey);
  367. }
  368. else
  369. {
  370. // we didn't find it, so add the key to the list.
  371. addKeyList(&pKeyList, pKey);
  372. }
  373. done:
  374. // pass list back to caller
  375. *ppKeyList = pKeyList;
  376. pKeyList = NULL;
  377. hr = S_OK;
  378. error:
  379. if (NULL != hProv)
  380. {
  381. CryptReleaseContext(hProv, 0);
  382. }
  383. if (NULL != pKeyList)
  384. {
  385. csiFreeKeyList(pKeyList);
  386. }
  387. if (NULL != pbData)
  388. {
  389. LocalFree(pbData);
  390. }
  391. return(hr);
  392. }