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.

639 lines
14 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: cspenum.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include <tchar.h>
  13. #include <assert.h>
  14. #include "initcert.h"
  15. #include "cscsp.h"
  16. #include "cspenum.h"
  17. #include "certmsg.h"
  18. #define __dwFILE__ __dwFILE_OCMSETUP_CSPENUM_CPP__
  19. WCHAR const g_wszRegKeyCSP[] = wszREGKEYCSP;
  20. WCHAR const g_wszRegKeyEncryptionCSP[] = wszREGKEYENCRYPTIONCSP;
  21. WCHAR const g_wszRegProviderType[] = wszREGPROVIDERTYPE;
  22. WCHAR const g_wszRegProvider[] = wszREGPROVIDER;
  23. WCHAR const g_wszRegHashAlgorithm[] = wszHASHALGORITHM;
  24. TCHAR const g_wszRegEncryptionAlgorithm[] = wszENCRYPTIONALGORITHM;
  25. WCHAR const g_wszRegMachineKeyset[] = wszMACHINEKEYSET;
  26. WCHAR const g_wszRegKeySize[] = wszREGKEYSIZE;
  27. // Hash Enumeration code begins
  28. // move point to link list top
  29. CSP_HASH*
  30. topHashInfoList(CSP_HASH *pHashInfoList)
  31. {
  32. while (pHashInfoList->last)
  33. {
  34. pHashInfoList = pHashInfoList->last;
  35. }
  36. return pHashInfoList;
  37. }
  38. // move point to link list end
  39. CSP_HASH*
  40. endHashInfoList(CSP_HASH *pHashInfoList)
  41. {
  42. while (pHashInfoList->next)
  43. {
  44. pHashInfoList = pHashInfoList->next;
  45. }
  46. return pHashInfoList;
  47. }
  48. // add one more CSP_INFO
  49. void
  50. addHashInfo(CSP_HASH *pHashInfoList, CSP_HASH *pHashInfo)
  51. {
  52. // add
  53. pHashInfoList->next = pHashInfo;
  54. pHashInfo->last = pHashInfoList;
  55. }
  56. // add one more CSP_INFO to end
  57. void
  58. addHashInfoToEnd(CSP_HASH *pHashInfoList, CSP_HASH *pHashInfo)
  59. {
  60. // go to end
  61. pHashInfoList = endHashInfoList(pHashInfoList);
  62. // add
  63. pHashInfoList->next = pHashInfo;
  64. pHashInfo->last = pHashInfoList;
  65. }
  66. CSP_HASH *
  67. newHashInfo(
  68. ALG_ID idAlg,
  69. CHAR *pszName)
  70. {
  71. CSP_HASH *pHashInfo = NULL;
  72. if (NULL != pszName)
  73. {
  74. pHashInfo = (CSP_HASH*)LocalAlloc(LMEM_FIXED, sizeof(CSP_HASH));
  75. if (NULL == pHashInfo)
  76. {
  77. SetLastError(E_OUTOFMEMORY);
  78. }
  79. else
  80. {
  81. pHashInfo->pwszName = (WCHAR*)LocalAlloc(LMEM_FIXED,
  82. (strlen(pszName)+1)*sizeof(WCHAR));
  83. if (NULL == pHashInfo->pwszName)
  84. {
  85. LocalFree(pHashInfo);
  86. SetLastError(E_OUTOFMEMORY);
  87. return NULL;
  88. }
  89. else
  90. {
  91. // create a new one
  92. pHashInfo->idAlg = idAlg;
  93. mbstowcs(pHashInfo->pwszName, pszName, strlen(pszName)+1);
  94. pHashInfo->last = NULL;
  95. pHashInfo->next = NULL;
  96. }
  97. }
  98. }
  99. return pHashInfo;
  100. }
  101. void
  102. freeHashInfo(CSP_HASH *pHashInfo)
  103. {
  104. if (pHashInfo)
  105. {
  106. if (pHashInfo->pwszName)
  107. {
  108. LocalFree(pHashInfo->pwszName);
  109. }
  110. LocalFree(pHashInfo);
  111. }
  112. }
  113. void
  114. freeHashInfoList(
  115. CSP_HASH *pHashInfoList)
  116. {
  117. CSP_HASH *pNext;
  118. if (pHashInfoList)
  119. {
  120. // go top
  121. pHashInfoList = topHashInfoList(pHashInfoList);
  122. do
  123. {
  124. pNext = pHashInfoList->next;
  125. freeHashInfo(pHashInfoList);
  126. pHashInfoList = pNext;
  127. } while (pHashInfoList);
  128. }
  129. }
  130. HRESULT
  131. GetHashList(
  132. DWORD dwProvType,
  133. WCHAR *pwszProvName,
  134. CSP_HASH **pHashInfoList)
  135. {
  136. HRESULT hr;
  137. HCRYPTPROV hProv = NULL;
  138. CHAR *pszName = NULL;
  139. DWORD i;
  140. ALG_ID idAlg;
  141. DWORD cbData;
  142. BYTE *pbData;
  143. DWORD dwFlags;
  144. BOOL fSupportSigningFlag = FALSE; // none-ms csp likely
  145. PROV_ENUMALGS_EX EnumAlgsEx;
  146. PROV_ENUMALGS EnumAlgs;
  147. CSP_HASH *pHashInfo = NULL;
  148. CSP_HASH *pHashInfoNode;
  149. if (NULL == pwszProvName)
  150. {
  151. // the reason why I check this because
  152. // NULL is a valid input for CryptAcquireContext()
  153. hr = E_INVALIDARG;
  154. _JumpError(hr, error, "no provider name");
  155. }
  156. if (!myCertSrvCryptAcquireContext(
  157. &hProv,
  158. NULL,
  159. pwszProvName,
  160. dwProvType,
  161. CRYPT_VERIFYCONTEXT,
  162. FALSE))
  163. {
  164. hr = myHLastError();
  165. if (NULL != hProv)
  166. {
  167. hProv = NULL;
  168. _PrintError(hr, "CSP returns a non-null handle");
  169. }
  170. _JumpErrorStr(hr, error, "myCertSrvCryptAcquireContext", pwszProvName);
  171. }
  172. // check if csp support signing flag
  173. if (CryptGetProvParam(hProv, PP_ENUMEX_SIGNING_PROT, NULL, &cbData, 0))
  174. {
  175. fSupportSigningFlag = TRUE;
  176. }
  177. dwFlags = CRYPT_FIRST;
  178. for (i = 0; ; dwFlags = 0, i++)
  179. {
  180. if (fSupportSigningFlag)
  181. {
  182. cbData = sizeof(EnumAlgsEx);
  183. pbData = (BYTE *) &EnumAlgsEx;
  184. }
  185. else
  186. {
  187. cbData = sizeof(EnumAlgs);
  188. pbData = (BYTE *) &EnumAlgs;
  189. }
  190. ZeroMemory(pbData, cbData);
  191. if (!CryptGetProvParam(
  192. hProv,
  193. fSupportSigningFlag?
  194. PP_ENUMALGS_EX : PP_ENUMALGS,
  195. pbData,
  196. &cbData,
  197. dwFlags))
  198. {
  199. hr = myHLastError();
  200. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  201. {
  202. // out of for loop
  203. break;
  204. }
  205. _JumpError(hr, error, "CryptGetProvParam");
  206. }
  207. idAlg = fSupportSigningFlag? EnumAlgsEx.aiAlgid : EnumAlgs.aiAlgid;
  208. if (ALG_CLASS_HASH == GET_ALG_CLASS(idAlg))
  209. {
  210. if (fSupportSigningFlag)
  211. {
  212. if (0 == (EnumAlgsEx.dwProtocols & CRYPT_FLAG_SIGNING))
  213. {
  214. // this means this hash doesn't support signing
  215. continue; // skip
  216. }
  217. pszName = EnumAlgsEx.szLongName;
  218. pszName = EnumAlgsEx.szName;
  219. }
  220. else
  221. {
  222. pszName = EnumAlgs.szName;
  223. }
  224. pHashInfoNode = newHashInfo(idAlg, pszName); // 2nd parm: name
  225. if (NULL == pHashInfoNode)
  226. {
  227. hr = E_OUTOFMEMORY;
  228. _JumpError(hr, error, "newHashInfo");
  229. }
  230. if (NULL == pHashInfo)
  231. {
  232. pHashInfo = pHashInfoNode;
  233. }
  234. else
  235. {
  236. // add to temp list
  237. addHashInfoToEnd(pHashInfo, pHashInfoNode);
  238. }
  239. }
  240. }
  241. // pass it back to caller
  242. *pHashInfoList = pHashInfo;
  243. pHashInfo = NULL;
  244. hr = S_OK;
  245. error:
  246. if (NULL != pHashInfo)
  247. {
  248. freeHashInfoList(pHashInfo);
  249. }
  250. if (NULL != hProv)
  251. {
  252. CryptReleaseContext(hProv, 0);
  253. }
  254. return hr;
  255. }
  256. // CSP Enumeration code begins
  257. // move point to link list top
  258. CSP_INFO*
  259. topCSPInfoList(CSP_INFO *pCSPInfoList)
  260. {
  261. while (pCSPInfoList->last)
  262. {
  263. pCSPInfoList = pCSPInfoList->last;
  264. }
  265. return pCSPInfoList;
  266. }
  267. // move point to link list end
  268. CSP_INFO*
  269. endCSPInfoList(CSP_INFO *pCSPInfoList)
  270. {
  271. while (pCSPInfoList->next)
  272. {
  273. pCSPInfoList = pCSPInfoList->next;
  274. }
  275. return pCSPInfoList;
  276. }
  277. // find first matched csp info from the list
  278. CSP_INFO*
  279. findCSPInfoFromList(
  280. CSP_INFO *pCSPInfoList,
  281. WCHAR const *pwszProvName,
  282. const DWORD dwProvType)
  283. {
  284. while (NULL != pCSPInfoList)
  285. {
  286. if (0 == wcscmp(pCSPInfoList->pwszProvName, pwszProvName) &&
  287. pCSPInfoList->dwProvType == dwProvType)
  288. {
  289. // found it
  290. break;
  291. }
  292. pCSPInfoList = pCSPInfoList->next;
  293. }
  294. return pCSPInfoList;
  295. }
  296. // add one more CSP_INFO
  297. void
  298. addCSPInfo(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
  299. {
  300. // add
  301. pCSPInfoList->next = pCSPInfo;
  302. pCSPInfo->last = pCSPInfoList;
  303. }
  304. // add one more CSP_INFO to end
  305. void
  306. addCSPInfoToEnd(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
  307. {
  308. // go to end
  309. pCSPInfoList = endCSPInfoList(pCSPInfoList);
  310. // add
  311. pCSPInfoList->next = pCSPInfo;
  312. pCSPInfo->last = pCSPInfoList;
  313. }
  314. void
  315. freeCSPInfo(CSP_INFO *pCSPInfo)
  316. {
  317. if (pCSPInfo)
  318. {
  319. if (pCSPInfo->pwszProvName)
  320. {
  321. LocalFree(pCSPInfo->pwszProvName);
  322. }
  323. if (pCSPInfo->pHashList)
  324. {
  325. freeHashInfoList(pCSPInfo->pHashList);
  326. }
  327. LocalFree(pCSPInfo);
  328. }
  329. }
  330. CSP_INFO *
  331. newCSPInfo(
  332. DWORD dwProvType,
  333. WCHAR *pwszProvName)
  334. {
  335. CSP_INFO *pCSPInfo = NULL;
  336. CSP_HASH *pHashList = NULL;
  337. if (NULL != pwszProvName)
  338. {
  339. // get all hash algorithms under this csp
  340. if (S_OK != GetHashList(dwProvType, pwszProvName, &pHashList))
  341. {
  342. // certsrv needs csp with hash support
  343. goto done;
  344. }
  345. else
  346. {
  347. pCSPInfo = (CSP_INFO*)LocalAlloc(LMEM_FIXED, sizeof(CSP_INFO));
  348. if (NULL == pCSPInfo)
  349. {
  350. freeHashInfoList(pHashList);
  351. SetLastError(E_OUTOFMEMORY);
  352. }
  353. else
  354. {
  355. pCSPInfo->pwszProvName = (WCHAR*)LocalAlloc(LMEM_FIXED,
  356. (wcslen(pwszProvName) + 1) * sizeof(WCHAR));
  357. if (NULL == pCSPInfo->pwszProvName)
  358. {
  359. freeHashInfoList(pHashList);
  360. LocalFree(pCSPInfo);
  361. pCSPInfo = NULL;
  362. SetLastError(E_OUTOFMEMORY);
  363. goto done;
  364. }
  365. else
  366. {
  367. // create a new one
  368. pCSPInfo->dwProvType = dwProvType;
  369. pCSPInfo->fMachineKeyset = TRUE; // assume???
  370. wcscpy(pCSPInfo->pwszProvName, pwszProvName);
  371. pCSPInfo->pHashList = pHashList;
  372. pCSPInfo->last = NULL;
  373. pCSPInfo->next = NULL;
  374. }
  375. }
  376. }
  377. }
  378. done:
  379. return pCSPInfo;
  380. }
  381. void
  382. FreeCSPInfoList(CSP_INFO *pCSPInfoList)
  383. {
  384. CSP_INFO *pNext;
  385. if (pCSPInfoList)
  386. {
  387. // go top
  388. pCSPInfoList = topCSPInfoList(pCSPInfoList);
  389. do
  390. {
  391. pNext = pCSPInfoList->next;
  392. freeCSPInfo(pCSPInfoList);
  393. pCSPInfoList = pNext;
  394. } while (pCSPInfoList);
  395. }
  396. }
  397. HRESULT
  398. GetCSPInfoList(CSP_INFO **pCSPInfoList)
  399. {
  400. HRESULT hr;
  401. long i;
  402. DWORD dwProvType;
  403. WCHAR *pwszProvName = NULL;
  404. CSP_INFO *pCSPInfo = NULL;
  405. CSP_INFO *pCSPInfoNode;
  406. for (i = 0; ; i++)
  407. {
  408. // get provider name
  409. hr = myEnumProviders(
  410. i,
  411. NULL,
  412. 0,
  413. &dwProvType,
  414. &pwszProvName);
  415. if (S_OK != hr)
  416. {
  417. hr = myHLastError();
  418. CSASSERT(
  419. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  420. NTE_FAIL == hr);
  421. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  422. NTE_FAIL == hr)
  423. {
  424. // no more providers under type, terminate loop
  425. break;
  426. }
  427. // invalid CSP entry, skip it
  428. continue;
  429. }
  430. if (PROV_RSA_FULL == dwProvType ||
  431. PROV_RSA_SIG == dwProvType ||
  432. PROV_DSS == dwProvType ||
  433. PROV_MS_EXCHANGE == dwProvType ||
  434. PROV_SSL == dwProvType)
  435. {
  436. if (NULL == pCSPInfo)
  437. {
  438. // first csp info
  439. pCSPInfo = newCSPInfo(dwProvType, pwszProvName);
  440. }
  441. else
  442. {
  443. // create a node
  444. pCSPInfoNode = newCSPInfo(dwProvType, pwszProvName);
  445. if (NULL != pCSPInfoNode)
  446. {
  447. // add to list
  448. addCSPInfoToEnd(pCSPInfo, pCSPInfoNode);
  449. }
  450. }
  451. }
  452. LocalFree(pwszProvName);
  453. pwszProvName = NULL;
  454. }
  455. // pass back to caller
  456. *pCSPInfoList = pCSPInfo;
  457. hr = S_OK;
  458. //error:
  459. if (NULL != pwszProvName)
  460. {
  461. LocalFree(pwszProvName);
  462. }
  463. return(hr);
  464. }
  465. HRESULT
  466. SetCertSrvCSP(
  467. IN BOOL fEncryptionCSP,
  468. IN WCHAR const *pwszCAName,
  469. IN DWORD dwProvType,
  470. IN WCHAR const *pwszProvName,
  471. IN ALG_ID idAlg,
  472. IN BOOL fMachineKeyset,
  473. IN DWORD dwKeySize)
  474. {
  475. HRESULT hr;
  476. HKEY hCertSrvKey = NULL;
  477. HKEY hCertSrvCAKey = NULL;
  478. HKEY hCertSrvCSPKey = NULL;
  479. DWORD dwDisposition;
  480. hr = RegCreateKeyEx(
  481. HKEY_LOCAL_MACHINE,
  482. wszREGKEYCONFIGPATH,
  483. 0,
  484. NULL,
  485. REG_OPTION_NON_VOLATILE,
  486. KEY_ALL_ACCESS,
  487. NULL,
  488. &hCertSrvKey,
  489. &dwDisposition);
  490. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", wszREGKEYCONFIGPATH);
  491. hr = RegCreateKeyEx(
  492. hCertSrvKey,
  493. pwszCAName,
  494. 0,
  495. NULL,
  496. REG_OPTION_NON_VOLATILE,
  497. KEY_ALL_ACCESS,
  498. NULL,
  499. &hCertSrvCAKey,
  500. &dwDisposition);
  501. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", pwszCAName);
  502. hr = RegCreateKeyEx(
  503. hCertSrvCAKey,
  504. fEncryptionCSP? g_wszRegKeyEncryptionCSP : g_wszRegKeyCSP,
  505. 0,
  506. NULL,
  507. REG_OPTION_NON_VOLATILE,
  508. KEY_ALL_ACCESS,
  509. NULL,
  510. &hCertSrvCSPKey,
  511. &dwDisposition);
  512. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", g_wszRegKeyCSP);
  513. hr = RegSetValueEx(
  514. hCertSrvCSPKey,
  515. g_wszRegProviderType,
  516. 0,
  517. REG_DWORD,
  518. (BYTE const *) &dwProvType,
  519. sizeof(dwProvType));
  520. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProviderType);
  521. hr = RegSetValueEx(
  522. hCertSrvCSPKey,
  523. g_wszRegProvider,
  524. 0,
  525. REG_SZ,
  526. (BYTE const *) pwszProvName,
  527. wcslen(pwszProvName) * sizeof(WCHAR));
  528. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProvider);
  529. hr = RegSetValueEx(
  530. hCertSrvCSPKey,
  531. fEncryptionCSP?
  532. g_wszRegEncryptionAlgorithm :
  533. g_wszRegHashAlgorithm,
  534. 0,
  535. REG_DWORD, // questionable???
  536. (BYTE const *) &idAlg,
  537. sizeof(idAlg));
  538. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegHashAlgorithm);
  539. hr = RegSetValueEx(
  540. hCertSrvCSPKey,
  541. g_wszRegMachineKeyset,
  542. 0,
  543. REG_DWORD,
  544. (BYTE const *) &fMachineKeyset,
  545. sizeof(fMachineKeyset));
  546. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegMachineKeyset);
  547. if (0 != dwKeySize)
  548. {
  549. hr = RegSetValueEx(
  550. hCertSrvCSPKey,
  551. g_wszRegKeySize,
  552. 0,
  553. REG_DWORD,
  554. (BYTE const *) &dwKeySize,
  555. sizeof(dwKeySize));
  556. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegKeySize);
  557. }
  558. error:
  559. if (NULL != hCertSrvCSPKey)
  560. {
  561. RegCloseKey(hCertSrvCSPKey);
  562. }
  563. if (NULL != hCertSrvCAKey)
  564. {
  565. RegCloseKey(hCertSrvCAKey);
  566. }
  567. if (NULL != hCertSrvKey)
  568. {
  569. RegCloseKey(hCertSrvKey);
  570. }
  571. return(myHError(hr));
  572. }