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.

975 lines
34 KiB

  1. //depot/Lab03_DEV/Ds/security/cryptoapi/common/keysvc/keysvcc.cpp#3 - edit change 21738 (text)
  2. //depot/Lab03_N/DS/security/cryptoapi/common/keysvc/keysvcc.cpp#9 - edit change 6380 (text)
  3. //+-------------------------------------------------------------------------
  4. //
  5. // Microsoft Windows
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997 - 1999
  8. //
  9. // File: keysvcc.cpp
  10. //
  11. //--------------------------------------------------------------------------
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <wincrypt.h>
  17. #include <rpc.h>
  18. #include <ntdsapi.h>
  19. #include <assert.h>
  20. #include "keysvc.h"
  21. #include "cryptui.h"
  22. #include "lenroll.h"
  23. #include "keysvcc.h"
  24. #include "unicode.h"
  25. #include "waitsvc.h"
  26. typedef struct _WZR_RPC_BINDING_LIST
  27. {
  28. LPCSTR pszProtSeq;
  29. LPCSTR pszEndpoint;
  30. } WZR_RPC_BINDING_LIST;
  31. WZR_RPC_BINDING_LIST g_awzrBindingList[] =
  32. {
  33. { KEYSVC_LOCAL_PROT_SEQ, KEYSVC_LOCAL_ENDPOINT },
  34. { KEYSVC_DEFAULT_PROT_SEQ, KEYSVC_DEFAULT_ENDPOINT}
  35. };
  36. DWORD g_cwzrBindingList = sizeof(g_awzrBindingList)/sizeof(g_awzrBindingList[0]);
  37. //
  38. // BUGBUG: TODO: move the following to common header (rkeysvcc.w)
  39. //
  40. #define RKEYSVC_CONNECT_SECURE_ONLY 0x00000001
  41. /****************************************
  42. * Client side Key Service handles
  43. ****************************************/
  44. typedef struct _KEYSVCC_INFO_ {
  45. KEYSVC_HANDLE hKeySvc;
  46. handle_t hRPCBinding;
  47. } KEYSVCC_INFO, *PKEYSVCC_INFO;
  48. void InitUnicodeString(
  49. PKEYSVC_UNICODE_STRING pUnicodeString,
  50. LPCWSTR pszString
  51. )
  52. {
  53. pUnicodeString->Length = (USHORT)(wcslen(pszString) * sizeof(WCHAR));
  54. pUnicodeString->MaximumLength = pUnicodeString->Length + sizeof(WCHAR);
  55. pUnicodeString->Buffer = (USHORT*)pszString;
  56. // Ensure that we don't have a string longer than allowed by our interface:
  57. assert(pUnicodeString->Length < 64*1024);
  58. assert(pUnicodeString->MaximumLength < 64*1024);
  59. }
  60. ULONG SetupRemoteRPCSecurity(handle_t hRPCBinding, LPSTR wszServer, BOOL fMutualAuth)
  61. {
  62. DWORD ccServerPrincName;
  63. DWORD dwResult;
  64. RPC_SECURITY_QOS SecurityQOS;
  65. ULONG ulErr;
  66. unsigned char szServerPrincName[256];
  67. ZeroMemory(szServerPrincName, sizeof(szServerPrincName));
  68. // Construct the SPN of the server we want to communicate with:
  69. ccServerPrincName = sizeof(szServerPrincName) / sizeof(szServerPrincName[0]);
  70. dwResult = DsMakeSpn("protectedstorage", wszServer, NULL, 0, NULL, &ccServerPrincName, (LPSTR)szServerPrincName);
  71. if (ERROR_SUCCESS != dwResult) {
  72. goto Ret;
  73. }
  74. // Specify quality of service parameters.
  75. SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
  76. SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
  77. SecurityQOS.Capabilities = fMutualAuth ? RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT ; // do we need mutual auth?
  78. SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
  79. // NOTE: we still need to get MUTUAL_AUTH working in the remote case:
  80. ulErr = RpcBindingSetAuthInfoExA(hRPCBinding, szServerPrincName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_GSS_NEGOTIATE, NULL, RPC_C_AUTHZ_NAME, &SecurityQOS);
  81. if (RPC_S_OK != ulErr)
  82. {
  83. goto Ret;
  84. }
  85. ulErr = ERROR_SUCCESS;
  86. Ret:
  87. return ulErr;
  88. }
  89. ULONG SetupLocalRPCSecurity(handle_t hRPCBinding, BOOL fMutualAuth)
  90. {
  91. CHAR szDomainName[128];
  92. CHAR szName[128];
  93. DWORD cbDomainName;
  94. DWORD cbName;
  95. PSID pSid = NULL;
  96. RPC_SECURITY_QOS SecurityQOS;
  97. SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
  98. SID_NAME_USE SidNameUse;
  99. ULONG ulErr;
  100. // We're doing LRPC -- we need to get the account name of the service to do mutual auth
  101. if (!AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSid))
  102. {
  103. ulErr = GetLastError();
  104. goto Ret;
  105. }
  106. cbName = sizeof(szName);
  107. cbDomainName = sizeof(szDomainName);
  108. if (!LookupAccountSidA(NULL, pSid, szName, &cbName, szDomainName, &cbDomainName, &SidNameUse))
  109. {
  110. ulErr = GetLastError();
  111. goto Ret;
  112. }
  113. // Specify quality of service parameters.
  114. SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
  115. SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
  116. SecurityQOS.Capabilities = fMutualAuth ? RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH : RPC_C_QOS_CAPABILITIES_DEFAULT ; // do we need mutual auth?
  117. SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
  118. ulErr = RpcBindingSetAuthInfoExA(hRPCBinding, (unsigned char *)szName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, NULL, 0, &SecurityQOS);
  119. if (RPC_S_OK != ulErr)
  120. {
  121. goto Ret;
  122. }
  123. ulErr = ERROR_SUCCESS;
  124. Ret:
  125. if (NULL != pSid) {
  126. FreeSid(pSid);
  127. }
  128. return ulErr;
  129. }
  130. //*****************************************************
  131. //
  132. // Implementation of Client API for Key Service
  133. //
  134. //*****************************************************
  135. //--------------------------------------------------------------------------------
  136. // KeyOpenKeyServiceEx
  137. //
  138. // Creates a KEYSVCC_HANDLE which a keysvc client can use to access the keysvc
  139. // interface. This method should
  140. //
  141. // a) Create an RPC binding handle based on the best available protseq (LRPC or named pipes)
  142. // b) request mutual auth to ensure that the (L)RPC server isn't spoofing us.
  143. // c) set PKT_PRIVACY encryption type. NOTE: should this work for LPC?
  144. // d) ping the server to ensure that it's up (allows for better error reporting)
  145. // e) determine whether the server is an XP box. If it is XP, we need to
  146. // return an old-style KEYSVC_HANDLE for compatibility. This field
  147. // is ignored post-XP.
  148. //
  149. // rpc_ifspec - the interface to open (keysvc or remote keysvc)
  150. // pszMachineName - the server to bind to
  151. // OwnerType - must be KeySvcMachine
  152. // pwszOwnerName - must be NULL
  153. // fMutualAuth - TRUE if mutual auth is required, FALSE otherwise
  154. // pReserved - must be NULL
  155. // phKeySvcCli - the handle through which the client can access keysvc.
  156. // Must be closed through KeyCloseKeyService().
  157. //
  158. ULONG KeyOpenKeyServiceEx
  159. (/* [in] */ BOOL fRemoteKeysvc,
  160. /* [in] */ LPSTR pszMachineName,
  161. /* [in] */ KEYSVC_TYPE OwnerType,
  162. /* [in] */ LPWSTR pwszOwnerName,
  163. /* [in] */ BOOL fMutualAuth,
  164. /* [out][in] */ void *pReserved,
  165. /* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
  166. {
  167. BOOL static fDone = FALSE;
  168. DWORD i;
  169. handle_t hRPCBinding = NULL;
  170. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  171. ULONG ulErr = 0;
  172. unsigned char *pStringBinding = NULL;
  173. if (NULL != pReserved || KeySvcMachine != OwnerType || NULL != pwszOwnerName)
  174. {
  175. ulErr = ERROR_INVALID_PARAMETER;
  176. goto Ret;
  177. }
  178. // allocate for the client key service handle
  179. if (NULL == (pKeySvcCliInfo =
  180. (PKEYSVCC_INFO)LocalAlloc(LMEM_ZEROINIT,
  181. sizeof(KEYSVCC_INFO))))
  182. {
  183. ulErr = ERROR_NOT_ENOUGH_MEMORY;
  184. goto Ret;
  185. }
  186. //
  187. // before doing the Bind operation, wait for the cryptography
  188. // service to be available.
  189. //
  190. WaitForCryptService(L"ProtectedStorage", &fDone);
  191. //
  192. // a) Create the binding handle
  193. for (i = 0; i < g_cwzrBindingList; i++)
  194. {
  195. if (RPC_S_OK != RpcNetworkIsProtseqValid(
  196. (unsigned char *)g_awzrBindingList[i].pszProtSeq))
  197. {
  198. goto next;
  199. }
  200. ulErr = RpcStringBindingComposeA(
  201. NULL,
  202. (unsigned char *)g_awzrBindingList[i].pszProtSeq,
  203. (unsigned char *)pszMachineName,
  204. (unsigned char *)g_awzrBindingList[i].pszEndpoint,
  205. NULL,
  206. &pStringBinding);
  207. if (RPC_S_OK != ulErr)
  208. {
  209. goto next;
  210. }
  211. ulErr = RpcBindingFromStringBinding(
  212. pStringBinding,
  213. &hRPCBinding);
  214. if (RPC_S_OK != ulErr)
  215. {
  216. goto next;
  217. }
  218. //
  219. // b) we've got the RPC binding, now request mutual auth and
  220. // c) request PKT_PRIVACY
  221. //
  222. if (0 == strcmp("ncalrpc", g_awzrBindingList[i].pszProtSeq)) {
  223. ulErr = SetupLocalRPCSecurity(hRPCBinding, fMutualAuth);
  224. if (ERROR_SUCCESS != ulErr)
  225. {
  226. goto next;
  227. }
  228. } else if (0 == strcmp("ncacn_np", g_awzrBindingList[i].pszProtSeq)) {
  229. ulErr = SetupRemoteRPCSecurity(hRPCBinding, pszMachineName, fMutualAuth);
  230. if (ERROR_SUCCESS != ulErr)
  231. {
  232. goto next;
  233. }
  234. } else {
  235. // Unknown binding (shouldn't get here):
  236. ulErr = RPC_S_WRONG_KIND_OF_BINDING;
  237. goto Ret;
  238. }
  239. //
  240. // d) We've set up mutual auth, now ping the server to make sure it's up.
  241. // BUGBUG: There are two recommended ways of doing this. The "preferred"
  242. // way is to resolve the endpoint and call RpcMgmtIsServerListening().
  243. // This didn't work for me -- the function returned RPC_S_OK regardless
  244. // of whether the server was up. The "less preferred but acceptable"
  245. // way is simply to call a method on the remote interface. In the interests
  246. // of time, I'm sticking with this method for Whistler.
  247. //
  248. // e) we'll also try to determine whether we're binding to an XP
  249. // box. If so, return a KEYSVC_HANDLE for compatibility.
  250. // This is ignored post-XP.
  251. // we already have the binding we want to return:
  252. pKeySvcCliInfo->hRPCBinding = hRPCBinding;
  253. pKeySvcCliInfo->hKeySvc = NULL; // NULL for post-XP (we'll check this below)
  254. RpcTryExcept {
  255. KEYSVC_UNICODE_STRING kusOwnerName;
  256. KEYSVC_BLOB kBlobAuthentication;
  257. PKEYSVC_BLOB pkBlobReserved = NULL;
  258. PKEYSVC_BLOB pkBlobVersion = NULL;
  259. KEYSVC_HANDLE khCli = NULL;
  260. ZeroMemory(&kusOwnerName, sizeof(kusOwnerName));
  261. ZeroMemory(&kBlobAuthentication, sizeof(kBlobAuthentication));
  262. if (!fRemoteKeysvc)
  263. ulErr = KeyrOpenKeyService(hRPCBinding, KeySvcMachine, &kusOwnerName, 0, &kBlobAuthentication, &pkBlobVersion, &khCli);
  264. else
  265. ulErr = RKeyrOpenKeyService(hRPCBinding, KeySvcMachine, &kusOwnerName, 0, &kBlobAuthentication, &pkBlobVersion, &khCli);
  266. if (ERROR_SUCCESS == ulErr)
  267. {
  268. // we've got an XP box. Return the KEYSVC_HANDLE to the client.
  269. pKeySvcCliInfo->hKeySvc = khCli;
  270. } else if (ERROR_CALL_NOT_IMPLEMENTED == ulErr) {
  271. // we have a post-XP box -- that's fine.
  272. ulErr = ERROR_SUCCESS;
  273. } else {
  274. // unexpected, we'll give up.
  275. }
  276. } RpcExcept(I_RpcExceptionFilter(RpcExceptionCode())) { // handle only the RPC exceptions
  277. // We encountered an exception trying to contact the remote computer --
  278. // give up and return the error to the user.
  279. ulErr = RpcExceptionCode();
  280. } RpcEndExcept;
  281. if (ERROR_SUCCESS == ulErr)
  282. {
  283. break;
  284. }
  285. next:
  286. if (NULL != hRPCBinding) {
  287. // If we're talking to an XP box, free server data:
  288. if (NULL != pKeySvcCliInfo->hKeySvc) {
  289. PKEYSVC_BLOB pTmpReserved = NULL;
  290. KeyrCloseKeyService(hRPCBinding, pKeySvcCliInfo->hKeySvc, &pTmpReserved);
  291. pKeySvcCliInfo->hKeySvc = NULL;
  292. }
  293. // close the RPC binding
  294. RpcBindingFree(&hRPCBinding);
  295. hRPCBinding = NULL;
  296. }
  297. if (NULL != pStringBinding) {
  298. RpcStringFree(&pStringBinding);
  299. pStringBinding = NULL;
  300. }
  301. }
  302. if (ERROR_SUCCESS != ulErr)
  303. {
  304. // the server's a) not up, b) not supporting mutual auth, or c) not a compatibile version
  305. goto Ret;
  306. }
  307. ulErr = ERROR_SUCCESS;
  308. *phKeySvcCli = pKeySvcCliInfo;
  309. Ret:
  310. __try
  311. {
  312. if (pStringBinding)
  313. RpcStringFree(&pStringBinding);
  314. if (ERROR_SUCCESS != ulErr)
  315. {
  316. // If we're talking to an XP box, free server data:
  317. if (NULL != pKeySvcCliInfo) {
  318. if (NULL != pKeySvcCliInfo->hRPCBinding && NULL != pKeySvcCliInfo->hKeySvc) {
  319. PKEYSVC_BLOB pTmpReserved = NULL;
  320. KeyrCloseKeyService(pKeySvcCliInfo->hRPCBinding, pKeySvcCliInfo->hKeySvc, &pTmpReserved);
  321. }
  322. LocalFree(pKeySvcCliInfo);
  323. }
  324. // close the RPC binding
  325. if (NULL != hRPCBinding) {
  326. RpcBindingFree(&hRPCBinding);
  327. }
  328. }
  329. }
  330. __except ( EXCEPTION_EXECUTE_HANDLER )
  331. {
  332. ulErr = _exception_code();
  333. }
  334. return ulErr;
  335. }
  336. ULONG KeyOpenKeyService
  337. (/* [in] */ LPSTR pszMachineName,
  338. /* [in] */ KEYSVC_TYPE OwnerType,
  339. /* [in] */ LPWSTR pwszOwnerName,
  340. /* [in] */ void *pAuthentication,
  341. /* [out][in] */ void *pReserved,
  342. /* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
  343. {
  344. return KeyOpenKeyServiceEx
  345. (FALSE /*local key svc*/,
  346. pszMachineName,
  347. OwnerType,
  348. pwszOwnerName,
  349. TRUE,
  350. pReserved,
  351. phKeySvcCli);
  352. }
  353. ULONG KeyCloseKeyService(
  354. /* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  355. /* [out][in] */ void * /*pReserved*/)
  356. {
  357. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  358. PKEYSVC_BLOB pTmpReserved = NULL;
  359. ULONG ulErr = 0;
  360. __try
  361. {
  362. if (NULL == hKeySvcCli)
  363. {
  364. ulErr = ERROR_INVALID_PARAMETER;
  365. goto Ret;
  366. }
  367. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  368. if (NULL != pKeySvcCliInfo->hRPCBinding)
  369. {
  370. if (NULL != pKeySvcCliInfo->hKeySvc)
  371. {
  372. ulErr = KeyrCloseKeyService(pKeySvcCliInfo->hRPCBinding,
  373. pKeySvcCliInfo->hKeySvc,
  374. &pTmpReserved);
  375. }
  376. RpcBindingFree(&pKeySvcCliInfo->hRPCBinding);
  377. }
  378. LocalFree(hKeySvcCli);
  379. }
  380. __except ( EXCEPTION_EXECUTE_HANDLER )
  381. {
  382. ulErr = _exception_code();
  383. }
  384. Ret:
  385. return ulErr;
  386. }
  387. // Params needed for create:
  388. //
  389. // Params not needed for submit:
  390. // all except pszMachineName, dwPurpose, dwFlags, fEnroll, dwStoreFlags, hRequest, and dwFlags.
  391. //
  392. // Params not needed for free:
  393. // all except pszMachineName, hRequest, and dwFlags.
  394. //
  395. ULONG KeyEnroll_V2
  396. (/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  397. /* [in] */ LPSTR /*pszMachineName*/, //RESERVED: must be NULL (we don't support remote machine enrollment anymore)
  398. /* [in] */ BOOL fKeyService, //IN Required: Whether the function is called remotely
  399. /* [in] */ DWORD dwPurpose, //IN Required: Indicates type of request - enroll/renew
  400. /* [in] */ DWORD dwFlags, //IN Required: Flags for enrollment
  401. /* [in] */ LPWSTR pszAcctName, //IN Optional: Account name the service runs under
  402. /* [in] */ void * /*pAuthentication*/, //RESERVED must be NULL
  403. /* [in] */ BOOL /*fEnroll*/, //IN Required: Whether it is enrollment or renew
  404. /* [in] */ LPWSTR pszCALocation, //IN Required: The ca machine names to attempt to enroll with
  405. /* [in] */ LPWSTR pszCAName, //IN Required: The ca names to attempt to enroll with
  406. /* [in] */ BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
  407. /* [in] */ PCERT_REQUEST_PVK_NEW pKeyNew, //IN Required: The private key information
  408. /* [in] */ CERT_BLOB *pCert, //IN Optional: The old certificate if renewing
  409. /* [in] */ PCERT_REQUEST_PVK_NEW pRenewKey, //IN Optional: The new private key information
  410. /* [in] */ LPWSTR pszHashAlg, //IN Optional: The hash algorithm
  411. /* [in] */ LPWSTR pszDesStore, //IN Optional: The destination store
  412. /* [in] */ DWORD dwStoreFlags, //IN Optional: Flags for cert store.
  413. /* [in] */ PCERT_ENROLL_INFO pRequestInfo, //IN Required: The information about the cert request
  414. /* [in] */ LPWSTR pszAttributes, //IN Optional: Attribute string for request
  415. /* [in] */ DWORD dwReservedFlags, //RESERVED must be 0
  416. /* [in] */ BYTE * /*pReserved*/, //RESERVED must be NULL
  417. /* [in][out] */ HANDLE *phRequest, //IN OUT Optional: A handle to a created request
  418. /* [out] */ CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
  419. /* [out] */ CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
  420. /* [out] */ DWORD *pdwStatus) //OUT Optional: The status of the enrollment/renewal
  421. {
  422. PKEYSVC_BLOB pReservedBlob = NULL;
  423. KEYSVC_UNICODE_STRING AcctName;
  424. KEYSVC_UNICODE_STRING CALocation;
  425. KEYSVC_UNICODE_STRING CAName;
  426. KEYSVC_UNICODE_STRING DesStore;
  427. KEYSVC_UNICODE_STRING HashAlg;
  428. KEYSVC_BLOB KeySvcRequest;
  429. KEYSVC_BLOB *pKeySvcRequest = NULL;
  430. KEYSVC_BLOB *pPKCS7KeySvcBlob = NULL;
  431. KEYSVC_BLOB *pHashKeySvcBlob = NULL;
  432. ULONG ulKeySvcStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNKNOWN;
  433. KEYSVC_CERT_ENROLL_INFO EnrollInfo;
  434. KEYSVC_CERT_REQUEST_PVK_NEW_V2 NewKeyInfo;
  435. KEYSVC_CERT_REQUEST_PVK_NEW_V2 RenewKeyInfo;
  436. KEYSVC_BLOB CertBlob;
  437. DWORD i;
  438. DWORD j;
  439. DWORD dwErr = 0;
  440. DWORD cbExtensions;
  441. PBYTE pbExtensions;
  442. BOOL fCreateRequest = 0 == (dwFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY));
  443. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  444. __try
  445. {
  446. //////////////////////////////////////////////////////////////
  447. //
  448. // INITIALIZATION:
  449. //
  450. //////////////////////////////////////////////////////////////
  451. if (NULL != pPKCS7Blob) { memset(pPKCS7Blob, 0, sizeof(CERT_BLOB)); }
  452. if (NULL != pHashBlob) { memset(pHashBlob, 0, sizeof(CERT_BLOB)); }
  453. if (NULL != phRequest && NULL != *phRequest)
  454. {
  455. pKeySvcRequest = &KeySvcRequest;
  456. pKeySvcRequest->cb = sizeof(*phRequest);
  457. pKeySvcRequest->pb = (BYTE *)phRequest;
  458. }
  459. memset(&AcctName, 0, sizeof(AcctName));
  460. memset(&CALocation, 0, sizeof(CALocation));
  461. memset(&CAName, 0, sizeof(CAName));
  462. memset(&HashAlg, 0, sizeof(HashAlg));
  463. memset(&DesStore, 0, sizeof(DesStore));
  464. memset(&NewKeyInfo, 0, sizeof(NewKeyInfo));
  465. memset(&EnrollInfo, 0, sizeof(EnrollInfo));
  466. memset(&RenewKeyInfo, 0, sizeof(RenewKeyInfo));
  467. memset(&CertBlob, 0, sizeof(CertBlob));
  468. //////////////////////////////////////////////////////////////
  469. //
  470. // PROCEDURE BODY:
  471. //
  472. //////////////////////////////////////////////////////////////
  473. if (NULL == hKeySvcCli)
  474. {
  475. dwErr = ERROR_INVALID_PARAMETER;
  476. goto Ret;
  477. }
  478. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  479. // set up the key service unicode structs
  480. if (pszAcctName)
  481. InitUnicodeString(&AcctName, pszAcctName);
  482. if (pszCALocation)
  483. InitUnicodeString(&CALocation, pszCALocation);
  484. if (pszCAName)
  485. InitUnicodeString(&CAName, pszCAName);
  486. if (pszHashAlg)
  487. InitUnicodeString(&HashAlg, pszHashAlg);
  488. if (pszDesStore)
  489. InitUnicodeString(&DesStore, pszDesStore);
  490. // set up the new key info structure for the remote call
  491. // This is only necessary if we are actually _creating_ a request.
  492. // Submit-only and free-only operations can skip this operation.
  493. //
  494. if (TRUE == fCreateRequest)
  495. {
  496. NewKeyInfo.ulProvType = pKeyNew->dwProvType;
  497. if (pKeyNew->pwszProvider)
  498. {
  499. InitUnicodeString(&NewKeyInfo.Provider, pKeyNew->pwszProvider);
  500. }
  501. NewKeyInfo.ulProviderFlags = pKeyNew->dwProviderFlags;
  502. if (pKeyNew->pwszKeyContainer)
  503. {
  504. InitUnicodeString(&NewKeyInfo.KeyContainer,
  505. pKeyNew->pwszKeyContainer);
  506. }
  507. NewKeyInfo.ulKeySpec = pKeyNew->dwKeySpec;
  508. NewKeyInfo.ulGenKeyFlags = pKeyNew->dwGenKeyFlags;
  509. NewKeyInfo.ulEnrollmentFlags = pKeyNew->dwEnrollmentFlags;
  510. NewKeyInfo.ulSubjectNameFlags = pKeyNew->dwSubjectNameFlags;
  511. NewKeyInfo.ulPrivateKeyFlags = pKeyNew->dwPrivateKeyFlags;
  512. NewKeyInfo.ulGeneralFlags = pKeyNew->dwGeneralFlags;
  513. // set up the usage OIDs
  514. if (pRequestInfo->pwszUsageOID)
  515. {
  516. InitUnicodeString(&EnrollInfo.UsageOID, pRequestInfo->pwszUsageOID);
  517. }
  518. // set up the cert DN Name
  519. if (pRequestInfo->pwszCertDNName)
  520. {
  521. InitUnicodeString(&EnrollInfo.CertDNName, pRequestInfo->pwszCertDNName);
  522. }
  523. // set up the request info structure for the remote call
  524. EnrollInfo.ulPostOption = pRequestInfo->dwPostOption;
  525. if (pRequestInfo->pwszFriendlyName)
  526. {
  527. InitUnicodeString(&EnrollInfo.FriendlyName,
  528. pRequestInfo->pwszFriendlyName);
  529. }
  530. if (pRequestInfo->pwszDescription)
  531. {
  532. InitUnicodeString(&EnrollInfo.Description,
  533. pRequestInfo->pwszDescription);
  534. }
  535. if (pszAttributes)
  536. {
  537. InitUnicodeString(&EnrollInfo.Attributes, pszAttributes);
  538. }
  539. // convert the cert extensions
  540. // NOTE, the extensions structure cannot be simply cast,
  541. // as the structures have different packing behaviors in
  542. // 64 bit systems.
  543. EnrollInfo.cExtensions = pRequestInfo->dwExtensions;
  544. cbExtensions = EnrollInfo.cExtensions*(sizeof(PKEYSVC_CERT_EXTENSIONS) +
  545. sizeof(KEYSVC_CERT_EXTENSIONS));
  546. for(i=0; i < EnrollInfo.cExtensions; i++)
  547. {
  548. cbExtensions += pRequestInfo->prgExtensions[i]->cExtension*
  549. sizeof(KEYSVC_CERT_EXTENSION);
  550. }
  551. EnrollInfo.prgExtensions = (PKEYSVC_CERT_EXTENSIONS*)midl_user_allocate( cbExtensions);
  552. if(NULL == EnrollInfo.prgExtensions)
  553. {
  554. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  555. goto Ret;
  556. }
  557. pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.cExtensions);
  558. for(i=0; i < EnrollInfo.cExtensions; i++)
  559. {
  560. EnrollInfo.prgExtensions[i] = (PKEYSVC_CERT_EXTENSIONS)pbExtensions;
  561. pbExtensions += sizeof(KEYSVC_CERT_EXTENSIONS);
  562. EnrollInfo.prgExtensions[i]->cExtension = pRequestInfo->prgExtensions[i]->cExtension;
  563. EnrollInfo.prgExtensions[i]->rgExtension = (PKEYSVC_CERT_EXTENSION)pbExtensions;
  564. pbExtensions += sizeof(KEYSVC_CERT_EXTENSION)*EnrollInfo.prgExtensions[i]->cExtension;
  565. for(j=0; j < EnrollInfo.prgExtensions[i]->cExtension; j++)
  566. {
  567. EnrollInfo.prgExtensions[i]->rgExtension[j].pszObjId =
  568. pRequestInfo->prgExtensions[i]->rgExtension[j].pszObjId;
  569. EnrollInfo.prgExtensions[i]->rgExtension[j].fCritical =
  570. pRequestInfo->prgExtensions[i]->rgExtension[j].fCritical;
  571. EnrollInfo.prgExtensions[i]->rgExtension[j].cbData =
  572. pRequestInfo->prgExtensions[i]->rgExtension[j].Value.cbData;
  573. EnrollInfo.prgExtensions[i]->rgExtension[j].pbData =
  574. pRequestInfo->prgExtensions[i]->rgExtension[j].Value.pbData;
  575. }
  576. }
  577. // if doing renewal then make sure have everything needed
  578. if ((CRYPTUI_WIZ_CERT_RENEW == dwPurpose) &&
  579. ((NULL == pRenewKey) || (NULL == pCert)))
  580. {
  581. dwErr = ERROR_INVALID_PARAMETER;
  582. goto Ret;
  583. }
  584. // set up the new key info structure for the remote call
  585. if (pRenewKey)
  586. {
  587. RenewKeyInfo.ulProvType = pRenewKey->dwProvType;
  588. if (pRenewKey->pwszProvider)
  589. {
  590. InitUnicodeString(&RenewKeyInfo.Provider, pRenewKey->pwszProvider);
  591. }
  592. RenewKeyInfo.ulProviderFlags = pRenewKey->dwProviderFlags;
  593. if (pRenewKey->pwszKeyContainer)
  594. {
  595. InitUnicodeString(&RenewKeyInfo.KeyContainer,
  596. pRenewKey->pwszKeyContainer);
  597. }
  598. RenewKeyInfo.ulKeySpec = pRenewKey->dwKeySpec;
  599. RenewKeyInfo.ulGenKeyFlags = pRenewKey->dwGenKeyFlags;
  600. RenewKeyInfo.ulEnrollmentFlags = pRenewKey->dwEnrollmentFlags;
  601. RenewKeyInfo.ulSubjectNameFlags = pRenewKey->dwSubjectNameFlags;
  602. RenewKeyInfo.ulPrivateKeyFlags = pRenewKey->dwPrivateKeyFlags;
  603. RenewKeyInfo.ulGeneralFlags = pRenewKey->dwGeneralFlags;
  604. }
  605. // set up the cert blob for renewal
  606. if (pCert)
  607. {
  608. CertBlob.cb = pCert->cbData;
  609. CertBlob.pb = pCert->pbData;
  610. // Ensure that we don't have a blob longer than allowed by our interface:
  611. assert(CertBlob.pb < 128*1024);
  612. }
  613. }
  614. // make the remote enrollment call
  615. if (0 != (dwErr = KeyrEnroll_V2
  616. (pKeySvcCliInfo->hRPCBinding,
  617. fKeyService,
  618. dwPurpose,
  619. dwFlags,
  620. &AcctName,
  621. &CALocation,
  622. &CAName,
  623. fNewKey,
  624. &NewKeyInfo,
  625. &CertBlob,
  626. &RenewKeyInfo,
  627. &HashAlg,
  628. &DesStore,
  629. dwStoreFlags,
  630. &EnrollInfo,
  631. dwReservedFlags,
  632. &pReservedBlob,
  633. &pKeySvcRequest,
  634. &pPKCS7KeySvcBlob,
  635. &pHashKeySvcBlob,
  636. &ulKeySvcStatus)))
  637. goto Ret;
  638. // allocate and copy the output parameters.
  639. if ((NULL != pKeySvcRequest) &&
  640. (0 < pKeySvcRequest->cb) &&
  641. (NULL != phRequest))
  642. {
  643. memcpy(phRequest, pKeySvcRequest->pb, sizeof(*phRequest));
  644. }
  645. if ((NULL != pPKCS7KeySvcBlob) &&
  646. (0 < pPKCS7KeySvcBlob->cb) &&
  647. (NULL != pPKCS7Blob))
  648. {
  649. pPKCS7Blob->cbData = pPKCS7KeySvcBlob->cb;
  650. if (NULL == (pPKCS7Blob->pbData =
  651. (BYTE*)midl_user_allocate(pPKCS7Blob->cbData)))
  652. {
  653. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  654. goto Ret;
  655. }
  656. memcpy(pPKCS7Blob->pbData, pPKCS7KeySvcBlob->pb,
  657. pPKCS7Blob->cbData);
  658. }
  659. if ((NULL != pHashKeySvcBlob) &&
  660. (0 < pHashKeySvcBlob->cb) &&
  661. (NULL != pHashBlob))
  662. {
  663. pHashBlob->cbData = pHashKeySvcBlob->cb;
  664. if (NULL == (pHashBlob->pbData =
  665. (BYTE*)midl_user_allocate(pHashBlob->cbData)))
  666. {
  667. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  668. goto Ret;
  669. }
  670. memcpy(pHashBlob->pbData, pHashKeySvcBlob->pb, pHashBlob->cbData);
  671. }
  672. }
  673. __except ( EXCEPTION_EXECUTE_HANDLER )
  674. {
  675. return _exception_code();
  676. }
  677. Ret:
  678. __try
  679. {
  680. if(EnrollInfo.prgExtensions)
  681. {
  682. midl_user_free(EnrollInfo.prgExtensions);
  683. }
  684. if (pKeySvcRequest)
  685. {
  686. midl_user_free(pKeySvcRequest);
  687. }
  688. if (pPKCS7KeySvcBlob)
  689. {
  690. midl_user_free(pPKCS7KeySvcBlob);
  691. }
  692. if (pHashKeySvcBlob)
  693. {
  694. midl_user_free(pHashKeySvcBlob);
  695. }
  696. if (NULL != pdwStatus)
  697. {
  698. *pdwStatus = (DWORD)ulKeySvcStatus;
  699. }
  700. }
  701. __except ( EXCEPTION_EXECUTE_HANDLER )
  702. {
  703. return _exception_code();
  704. }
  705. return dwErr;
  706. }
  707. ULONG KeyEnumerateAvailableCertTypes(
  708. /* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  709. /* [out][in] */ void * /*pReserved*/,
  710. /* [out][in] */ ULONG *pcCertTypeCount,
  711. /* [in, out][size_is(,*pcCertTypeCount)] */
  712. PKEYSVC_UNICODE_STRING *ppCertTypes)
  713. {
  714. PKEYSVC_BLOB pTmpReserved = NULL;
  715. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  716. ULONG ulErr = 0;
  717. __try
  718. {
  719. if (NULL == hKeySvcCli)
  720. {
  721. ulErr = ERROR_INVALID_PARAMETER;
  722. goto Ret;
  723. }
  724. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  725. ulErr = KeyrEnumerateAvailableCertTypes(pKeySvcCliInfo->hRPCBinding,
  726. pKeySvcCliInfo->hKeySvc,
  727. &pTmpReserved,
  728. pcCertTypeCount,
  729. ppCertTypes);
  730. }
  731. __except ( EXCEPTION_EXECUTE_HANDLER )
  732. {
  733. ulErr = _exception_code();
  734. }
  735. Ret:
  736. return ulErr;
  737. }
  738. ULONG KeyEnumerateCAs(
  739. /* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  740. /* [out][in] */ void * /*pReserved*/,
  741. /* [in] */ ULONG ulFlags,
  742. /* [out][in] */ ULONG *pcCACount,
  743. /* [in, out][size_is(,*pcCACount)] */
  744. PKEYSVC_UNICODE_STRING *ppCAs)
  745. {
  746. PKEYSVC_BLOB pTmpReserved = NULL;
  747. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  748. ULONG ulErr = 0;
  749. __try
  750. {
  751. if (NULL == hKeySvcCli)
  752. {
  753. ulErr = ERROR_INVALID_PARAMETER;
  754. goto Ret;
  755. }
  756. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  757. ulErr = KeyrEnumerateCAs(pKeySvcCliInfo->hRPCBinding,
  758. pKeySvcCliInfo->hKeySvc,
  759. &pTmpReserved,
  760. ulFlags,
  761. pcCACount,
  762. ppCAs);
  763. }
  764. __except ( EXCEPTION_EXECUTE_HANDLER )
  765. {
  766. ulErr = _exception_code();
  767. }
  768. Ret:
  769. return ulErr;
  770. }
  771. extern "C" ULONG KeyQueryRequestStatus
  772. (/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  773. /* [in] */ HANDLE hRequest,
  774. /* [out, ref] */ CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *pQueryInfo)
  775. {
  776. KEYSVC_QUERY_CERT_REQUEST_INFO ksQueryCertRequestInfo;
  777. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  778. ULONG ulErr = 0;
  779. __try
  780. {
  781. if (NULL == hKeySvcCli || NULL == pQueryInfo)
  782. {
  783. ulErr = ERROR_INVALID_PARAMETER;
  784. goto Ret;
  785. }
  786. ZeroMemory(&ksQueryCertRequestInfo, sizeof(ksQueryCertRequestInfo));
  787. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  788. ulErr = KeyrQueryRequestStatus
  789. (pKeySvcCliInfo->hRPCBinding,
  790. (unsigned __int64)hRequest,
  791. &ksQueryCertRequestInfo);
  792. if (ERROR_SUCCESS == ulErr)
  793. {
  794. pQueryInfo->dwSize = ksQueryCertRequestInfo.ulSize;
  795. pQueryInfo->dwStatus = ksQueryCertRequestInfo.ulStatus;
  796. }
  797. }
  798. __except ( EXCEPTION_EXECUTE_HANDLER )
  799. {
  800. ulErr = _exception_code();
  801. }
  802. Ret:
  803. return ulErr;
  804. }
  805. extern "C" ULONG RKeyOpenKeyService
  806. (/* [in] */ LPSTR pszMachineName,
  807. /* [in] */ KEYSVC_TYPE OwnerType,
  808. /* [in] */ LPWSTR pwszOwnerName,
  809. /* [in] */ void *ulFlags,
  810. /* [out][in] */ void *pReserved,
  811. /* [out] */ KEYSVCC_HANDLE *phKeySvcCli)
  812. {
  813. return KeyOpenKeyServiceEx
  814. (TRUE /*remote key svc*/,
  815. pszMachineName,
  816. OwnerType,
  817. pwszOwnerName,
  818. (0 != (PtrToUlong(ulFlags) & RKEYSVC_CONNECT_SECURE_ONLY)),
  819. pReserved,
  820. phKeySvcCli);
  821. }
  822. extern "C" ULONG RKeyCloseKeyService(
  823. /* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  824. /* [out][in] */ void *pReserved)
  825. {
  826. return KeyCloseKeyService(hKeySvcCli, pReserved);
  827. }
  828. extern "C" ULONG RKeyPFXInstall
  829. (/* [in] */ KEYSVCC_HANDLE hKeySvcCli,
  830. /* [in] */ PKEYSVC_BLOB pPFX,
  831. /* [in] */ PKEYSVC_UNICODE_STRING pPassword,
  832. /* [in] */ ULONG ulFlags)
  833. {
  834. PKEYSVCC_INFO pKeySvcCliInfo = NULL;
  835. ULONG ulErr = 0;
  836. __try
  837. {
  838. if (NULL == hKeySvcCli)
  839. {
  840. ulErr = ERROR_INVALID_PARAMETER;
  841. goto Ret;
  842. }
  843. pKeySvcCliInfo = (PKEYSVCC_INFO)hKeySvcCli;
  844. ulErr = RKeyrPFXInstall(pKeySvcCliInfo->hRPCBinding,
  845. pPFX,
  846. pPassword,
  847. ulFlags);
  848. }
  849. __except ( EXCEPTION_EXECUTE_HANDLER )
  850. {
  851. ulErr = _exception_code();
  852. }
  853. Ret:
  854. return ulErr;
  855. }