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.

642 lines
15 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((DWORD) 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((DWORD) 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 *pidAlg;
  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. DWORD const *pdwProtocols;
  181. if (fSupportSigningFlag)
  182. {
  183. pdwProtocols = &EnumAlgsEx.dwProtocols;
  184. pidAlg = &EnumAlgsEx.aiAlgid;
  185. cbData = sizeof(EnumAlgsEx);
  186. pbData = (BYTE *) &EnumAlgsEx;
  187. }
  188. else
  189. {
  190. pdwProtocols = NULL;
  191. pidAlg = &EnumAlgs.aiAlgid;
  192. cbData = sizeof(EnumAlgs);
  193. pbData = (BYTE *) &EnumAlgs;
  194. }
  195. ZeroMemory(pbData, cbData);
  196. if (!CryptGetProvParam(
  197. hProv,
  198. fSupportSigningFlag?
  199. PP_ENUMALGS_EX : PP_ENUMALGS,
  200. pbData,
  201. &cbData,
  202. dwFlags))
  203. {
  204. hr = myHLastError();
  205. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  206. {
  207. // out of for loop
  208. break;
  209. }
  210. _JumpError(hr, error, "CryptGetProvParam");
  211. }
  212. if (ALG_CLASS_HASH == GET_ALG_CLASS(*pidAlg))
  213. {
  214. if (fSupportSigningFlag)
  215. {
  216. if (0 == (CRYPT_FLAG_SIGNING & *pdwProtocols))
  217. {
  218. // this means this hash doesn't support signing
  219. continue; // skip
  220. }
  221. pszName = EnumAlgsEx.szLongName;
  222. pszName = EnumAlgsEx.szName;
  223. }
  224. else
  225. {
  226. pszName = EnumAlgs.szName;
  227. }
  228. pHashInfoNode = newHashInfo(*pidAlg, pszName); // 2nd parm: name
  229. if (NULL == pHashInfoNode)
  230. {
  231. hr = E_OUTOFMEMORY;
  232. _JumpError(hr, error, "newHashInfo");
  233. }
  234. if (NULL == pHashInfo)
  235. {
  236. pHashInfo = pHashInfoNode;
  237. }
  238. else
  239. {
  240. // add to temp list
  241. addHashInfoToEnd(pHashInfo, pHashInfoNode);
  242. }
  243. }
  244. }
  245. // pass it back to caller
  246. *pHashInfoList = pHashInfo;
  247. pHashInfo = NULL;
  248. hr = S_OK;
  249. error:
  250. if (NULL != pHashInfo)
  251. {
  252. freeHashInfoList(pHashInfo);
  253. }
  254. if (NULL != hProv)
  255. {
  256. CryptReleaseContext(hProv, 0);
  257. }
  258. return hr;
  259. }
  260. // CSP Enumeration code begins
  261. // move point to link list top
  262. CSP_INFO*
  263. topCSPInfoList(CSP_INFO *pCSPInfoList)
  264. {
  265. while (pCSPInfoList->last)
  266. {
  267. pCSPInfoList = pCSPInfoList->last;
  268. }
  269. return pCSPInfoList;
  270. }
  271. // move point to link list end
  272. CSP_INFO*
  273. endCSPInfoList(CSP_INFO *pCSPInfoList)
  274. {
  275. while (pCSPInfoList->next)
  276. {
  277. pCSPInfoList = pCSPInfoList->next;
  278. }
  279. return pCSPInfoList;
  280. }
  281. // find first matched csp info from the list
  282. CSP_INFO*
  283. findCSPInfoFromList(
  284. CSP_INFO *pCSPInfoList,
  285. WCHAR const *pwszProvName,
  286. const DWORD dwProvType)
  287. {
  288. while (NULL != pCSPInfoList)
  289. {
  290. if (0 == mylstrcmpiL(pCSPInfoList->pwszProvName, pwszProvName) &&
  291. pCSPInfoList->dwProvType == dwProvType)
  292. {
  293. // found it
  294. break;
  295. }
  296. pCSPInfoList = pCSPInfoList->next;
  297. }
  298. return pCSPInfoList;
  299. }
  300. // add one more CSP_INFO
  301. void
  302. addCSPInfo(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
  303. {
  304. // add
  305. pCSPInfoList->next = pCSPInfo;
  306. pCSPInfo->last = pCSPInfoList;
  307. }
  308. // add one more CSP_INFO to end
  309. void
  310. addCSPInfoToEnd(CSP_INFO *pCSPInfoList, CSP_INFO *pCSPInfo)
  311. {
  312. // go to end
  313. pCSPInfoList = endCSPInfoList(pCSPInfoList);
  314. // add
  315. pCSPInfoList->next = pCSPInfo;
  316. pCSPInfo->last = pCSPInfoList;
  317. }
  318. void
  319. freeCSPInfo(CSP_INFO *pCSPInfo)
  320. {
  321. if (pCSPInfo)
  322. {
  323. if (pCSPInfo->pwszProvName)
  324. {
  325. LocalFree(pCSPInfo->pwszProvName);
  326. }
  327. if (pCSPInfo->pHashList)
  328. {
  329. freeHashInfoList(pCSPInfo->pHashList);
  330. }
  331. LocalFree(pCSPInfo);
  332. }
  333. }
  334. CSP_INFO *
  335. newCSPInfo(
  336. DWORD dwProvType,
  337. WCHAR *pwszProvName)
  338. {
  339. CSP_INFO *pCSPInfo = NULL;
  340. CSP_HASH *pHashList = NULL;
  341. if (NULL != pwszProvName)
  342. {
  343. // get all hash algorithms under this csp
  344. if (S_OK != GetHashList(dwProvType, pwszProvName, &pHashList))
  345. {
  346. // certsrv needs csp with hash support
  347. goto done;
  348. }
  349. else
  350. {
  351. pCSPInfo = (CSP_INFO*)LocalAlloc(LMEM_FIXED, sizeof(CSP_INFO));
  352. if (NULL == pCSPInfo)
  353. {
  354. freeHashInfoList(pHashList);
  355. SetLastError((DWORD) E_OUTOFMEMORY);
  356. }
  357. else
  358. {
  359. pCSPInfo->pwszProvName = (WCHAR*)LocalAlloc(LMEM_FIXED,
  360. (wcslen(pwszProvName) + 1) * sizeof(WCHAR));
  361. if (NULL == pCSPInfo->pwszProvName)
  362. {
  363. freeHashInfoList(pHashList);
  364. LocalFree(pCSPInfo);
  365. pCSPInfo = NULL;
  366. SetLastError((DWORD) E_OUTOFMEMORY);
  367. goto done;
  368. }
  369. else
  370. {
  371. // create a new one
  372. pCSPInfo->dwProvType = dwProvType;
  373. pCSPInfo->fMachineKeyset = TRUE; // assume???
  374. wcscpy(pCSPInfo->pwszProvName, pwszProvName);
  375. pCSPInfo->pHashList = pHashList;
  376. pCSPInfo->last = NULL;
  377. pCSPInfo->next = NULL;
  378. }
  379. }
  380. }
  381. }
  382. done:
  383. return pCSPInfo;
  384. }
  385. void
  386. FreeCSPInfoList(CSP_INFO *pCSPInfoList)
  387. {
  388. CSP_INFO *pNext;
  389. if (pCSPInfoList)
  390. {
  391. // go top
  392. pCSPInfoList = topCSPInfoList(pCSPInfoList);
  393. do
  394. {
  395. pNext = pCSPInfoList->next;
  396. freeCSPInfo(pCSPInfoList);
  397. pCSPInfoList = pNext;
  398. } while (pCSPInfoList);
  399. }
  400. }
  401. HRESULT
  402. GetCSPInfoList(CSP_INFO **pCSPInfoList)
  403. {
  404. HRESULT hr;
  405. long i;
  406. DWORD dwProvType;
  407. WCHAR *pwszProvName = NULL;
  408. CSP_INFO *pCSPInfo = NULL;
  409. CSP_INFO *pCSPInfoNode;
  410. for (i = 0; ; i++)
  411. {
  412. // get provider name
  413. hr = myEnumProviders(
  414. i,
  415. NULL,
  416. 0,
  417. &dwProvType,
  418. &pwszProvName);
  419. if (S_OK != hr)
  420. {
  421. hr = myHLastError();
  422. CSASSERT(
  423. HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  424. NTE_FAIL == hr);
  425. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr ||
  426. NTE_FAIL == hr)
  427. {
  428. // no more providers under type, terminate loop
  429. break;
  430. }
  431. // invalid CSP entry, skip it
  432. continue;
  433. }
  434. if (PROV_RSA_FULL == dwProvType ||
  435. PROV_RSA_SIG == dwProvType ||
  436. PROV_DSS == dwProvType ||
  437. PROV_MS_EXCHANGE == dwProvType ||
  438. PROV_SSL == dwProvType)
  439. {
  440. if (NULL == pCSPInfo)
  441. {
  442. // first csp info
  443. pCSPInfo = newCSPInfo(dwProvType, pwszProvName);
  444. }
  445. else
  446. {
  447. // create a node
  448. pCSPInfoNode = newCSPInfo(dwProvType, pwszProvName);
  449. if (NULL != pCSPInfoNode)
  450. {
  451. // add to list
  452. addCSPInfoToEnd(pCSPInfo, pCSPInfoNode);
  453. }
  454. }
  455. }
  456. LocalFree(pwszProvName);
  457. pwszProvName = NULL;
  458. }
  459. // pass back to caller
  460. *pCSPInfoList = pCSPInfo;
  461. hr = S_OK;
  462. //error:
  463. if (NULL != pwszProvName)
  464. {
  465. LocalFree(pwszProvName);
  466. }
  467. return(hr);
  468. }
  469. HRESULT
  470. SetCertSrvCSP(
  471. IN BOOL fEncryptionCSP,
  472. IN WCHAR const *pwszCAName,
  473. IN DWORD dwProvType,
  474. IN WCHAR const *pwszProvName,
  475. IN ALG_ID idAlg,
  476. IN BOOL fMachineKeyset,
  477. IN DWORD dwKeySize)
  478. {
  479. HRESULT hr;
  480. HKEY hCertSrvKey = NULL;
  481. HKEY hCertSrvCAKey = NULL;
  482. HKEY hCertSrvCSPKey = NULL;
  483. DWORD dwDisposition;
  484. hr = RegCreateKeyEx(
  485. HKEY_LOCAL_MACHINE,
  486. wszREGKEYCONFIGPATH,
  487. 0,
  488. NULL,
  489. REG_OPTION_NON_VOLATILE,
  490. KEY_ALL_ACCESS,
  491. NULL,
  492. &hCertSrvKey,
  493. &dwDisposition);
  494. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", wszREGKEYCONFIGPATH);
  495. hr = RegCreateKeyEx(
  496. hCertSrvKey,
  497. pwszCAName,
  498. 0,
  499. NULL,
  500. REG_OPTION_NON_VOLATILE,
  501. KEY_ALL_ACCESS,
  502. NULL,
  503. &hCertSrvCAKey,
  504. &dwDisposition);
  505. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", pwszCAName);
  506. hr = RegCreateKeyEx(
  507. hCertSrvCAKey,
  508. fEncryptionCSP? g_wszRegKeyEncryptionCSP : g_wszRegKeyCSP,
  509. 0,
  510. NULL,
  511. REG_OPTION_NON_VOLATILE,
  512. KEY_ALL_ACCESS,
  513. NULL,
  514. &hCertSrvCSPKey,
  515. &dwDisposition);
  516. _JumpIfErrorStr(hr, error, "RegCreateKeyEx", g_wszRegKeyCSP);
  517. hr = RegSetValueEx(
  518. hCertSrvCSPKey,
  519. g_wszRegProviderType,
  520. 0,
  521. REG_DWORD,
  522. (BYTE const *) &dwProvType,
  523. sizeof(dwProvType));
  524. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProviderType);
  525. hr = RegSetValueEx(
  526. hCertSrvCSPKey,
  527. g_wszRegProvider,
  528. 0,
  529. REG_SZ,
  530. (BYTE const *) pwszProvName,
  531. wcslen(pwszProvName) * sizeof(WCHAR));
  532. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegProvider);
  533. hr = RegSetValueEx(
  534. hCertSrvCSPKey,
  535. fEncryptionCSP?
  536. g_wszRegEncryptionAlgorithm :
  537. g_wszRegHashAlgorithm,
  538. 0,
  539. REG_DWORD, // questionable???
  540. (BYTE const *) &idAlg,
  541. sizeof(idAlg));
  542. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegHashAlgorithm);
  543. hr = RegSetValueEx(
  544. hCertSrvCSPKey,
  545. g_wszRegMachineKeyset,
  546. 0,
  547. REG_DWORD,
  548. (BYTE const *) &fMachineKeyset,
  549. sizeof(fMachineKeyset));
  550. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegMachineKeyset);
  551. if (0 != dwKeySize)
  552. {
  553. hr = RegSetValueEx(
  554. hCertSrvCSPKey,
  555. g_wszRegKeySize,
  556. 0,
  557. REG_DWORD,
  558. (BYTE const *) &dwKeySize,
  559. sizeof(dwKeySize));
  560. _JumpIfErrorStr(hr, error, "RegSetValueEx", g_wszRegKeySize);
  561. }
  562. error:
  563. if (NULL != hCertSrvCSPKey)
  564. {
  565. RegCloseKey(hCertSrvCSPKey);
  566. }
  567. if (NULL != hCertSrvCAKey)
  568. {
  569. RegCloseKey(hCertSrvCAKey);
  570. }
  571. if (NULL != hCertSrvKey)
  572. {
  573. RegCloseKey(hCertSrvKey);
  574. }
  575. return(myHError(hr));
  576. }