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.

1032 lines
33 KiB

  1. //depot/Lab03_N/DS/security/cryptoapi/cryptsvc/keysvr.cpp#9 - edit change 6380 (text)
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <windows.h>
  6. #include <svcs.h> // SVCS_
  7. #include <ntsecapi.h>
  8. #include <wincrypt.h>
  9. #include <wintrust.h>
  10. #include <wintrustp.h>
  11. #include <userenv.h>
  12. #include <lmcons.h>
  13. #include <certca.h>
  14. #include "keysvc.h"
  15. #include "keysvr.h"
  16. #include "pfx.h"
  17. #include "cryptui.h"
  18. #include "lenroll.h"
  19. #include "cryptmsg.h"
  20. #include "unicode.h"
  21. #include "unicode5.h"
  22. #include <crypt.h>
  23. #define KEYSVC_DEFAULT_ENDPOINT TEXT("\\pipe\\keysvc")
  24. #define KEYSVC_DEFAULT_PROT_SEQ TEXT("ncacn_np")
  25. #define MAXPROTSEQ 20
  26. #define ARRAYSIZE(rg) (sizeof(rg) / sizeof((rg)[0]))
  27. void *MyAlloc(size_t len)
  28. {
  29. return LocalAlloc(LMEM_ZEROINIT, len);
  30. }
  31. void MyFree(void *p)
  32. {
  33. LocalFree(p);
  34. }
  35. void MyRpcRevertToSelfEx(RPC_BINDING_HANDLE hRPCBinding)
  36. {
  37. RPC_STATUS rpcStatus;
  38. rpcStatus = RpcRevertToSelfEx((RPC_BINDING_HANDLE)hRPCBinding);
  39. if (RPC_S_OK != rpcStatus) {
  40. MyLogErrorMessage(rpcStatus, MSG_KEYSVC_REVERT_TO_SELF_FAILED);
  41. }
  42. }
  43. void MyRevertToSelf()
  44. {
  45. if (!RevertToSelf()) {
  46. MyLogErrorMessage(GetLastError(), MSG_KEYSVC_REVERT_TO_SELF_FAILED);
  47. }
  48. }
  49. DWORD
  50. StartKeyService(
  51. VOID
  52. )
  53. {
  54. return ERROR_SUCCESS; }
  55. DWORD
  56. StopKeyService(
  57. VOID
  58. )
  59. {
  60. return ERROR_SUCCESS;
  61. }
  62. DWORD AllocAndAssignString(
  63. IN PKEYSVC_UNICODE_STRING pUnicodeString,
  64. OUT LPWSTR *ppwsz
  65. )
  66. {
  67. DWORD dwErr = 0;
  68. if ((NULL != pUnicodeString->Buffer) && (0 != pUnicodeString->Length))
  69. {
  70. if ((pUnicodeString->Length > pUnicodeString->MaximumLength) ||
  71. (pUnicodeString->Length & 1) || (pUnicodeString->MaximumLength & 1))
  72. {
  73. dwErr = ERROR_INVALID_PARAMETER;
  74. goto Ret;
  75. }
  76. if (NULL == (*ppwsz = (LPWSTR)MyAlloc(pUnicodeString->MaximumLength +
  77. sizeof(WCHAR))))
  78. {
  79. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  80. goto Ret;
  81. }
  82. memcpy(*ppwsz, pUnicodeString->Buffer, pUnicodeString->Length);
  83. }
  84. Ret:
  85. return dwErr;
  86. }
  87. // key service functions
  88. ULONG s_KeyrOpenKeyService(
  89. /* [in] */ handle_t /*hRPCBinding*/,
  90. /* [in] */ KEYSVC_TYPE /*OwnerType*/,
  91. /* [in] */ PKEYSVC_UNICODE_STRING /*pOwnerName*/,
  92. /* [in] */ ULONG /*ulDesiredAccess*/,
  93. /* [in] */ PKEYSVC_BLOB /*pAuthentication*/,
  94. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/,
  95. /* [out] */ KEYSVC_HANDLE * /*phKeySvc*/)
  96. {
  97. return ERROR_CALL_NOT_IMPLEMENTED;
  98. }
  99. ULONG s_KeyrEnumerateProviders(
  100. /* [in] */ handle_t hRPCBinding,
  101. /* [in] */ KEYSVC_HANDLE /*hKeySvc*/,
  102. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/,
  103. /* [in, out] */ ULONG *pcProviderCount,
  104. /* [in, out][size_is(,*pcProviderCount)] */
  105. PKEYSVC_PROVIDER_INFO *ppProviders)
  106. {
  107. return ERROR_CALL_NOT_IMPLEMENTED;
  108. }
  109. ULONG s_KeyrCloseKeyService(
  110. /* [in] */ handle_t /*hRPCBinding*/,
  111. /* [in] */ KEYSVC_HANDLE /*hKeySvc*/,
  112. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/)
  113. {
  114. return ERROR_CALL_NOT_IMPLEMENTED;
  115. }
  116. ULONG s_KeyrGetDefaultProvider(
  117. /* [in] */ handle_t hRPCBinding,
  118. /* [in] */ KEYSVC_HANDLE /*hKeySvc*/,
  119. /* [in] */ ULONG ulProvType,
  120. /* [in] */ ULONG /*ulFlags*/,
  121. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/,
  122. /* [out] */ ULONG *pulDefType,
  123. /* [out] */ PKEYSVC_PROVIDER_INFO *ppProvider)
  124. {
  125. return ERROR_CALL_NOT_IMPLEMENTED;
  126. }
  127. ULONG s_KeyrEnroll(
  128. /* [in] */ handle_t /*hRPCBinding*/,
  129. /* [in] */ BOOL /*fKeyService*/,
  130. /* [in] */ ULONG /*ulPurpose*/,
  131. /* [in] */ PKEYSVC_UNICODE_STRING /*pAcctName*/,
  132. /* [in] */ PKEYSVC_UNICODE_STRING /*pCALocation*/,
  133. /* [in] */ PKEYSVC_UNICODE_STRING /*pCAName*/,
  134. /* [in] */ BOOL /*fNewKey*/,
  135. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW /*pKeyNew*/,
  136. /* [in] */ PKEYSVC_BLOB __RPC_FAR /*pCert*/,
  137. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW /*pRenewKey*/,
  138. /* [in] */ PKEYSVC_UNICODE_STRING /*pHashAlg*/,
  139. /* [in] */ PKEYSVC_UNICODE_STRING /*pDesStore*/,
  140. /* [in] */ ULONG /*ulStoreFlags*/,
  141. /* [in] */ PKEYSVC_CERT_ENROLL_INFO /*pRequestInfo*/,
  142. /* [in] */ ULONG /*ulFlags*/,
  143. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR * /*ppReserved*/,
  144. /* [out] */ PKEYSVC_BLOB __RPC_FAR * /*ppPKCS7Blob*/,
  145. /* [out] */ PKEYSVC_BLOB __RPC_FAR * /*ppHashBlob*/,
  146. /* [out] */ ULONG __RPC_FAR * /*pulStatus*/)
  147. {
  148. return ERROR_CALL_NOT_IMPLEMENTED;
  149. }
  150. ULONG s_KeyrEnumerateAvailableCertTypes(
  151. /* [in] */ handle_t hRPCBinding,
  152. /* [in] */ KEYSVC_HANDLE /*hKeySvc*/,
  153. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/,
  154. /* [out][in] */ ULONG *pcCertTypeCount,
  155. /* [in, out][size_is(,*pcCertTypeCount)] */
  156. PKEYSVC_UNICODE_STRING *ppCertTypes)
  157. {
  158. DWORD dwErr = ERROR_INVALID_DATA;
  159. HCERTTYPE hType = NULL;
  160. DWORD cTypes = 0;
  161. DWORD cTrustedTypes = 0;
  162. DWORD i;
  163. LPWSTR *awszTrustedTypes = NULL;
  164. DWORD cbTrustedTypes = 0;
  165. PKEYSVC_UNICODE_STRING awszResult = NULL;
  166. LPWSTR wszCurrentName;
  167. __try
  168. {
  169. *pcCertTypeCount = 0;
  170. *ppCertTypes = NULL;
  171. dwErr = CAEnumCertTypes(CT_FIND_LOCAL_SYSTEM | CT_ENUM_MACHINE_TYPES, &hType);
  172. if(dwErr != S_OK)
  173. {
  174. goto Ret;
  175. }
  176. cTypes = CACountCertTypes(hType);
  177. awszTrustedTypes = (LPWSTR *)MyAlloc(sizeof(LPWSTR)*cTypes);
  178. if(awszTrustedTypes == NULL)
  179. {
  180. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  181. goto Ret;
  182. }
  183. while(hType)
  184. {
  185. HCERTTYPE hNextType = NULL;
  186. LPWSTR *awszTypeName = NULL;
  187. dwErr = CAGetCertTypeProperty(hType, CERTTYPE_PROP_DN, &awszTypeName);
  188. if((dwErr == S_OK) && (awszTypeName))
  189. {
  190. if(awszTypeName[0])
  191. {
  192. dwErr = CACertTypeAccessCheck(hType, NULL);
  193. if(dwErr == S_OK)
  194. {
  195. // SECURITY: can awszTypeName be very large (perhaps the hacker managed to get into the DS and muck with template names).
  196. // Should we disable allocs over a certain value?
  197. awszTrustedTypes[cTrustedTypes] = (LPWSTR)MyAlloc((wcslen(awszTypeName[0])+1)*sizeof(WCHAR));
  198. if(awszTrustedTypes[cTrustedTypes])
  199. {
  200. wcscpy(awszTrustedTypes[cTrustedTypes], awszTypeName[0]);
  201. cbTrustedTypes += (wcslen(awszTypeName[0])+1)*sizeof(WCHAR);
  202. cTrustedTypes++;
  203. }
  204. }
  205. }
  206. CAFreeCertTypeProperty(hType, awszTypeName);
  207. }
  208. dwErr = CAEnumNextCertType(hType, &hNextType);
  209. if(dwErr != S_OK)
  210. {
  211. break;
  212. }
  213. CACloseCertType(hType);
  214. hType = hNextType;
  215. }
  216. cbTrustedTypes += sizeof(KEYSVC_UNICODE_STRING)*cTrustedTypes;
  217. awszResult = (PKEYSVC_UNICODE_STRING)MyAlloc(cbTrustedTypes);
  218. if(awszResult == NULL)
  219. {
  220. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  221. goto Ret;
  222. }
  223. wszCurrentName = (LPWSTR)(&awszResult[cTrustedTypes]);
  224. for(i=0; i < cTrustedTypes; i++)
  225. {
  226. wcscpy(wszCurrentName, awszTrustedTypes[i]);
  227. // BUGBUG: we're truncating the template name here. Might be better to filter this out? Are there any security issues here?
  228. awszResult[i].Length = (WORD)(((wcslen(awszTrustedTypes[i]) + 1)*sizeof(WCHAR)) & 0xFFFF);
  229. awszResult[i].MaximumLength = awszResult[i].Length;
  230. awszResult[i].Buffer = wszCurrentName;
  231. wszCurrentName += wcslen(awszTrustedTypes[i]) + 1;
  232. }
  233. *pcCertTypeCount = cTrustedTypes;
  234. *ppCertTypes = awszResult;
  235. awszResult = NULL;
  236. dwErr = ERROR_SUCCESS;
  237. }
  238. __except ( EXCEPTION_EXECUTE_HANDLER )
  239. {
  240. dwErr = _exception_code();
  241. }
  242. Ret:
  243. __try
  244. {
  245. if(awszTrustedTypes)
  246. {
  247. for(i=0; i < cTrustedTypes; i++)
  248. {
  249. if(awszTrustedTypes[i])
  250. {
  251. MyFree(awszTrustedTypes[i]);
  252. }
  253. }
  254. MyFree(awszTrustedTypes);
  255. }
  256. if(awszResult)
  257. {
  258. MyFree(awszResult);
  259. }
  260. }
  261. __except ( EXCEPTION_EXECUTE_HANDLER )
  262. {
  263. dwErr = ERROR_INVALID_PARAMETER;
  264. }
  265. return dwErr;
  266. }
  267. ULONG s_KeyrEnumerateCAs(
  268. /* [in] */ handle_t hRPCBinding,
  269. /* [in] */ KEYSVC_HANDLE /*hKeySvc*/,
  270. /* [in, out] */ PKEYSVC_BLOB * /*ppReserved*/,
  271. /* [in] */ ULONG ulFlags,
  272. /* [out][in] */ ULONG *pcCACount,
  273. /* [in, out][size_is(,*pcCACount)] */
  274. PKEYSVC_UNICODE_STRING *ppCAs)
  275. {
  276. DWORD dwErr = ERROR_INVALID_DATA;
  277. HCAINFO hCA = NULL;
  278. DWORD cCAs = 0;
  279. DWORD cTrustedCAs = 0;
  280. DWORD i;
  281. LPWSTR *awszTrustedCAs = NULL;
  282. DWORD cbTrustedCAs = 0;
  283. PKEYSVC_UNICODE_STRING awszResult = NULL;
  284. LPWSTR wszCurrentName;
  285. __try
  286. {
  287. *pcCACount = 0;
  288. *ppCAs = NULL;
  289. dwErr = CAEnumFirstCA(NULL, ulFlags, &hCA);
  290. if(dwErr != S_OK)
  291. {
  292. goto Ret;
  293. }
  294. cCAs = CACountCAs(hCA);
  295. awszTrustedCAs = (LPWSTR *)MyAlloc(sizeof(LPWSTR)*cCAs);
  296. if(awszTrustedCAs == NULL)
  297. {
  298. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  299. goto Ret;
  300. }
  301. while(hCA)
  302. {
  303. HCAINFO hNextCA = NULL;
  304. LPWSTR *awszCAName = NULL;
  305. dwErr = CAGetCAProperty(hCA, CA_PROP_NAME, &awszCAName);
  306. if((dwErr == S_OK) && (awszCAName))
  307. {
  308. if(awszCAName[0])
  309. {
  310. dwErr = CAAccessCheck(hCA, NULL);
  311. if(dwErr == S_OK)
  312. {
  313. awszTrustedCAs[cTrustedCAs] = (LPWSTR)MyAlloc((wcslen(awszCAName[0])+1)*sizeof(WCHAR));
  314. if(awszTrustedCAs[cTrustedCAs])
  315. {
  316. wcscpy(awszTrustedCAs[cTrustedCAs], awszCAName[0]);
  317. cbTrustedCAs += (wcslen(awszCAName[0])+1)*sizeof(WCHAR);
  318. cTrustedCAs++;
  319. }
  320. }
  321. }
  322. CAFreeCAProperty(hCA, awszCAName);
  323. }
  324. dwErr = CAEnumNextCA(hCA, &hNextCA);
  325. if(dwErr != S_OK)
  326. {
  327. break;
  328. }
  329. CACloseCA(hCA);
  330. hCA = hNextCA;
  331. }
  332. cbTrustedCAs += sizeof(KEYSVC_UNICODE_STRING)*cTrustedCAs;
  333. awszResult = (PKEYSVC_UNICODE_STRING)MyAlloc(cbTrustedCAs);
  334. if(awszResult == NULL)
  335. {
  336. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  337. goto Ret;
  338. }
  339. wszCurrentName = (LPWSTR)(&awszResult[cTrustedCAs]);
  340. for(i=0; i < cTrustedCAs; i++)
  341. {
  342. wcscpy(wszCurrentName, awszTrustedCAs[i]);
  343. // BUGBUG: we're truncating the template name here. Might be better to filter this out? Are there any security issues here?
  344. awszResult[i].Length = (WORD)(((wcslen(awszTrustedCAs[i]) + 1)*sizeof(WCHAR)) & 0xFFFF);
  345. awszResult[i].MaximumLength = awszResult[i].Length;
  346. awszResult[i].Buffer = wszCurrentName;
  347. wszCurrentName += wcslen(awszTrustedCAs[i]) + 1;
  348. }
  349. *pcCACount = cTrustedCAs;
  350. *ppCAs = awszResult;
  351. awszResult = NULL;
  352. dwErr = ERROR_SUCCESS;
  353. }
  354. __except ( EXCEPTION_EXECUTE_HANDLER )
  355. {
  356. dwErr = _exception_code();
  357. }
  358. Ret:
  359. __try
  360. {
  361. if(awszTrustedCAs)
  362. {
  363. for(i=0; i < cTrustedCAs; i++)
  364. {
  365. if(awszTrustedCAs[i])
  366. {
  367. MyFree(awszTrustedCAs[i]);
  368. }
  369. }
  370. MyFree(awszTrustedCAs);
  371. }
  372. if(awszResult)
  373. {
  374. MyFree(awszResult);
  375. }
  376. }
  377. __except ( EXCEPTION_EXECUTE_HANDLER )
  378. {
  379. dwErr = ERROR_INVALID_PARAMETER;
  380. }
  381. return dwErr;
  382. }
  383. ULONG s_KeyrEnroll_V2
  384. (/* [in] */ handle_t hRPCBinding,
  385. /* [in] */ BOOL fKeyService,
  386. /* [in] */ ULONG ulPurpose,
  387. /* [in] */ ULONG ulFlags,
  388. /* [in] */ PKEYSVC_UNICODE_STRING pAcctName,
  389. /* [in] */ PKEYSVC_UNICODE_STRING pCALocation,
  390. /* [in] */ PKEYSVC_UNICODE_STRING pCAName,
  391. /* [in] */ BOOL fNewKey,
  392. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW_V2 pKeyNew,
  393. /* [in] */ PKEYSVC_BLOB __RPC_FAR pCert,
  394. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW_V2 pRenewKey,
  395. /* [in] */ PKEYSVC_UNICODE_STRING pHashAlg,
  396. /* [in] */ PKEYSVC_UNICODE_STRING pDesStore,
  397. /* [in] */ ULONG ulStoreFlags,
  398. /* [in] */ PKEYSVC_CERT_ENROLL_INFO pRequestInfo,
  399. /* [in] */ ULONG /*ulReservedFlags*/,
  400. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR * /*ppReserved*/,
  401. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR *ppRequest,
  402. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppPKCS7Blob,
  403. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppHashBlob,
  404. /* [out] */ ULONG __RPC_FAR *pulStatus)
  405. {
  406. CERT_REQUEST_PVK_NEW KeyNew;
  407. CERT_REQUEST_PVK_NEW RenewKey;
  408. DWORD cbExtensions;
  409. PBYTE pbExtensions = NULL;
  410. PCERT_REQUEST_PVK_NEW pTmpRenewKey = NULL;
  411. PCERT_REQUEST_PVK_NEW pTmpKeyNew = NULL;
  412. LPWSTR pwszProv = NULL;
  413. LPWSTR pwszCont = NULL;
  414. LPWSTR pwszRenewProv = NULL;
  415. LPWSTR pwszRenewCont = NULL;
  416. LPWSTR pwszDesStore = NULL;
  417. LPWSTR pwszAttributes = NULL;
  418. LPWSTR pwszFriendly = NULL;
  419. LPWSTR pwszDescription = NULL;
  420. LPWSTR pwszUsage = NULL;
  421. LPWSTR pwszCALocation = NULL;
  422. LPWSTR pwszCertDNName = NULL;
  423. LPWSTR pwszCAName = NULL;
  424. LPWSTR pwszHashAlg = NULL;
  425. CERT_BLOB CertBlob;
  426. CERT_BLOB *pCertBlob = NULL;
  427. CERT_BLOB PKCS7Blob;
  428. CERT_BLOB HashBlob;
  429. CERT_ENROLL_INFO EnrollInfo;
  430. DWORD dwErr = 0;
  431. HANDLE hRequest = *ppRequest;
  432. KEYSVC_BLOB ReservedBlob;
  433. BOOL fCreateRequest = 0 == (ulFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY));
  434. BOOL fFreeRequest = 0 == (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY));
  435. BOOL fSubmitRequest = 0 == (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_FREE_ONLY));
  436. __try
  437. {
  438. //////////////////////////////////////////////////////////////
  439. //
  440. // INITIALIZATION:
  441. //
  442. //////////////////////////////////////////////////////////////
  443. memset(&KeyNew, 0, sizeof(KeyNew));
  444. memset(&RenewKey, 0, sizeof(RenewKey));
  445. memset(&EnrollInfo, 0, sizeof(EnrollInfo));
  446. memset(&PKCS7Blob, 0, sizeof(PKCS7Blob));
  447. memset(&HashBlob, 0, sizeof(HashBlob));
  448. memset(&CertBlob, 0, sizeof(CertBlob));
  449. memset(&ReservedBlob, 0, sizeof(ReservedBlob));
  450. *ppPKCS7Blob = NULL;
  451. *ppHashBlob = NULL;
  452. //////////////////////////////////////////////////////////////
  453. //
  454. // INPUT VALIDATION:
  455. //
  456. //////////////////////////////////////////////////////////////
  457. BOOL fValidInput = TRUE;
  458. fValidInput &= fCreateRequest || fSubmitRequest || fFreeRequest;
  459. switch (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY))
  460. {
  461. case CRYPTUI_WIZ_CREATE_ONLY:
  462. fValidInput &= NULL == *ppRequest;
  463. break;
  464. case CRYPTUI_WIZ_SUBMIT_ONLY:
  465. case CRYPTUI_WIZ_FREE_ONLY:
  466. fValidInput &= NULL != *ppRequest;
  467. break;
  468. case 0:
  469. default:
  470. ;
  471. }
  472. if (FALSE == fValidInput)
  473. {
  474. dwErr = ERROR_INVALID_PARAMETER;
  475. goto Ret;
  476. }
  477. //////////////////////////////////////////////////////////////
  478. //
  479. // PROCEDURE BODY:
  480. //
  481. //////////////////////////////////////////////////////////////
  482. // if enrolling for a service account then need to logon and load profile
  483. if (0 != pAcctName->Length)
  484. {
  485. dwErr = ERROR_NOT_SUPPORTED;
  486. goto Ret;
  487. }
  488. // assign all the values in the passed in structure to the
  489. // temporary structure
  490. KeyNew.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  491. KeyNew.dwProvType = pKeyNew->ulProvType;
  492. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->Provider,
  493. &pwszProv)))
  494. goto Ret;
  495. KeyNew.pwszProvider = pwszProv;
  496. KeyNew.dwProviderFlags = pKeyNew->ulProviderFlags;
  497. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->KeyContainer,
  498. &pwszCont)))
  499. goto Ret;
  500. KeyNew.pwszKeyContainer = pwszCont;
  501. KeyNew.dwKeySpec = pKeyNew->ulKeySpec;
  502. KeyNew.dwGenKeyFlags = pKeyNew->ulGenKeyFlags;
  503. KeyNew.dwEnrollmentFlags = pKeyNew->ulEnrollmentFlags;
  504. KeyNew.dwSubjectNameFlags = pKeyNew->ulSubjectNameFlags;
  505. KeyNew.dwPrivateKeyFlags = pKeyNew->ulPrivateKeyFlags;
  506. KeyNew.dwGeneralFlags = pKeyNew->ulGeneralFlags;
  507. pTmpKeyNew = &KeyNew;
  508. if (pCert->cb)
  509. {
  510. // if necessary assign the cert to be renewed values
  511. // temporary structure
  512. CertBlob.cbData = pCert->cb;
  513. CertBlob.pbData = pCert->pb;
  514. pCertBlob = &CertBlob;
  515. }
  516. if (CRYPTUI_WIZ_CERT_RENEW == ulPurpose)
  517. {
  518. // assign all the values in the passed in structure to the
  519. // temporary structure
  520. RenewKey.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  521. RenewKey.dwProvType = pRenewKey->ulProvType;
  522. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->Provider,
  523. &pwszRenewProv)))
  524. goto Ret;
  525. RenewKey.pwszProvider = pwszRenewProv;
  526. RenewKey.dwProviderFlags = pRenewKey->ulProviderFlags;
  527. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->KeyContainer,
  528. &pwszRenewCont)))
  529. goto Ret;
  530. RenewKey.pwszKeyContainer = pwszRenewCont;
  531. RenewKey.dwKeySpec = pRenewKey->ulKeySpec;
  532. RenewKey.dwGenKeyFlags = pRenewKey->ulGenKeyFlags;
  533. RenewKey.dwEnrollmentFlags = pRenewKey->ulEnrollmentFlags;
  534. RenewKey.dwSubjectNameFlags = pRenewKey->ulSubjectNameFlags;
  535. RenewKey.dwPrivateKeyFlags = pRenewKey->ulPrivateKeyFlags;
  536. RenewKey.dwGeneralFlags = pRenewKey->ulGeneralFlags;
  537. pTmpRenewKey = &RenewKey;
  538. }
  539. // For SUBMIT and FREE operations, hRequest is an IN parameter.
  540. if (0 != ((CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY) & ulFlags))
  541. {
  542. memcpy(&hRequest, (*ppRequest)->pb, sizeof(hRequest));
  543. }
  544. // check if the destination cert store was passed in
  545. if (0 != (dwErr = AllocAndAssignString(pDesStore, &pwszDesStore)))
  546. goto Ret;
  547. // copy over the request info
  548. EnrollInfo.dwSize = sizeof(EnrollInfo);
  549. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->UsageOID,
  550. &pwszUsage)))
  551. goto Ret;
  552. EnrollInfo.pwszUsageOID = pwszUsage;
  553. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->CertDNName,
  554. &pwszCertDNName)))
  555. goto Ret;
  556. EnrollInfo.pwszCertDNName = pwszCertDNName;
  557. // cast the cert extensions
  558. EnrollInfo.dwExtensions = pRequestInfo->cExtensions;
  559. cbExtensions = (sizeof(CERT_EXTENSIONS)+sizeof(PCERT_EXTENSIONS)) * pRequestInfo->cExtensions;
  560. for (DWORD dwIndex = 0; dwIndex < pRequestInfo->cExtensions; dwIndex++)
  561. {
  562. cbExtensions += sizeof(CERT_EXTENSION) *
  563. pRequestInfo->prgExtensions[dwIndex]->cExtension;
  564. }
  565. EnrollInfo.prgExtensions = (PCERT_EXTENSIONS *)MyAlloc(cbExtensions);
  566. if (NULL == EnrollInfo.prgExtensions)
  567. {
  568. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  569. goto Ret;
  570. }
  571. pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.dwExtensions);
  572. for (DWORD dwIndex = 0; dwIndex < EnrollInfo.dwExtensions; dwIndex++)
  573. {
  574. EnrollInfo.prgExtensions[dwIndex] = (PCERT_EXTENSIONS)pbExtensions;
  575. pbExtensions += sizeof(CERT_EXTENSIONS);
  576. EnrollInfo.prgExtensions[dwIndex]->cExtension = pRequestInfo->prgExtensions[dwIndex]->cExtension;
  577. EnrollInfo.prgExtensions[dwIndex]->rgExtension = (PCERT_EXTENSION)pbExtensions;
  578. pbExtensions += sizeof(CERT_EXTENSION) * EnrollInfo.prgExtensions[dwIndex]->cExtension;
  579. for (DWORD dwSubIndex = 0; dwSubIndex < EnrollInfo.prgExtensions[dwIndex]->cExtension; dwSubIndex++)
  580. {
  581. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId =
  582. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId;
  583. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical =
  584. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical;
  585. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.cbData =
  586. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].cbData;
  587. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.pbData =
  588. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pbData;
  589. }
  590. }
  591. EnrollInfo.dwPostOption = pRequestInfo->ulPostOption;
  592. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->FriendlyName,
  593. &pwszFriendly)))
  594. goto Ret;
  595. EnrollInfo.pwszFriendlyName = pwszFriendly;
  596. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Description,
  597. &pwszDescription)))
  598. goto Ret;
  599. EnrollInfo.pwszDescription = pwszDescription;
  600. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Attributes,
  601. &pwszAttributes)))
  602. goto Ret;
  603. if (0 != (dwErr = AllocAndAssignString(pHashAlg,
  604. &pwszHashAlg)))
  605. goto Ret;
  606. if (0 != (dwErr = AllocAndAssignString(pCALocation,
  607. &pwszCALocation)))
  608. goto Ret;
  609. if (0 != (dwErr = AllocAndAssignString(pCAName,
  610. &pwszCAName)))
  611. goto Ret;
  612. // call the local enrollment API
  613. __try {
  614. dwErr = LocalEnrollNoDS(ulFlags, pwszAttributes, NULL, fKeyService,
  615. ulPurpose, FALSE, 0, NULL, 0, pwszCALocation,
  616. pwszCAName, pCertBlob, pTmpRenewKey, fNewKey,
  617. pTmpKeyNew, pwszHashAlg, pwszDesStore, ulStoreFlags,
  618. &EnrollInfo, &PKCS7Blob, &HashBlob, pulStatus, &hRequest);
  619. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  620. // TODO: convert to Winerror
  621. dwErr = GetExceptionCode();
  622. }
  623. if( dwErr != 0 )
  624. goto Ret;
  625. // Assign OUT parameters based on what kind of request we've just made.
  626. // Possible requests are:
  627. //
  628. // 1) CREATE only // Assign "ppRequest" to contain a HANDLE to the cert request.
  629. // 2) SUBMIT only // Assign "ppPKCS7Blob" and "ppHashBlob" to the values returned from LocalEnrollNoDS()
  630. // 3) FREE only // No need to assign OUT params.
  631. // 4) Complete (all 3).
  632. switch (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY))
  633. {
  634. case CRYPTUI_WIZ_CREATE_ONLY:
  635. // We've done the request creation portion of a 3-stage request,
  636. // assign the "request" out parameter now:
  637. if (NULL == (*ppRequest = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB)+
  638. sizeof(hRequest))))
  639. {
  640. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  641. goto Ret;
  642. }
  643. (*ppRequest)->cb = sizeof(hRequest);
  644. (*ppRequest)->pb = (BYTE*)(*ppRequest) + sizeof(KEYSVC_BLOB);
  645. memcpy((*ppRequest)->pb, &hRequest, sizeof(hRequest));
  646. break;
  647. case CRYPTUI_WIZ_SUBMIT_ONLY:
  648. case 0:
  649. // We've done the request submittal portion of a 3-stage request,
  650. // or we've done a 1-stage request. Assign the "certificate" out parameters now:
  651. // alloc and copy for the RPC out parameters
  652. if (NULL == (*ppPKCS7Blob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  653. PKCS7Blob.cbData)))
  654. {
  655. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  656. goto Ret;
  657. }
  658. (*ppPKCS7Blob)->cb = PKCS7Blob.cbData;
  659. (*ppPKCS7Blob)->pb = (BYTE*)(*ppPKCS7Blob) + sizeof(KEYSVC_BLOB);
  660. memcpy((*ppPKCS7Blob)->pb, PKCS7Blob.pbData, (*ppPKCS7Blob)->cb);
  661. if (NULL == (*ppHashBlob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  662. HashBlob.cbData)))
  663. {
  664. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  665. goto Ret;
  666. }
  667. (*ppHashBlob)->cb = HashBlob.cbData;
  668. (*ppHashBlob)->pb = (BYTE*)(*ppHashBlob) + sizeof(KEYSVC_BLOB);
  669. memcpy((*ppHashBlob)->pb, HashBlob.pbData, (*ppHashBlob)->cb);
  670. break;
  671. case CRYPTUI_WIZ_FREE_ONLY:
  672. default:
  673. *ppRequest = NULL;
  674. break;
  675. }
  676. }
  677. __except ( EXCEPTION_EXECUTE_HANDLER )
  678. {
  679. dwErr = ERROR_INVALID_PARAMETER;
  680. goto Ret;
  681. }
  682. Ret:
  683. __try
  684. {
  685. if (pwszProv)
  686. MyFree(pwszProv);
  687. if (pwszCont)
  688. MyFree(pwszCont);
  689. if (pwszRenewProv)
  690. MyFree(pwszRenewProv);
  691. if (pwszRenewCont)
  692. MyFree(pwszRenewCont);
  693. if (pwszDesStore)
  694. MyFree(pwszDesStore);
  695. if (pwszAttributes)
  696. MyFree(pwszAttributes);
  697. if (pwszFriendly)
  698. MyFree(pwszFriendly);
  699. if (pwszDescription)
  700. MyFree(pwszDescription);
  701. if (pwszUsage)
  702. MyFree(pwszUsage);
  703. if (pwszCertDNName)
  704. MyFree(pwszCertDNName);
  705. if (pwszCAName)
  706. MyFree(pwszCAName);
  707. if (pwszCALocation)
  708. MyFree(pwszCALocation);
  709. if (pwszHashAlg)
  710. MyFree(pwszHashAlg);
  711. if (PKCS7Blob.pbData)
  712. {
  713. MyFree(PKCS7Blob.pbData);
  714. }
  715. if (HashBlob.pbData)
  716. {
  717. MyFree(HashBlob.pbData);
  718. }
  719. if (EnrollInfo.prgExtensions)
  720. MyFree(EnrollInfo.prgExtensions);
  721. }
  722. __except ( EXCEPTION_EXECUTE_HANDLER )
  723. {
  724. dwErr = ERROR_INVALID_PARAMETER;
  725. }
  726. return dwErr;
  727. }
  728. ULONG s_KeyrQueryRequestStatus
  729. (/* [in] */ handle_t hRPCBinding,
  730. /* [in] */ unsigned __int64 u64Request,
  731. /* [out, ref] */ KEYSVC_QUERY_CERT_REQUEST_INFO *pQueryInfo)
  732. {
  733. CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO QueryInfo;
  734. DWORD dwErr = 0;
  735. HANDLE hRequest = (HANDLE)u64Request;
  736. __try
  737. {
  738. // We have the permission necessary to query the request. Proceed.
  739. ZeroMemory(&QueryInfo, sizeof(QueryInfo));
  740. // Query the request.
  741. dwErr = LocalEnrollNoDS(CRYPTUI_WIZ_QUERY_ONLY, NULL, &QueryInfo, FALSE, 0, FALSE, NULL, NULL,
  742. 0, NULL, NULL, NULL, NULL, FALSE, NULL, NULL, NULL,
  743. 0, NULL, NULL, NULL, NULL, &hRequest);
  744. if (ERROR_SUCCESS != dwErr)
  745. goto Ret;
  746. }
  747. __except ( EXCEPTION_EXECUTE_HANDLER )
  748. {
  749. dwErr = ERROR_INVALID_PARAMETER;
  750. goto Ret;
  751. }
  752. pQueryInfo->ulSize = QueryInfo.dwSize;
  753. pQueryInfo->ulStatus = QueryInfo.dwStatus;
  754. Ret:
  755. return dwErr;
  756. }
  757. ULONG s_RKeyrPFXInstall
  758. (/* [in] */ handle_t hRPCBinding,
  759. /* [in] */ PKEYSVC_BLOB pPFX,
  760. /* [in] */ PKEYSVC_UNICODE_STRING pPassword,
  761. /* [in] */ ULONG ulFlags)
  762. {
  763. BOOL fIsImpersonatingClient = FALSE;
  764. CRYPT_DATA_BLOB PFXBlob;
  765. DWORD dwCertOpenStoreFlags;
  766. DWORD dwData;
  767. DWORD dwResult;
  768. HCERTSTORE hSrcStore = NULL;
  769. HCERTSTORE hCAStore = NULL;
  770. HCERTSTORE hMyStore = NULL;
  771. HCERTSTORE hRootStore = NULL;
  772. LPWSTR pwszPassword = NULL;
  773. PCCERT_CONTEXT pCertContext = NULL;
  774. struct Stores {
  775. HANDLE *phStore;
  776. LPCWSTR pwszStoreName;
  777. } rgStores[] = {
  778. { &hMyStore, L"my" },
  779. { &hCAStore, L"ca" },
  780. { &hRootStore, L"root" }
  781. };
  782. __try
  783. {
  784. // Initialize locals:
  785. PFXBlob.cbData = pPFX->cb;
  786. PFXBlob.pbData = pPFX->pb;
  787. switch (ulFlags & (CRYPT_MACHINE_KEYSET | CRYPT_USER_KEYSET))
  788. {
  789. case CRYPT_MACHINE_KEYSET:
  790. dwCertOpenStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  791. break;
  792. case CRYPT_USER_KEYSET: // not supported
  793. default:
  794. dwResult = ERROR_INVALID_PARAMETER;
  795. goto error;
  796. }
  797. dwResult = RpcImpersonateClient(hRPCBinding);
  798. if (RPC_S_OK != dwResult)
  799. goto error;
  800. fIsImpersonatingClient = TRUE;
  801. if (ERROR_SUCCESS != (dwResult = AllocAndAssignString((PKEYSVC_UNICODE_STRING)pPassword, &pwszPassword)))
  802. goto error;
  803. // Get an in-memory store which contains all of the certs in the PFX
  804. // blob.
  805. if (NULL == (hSrcStore = PFXImportCertStore(&PFXBlob, pwszPassword, ulFlags)))
  806. {
  807. dwResult = GetLastError();
  808. goto error;
  809. }
  810. // Open the stores we'll need:
  811. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStores); dwIndex++)
  812. {
  813. *(rgStores[dwIndex].phStore) = CertOpenStore
  814. (CERT_STORE_PROV_SYSTEM_W, // store provider type
  815. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, // cert encoding type
  816. NULL, // hCryptProv
  817. dwCertOpenStoreFlags, // open store flags
  818. rgStores[dwIndex].pwszStoreName // store name
  819. );
  820. if (NULL == *(rgStores[dwIndex].phStore))
  821. {
  822. dwResult = GetLastError();
  823. goto error;
  824. }
  825. }
  826. // Enumerate the certs in the in-memory store, and add them to the local machine's
  827. // "my" store. NOTE: CertEnumCertificatesInStore frees the previous cert context
  828. // before returning the new context.
  829. while (NULL != (pCertContext = CertEnumCertificatesInStore(hSrcStore, pCertContext)))
  830. {
  831. HCERTSTORE hCertStore;
  832. // check if the certificate has the property on it
  833. // make sure the private key matches the certificate
  834. // search for both machine key and user keys
  835. if (CertGetCertificateContextProperty
  836. (pCertContext,
  837. CERT_KEY_PROV_INFO_PROP_ID,
  838. NULL,
  839. &dwData) &&
  840. CryptFindCertificateKeyProvInfo
  841. (pCertContext,
  842. 0,
  843. NULL))
  844. {
  845. hCertStore = hMyStore;
  846. }
  847. else if (TrustIsCertificateSelfSigned
  848. (pCertContext,
  849. pCertContext->dwCertEncodingType,
  850. 0))
  851. {
  852. hCertStore = hRootStore;
  853. }
  854. else
  855. {
  856. hCertStore = hCAStore;
  857. }
  858. if (!CertAddCertificateContextToStore
  859. (hCertStore,
  860. pCertContext,
  861. CERT_STORE_ADD_NEW,
  862. NULL))
  863. {
  864. dwResult = GetLastError();
  865. goto error;
  866. }
  867. }
  868. }
  869. __except (EXCEPTION_EXECUTE_HANDLER)
  870. {
  871. dwResult = GetExceptionCode();
  872. goto error;
  873. }
  874. // We're done!
  875. dwResult = ERROR_SUCCESS;
  876. error:
  877. if (fIsImpersonatingClient) { MyRpcRevertToSelfEx(hRPCBinding); }
  878. if (NULL != hSrcStore) { CertCloseStore(hSrcStore, 0); }
  879. // Close all of the destination stores we've opened.
  880. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStores); dwIndex++)
  881. if (NULL != *(rgStores[dwIndex].phStore))
  882. CertCloseStore(*(rgStores[dwIndex].phStore), 0);
  883. if (NULL != pwszPassword) { MyFree(pwszPassword); }
  884. if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
  885. return dwResult;
  886. }
  887. ULONG s_RKeyrOpenKeyService(
  888. /* [in] */ handle_t hRPCBinding,
  889. /* [in] */ KEYSVC_TYPE OwnerType,
  890. /* [in] */ PKEYSVC_UNICODE_STRING pOwnerName,
  891. /* [in] */ ULONG ulDesiredAccess,
  892. /* [in] */ PKEYSVC_BLOB pAuthentication,
  893. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  894. /* [out] */ KEYSVC_HANDLE *phKeySvc)
  895. {
  896. return s_KeyrOpenKeyService
  897. (hRPCBinding,
  898. OwnerType,
  899. pOwnerName,
  900. ulDesiredAccess,
  901. pAuthentication,
  902. ppReserved,
  903. phKeySvc);
  904. }
  905. ULONG s_RKeyrCloseKeyService(
  906. /* [in] */ handle_t hRPCBinding,
  907. /* [in] */ KEYSVC_HANDLE hKeySvc,
  908. /* [in, out] */ PKEYSVC_BLOB *ppReserved)
  909. {
  910. return s_KeyrCloseKeyService
  911. (hRPCBinding,
  912. hKeySvc,
  913. ppReserved);
  914. }