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.

3479 lines
105 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 "unicode.h"
  20. #include "unicode5.h"
  21. #include <crypt.h>
  22. // Link List structure
  23. typedef struct _ContextList
  24. {
  25. KEYSVC_HANDLE hKeySvc;
  26. KEYSVC_CONTEXT *pContext;
  27. _ContextList *pNext;
  28. } CONTEXTLIST, *PCONTEXTLIST;
  29. static PCONTEXTLIST g_pContextList = NULL;
  30. // critical section for context linked list
  31. static CRITICAL_SECTION g_ListCritSec;
  32. BOOL
  33. GetTextualSid(
  34. IN PSID pSid, // binary Sid
  35. IN OUT LPWSTR TextualSid, // buffer for Textual representaion of Sid
  36. IN OUT LPDWORD dwBufferLen // required/provided TextualSid buffersize
  37. );
  38. BOOL
  39. GetUserTextualSid(
  40. IN OUT LPWSTR lpBuffer,
  41. IN OUT LPDWORD nSize
  42. );
  43. static BOOL g_fStartedKeyService = FALSE;
  44. #define KEYSVC_DEFAULT_ENDPOINT TEXT("\\pipe\\keysvc")
  45. #define KEYSVC_DEFAULT_PROT_SEQ TEXT("ncacn_np")
  46. #define MAXPROTSEQ 20
  47. #define ARRAYSIZE(rg) (sizeof(rg) / sizeof((rg)[0]))
  48. RPC_BINDING_VECTOR *pKeySvcBindingVector = NULL;
  49. void
  50. InitLsaString(
  51. PLSA_UNICODE_STRING LsaString, // destination
  52. LPWSTR String // source (Unicode)
  53. );
  54. void *MyAlloc(size_t len)
  55. {
  56. return LocalAlloc(LMEM_ZEROINIT, len);
  57. }
  58. void MyFree(void *p)
  59. {
  60. LocalFree(p);
  61. }
  62. DWORD
  63. StartKeyService(
  64. VOID
  65. )
  66. {
  67. DWORD dwLastError = ERROR_SUCCESS;
  68. //
  69. // WinNT4, Win95: do nothing, just return success
  70. //
  71. if( !FIsWinNT5() )
  72. return ERROR_SUCCESS;
  73. // initialize the context list critical section
  74. __try {
  75. InitializeCriticalSection(&g_ListCritSec);
  76. } __except (EXCEPTION_EXECUTE_HANDLER) {
  77. dwLastError = _exception_code();
  78. }
  79. if( dwLastError == ERROR_SUCCESS )
  80. g_fStartedKeyService = TRUE;
  81. return dwLastError;
  82. }
  83. DWORD
  84. StopKeyService(
  85. VOID
  86. )
  87. {
  88. DWORD dwLastError = ERROR_SUCCESS;
  89. if( !g_fStartedKeyService )
  90. return ERROR_SUCCESS;
  91. // delete the context list critical section which was inited in startup
  92. DeleteCriticalSection(&g_ListCritSec);
  93. return dwLastError;
  94. }
  95. BOOL
  96. IsAdministrator2(
  97. VOID
  98. )
  99. /*++
  100. This function determines if the calling user is an Administrator.
  101. On Windows 95, this function always returns FALSE, as there is
  102. no difference between users on that platform.
  103. NOTE : This function originally returned TRUE on Win95, but since this
  104. would allow machine key administration by anyone this was changed to
  105. FALSE.
  106. On Windows NT, the caller of this function must be impersonating
  107. the user which is to be queried. If the caller is not impersonating,
  108. this function will always return FALSE.
  109. --*/
  110. {
  111. HANDLE hAccessToken;
  112. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  113. PSID psidAdministrators = NULL;
  114. BOOL bSuccess;
  115. //
  116. // If we aren't on WinNT (on Win95) just return TRUE
  117. //
  118. if(!FIsWinNT())
  119. return FALSE;
  120. if(!OpenThreadToken(
  121. GetCurrentThread(),
  122. TOKEN_QUERY,
  123. TRUE,
  124. &hAccessToken
  125. )) return FALSE;
  126. bSuccess = AllocateAndInitializeSid(
  127. &siaNtAuthority,
  128. 2,
  129. SECURITY_BUILTIN_DOMAIN_RID,
  130. DOMAIN_ALIAS_RID_ADMINS,
  131. 0, 0, 0, 0, 0, 0,
  132. &psidAdministrators
  133. );
  134. if( bSuccess ) {
  135. BOOL fIsMember = FALSE;
  136. bSuccess = CheckTokenMembership( hAccessToken, psidAdministrators, &fIsMember );
  137. if( bSuccess && !fIsMember )
  138. bSuccess = FALSE;
  139. }
  140. CloseHandle( hAccessToken );
  141. if(psidAdministrators)
  142. FreeSid(psidAdministrators);
  143. return bSuccess;
  144. }
  145. // Use QueryServiceConfig() to get the service user name and domain
  146. DWORD GetServiceDomain(
  147. LPWSTR pszServiceName,
  148. LPWSTR *ppszUserName,
  149. LPWSTR *ppszDomainName
  150. )
  151. {
  152. SC_HANDLE hSCManager = 0;
  153. SC_HANDLE hService = 0;
  154. QUERY_SERVICE_CONFIGW serviceConfigIgnore;
  155. QUERY_SERVICE_CONFIGW *pServiceConfig = NULL;
  156. DWORD cbServiceConfig;
  157. DWORD i;
  158. DWORD cch;
  159. WCHAR *pch;
  160. DWORD dwErr = 0;
  161. // Initialization:
  162. memset(&serviceConfigIgnore, 0, sizeof(serviceConfigIgnore));
  163. // open the service control manager
  164. if (0 == (hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT)))
  165. {
  166. dwErr = NTE_FAIL;
  167. goto Ret;
  168. }
  169. // open the service
  170. if (0 == (hService = OpenServiceW(hSCManager, pszServiceName,
  171. SERVICE_QUERY_CONFIG)))
  172. {
  173. dwErr = NTE_FAIL;
  174. goto Ret;
  175. }
  176. QueryServiceConfigW(hService, &serviceConfigIgnore, 0, &cbServiceConfig);
  177. if (NULL == (pServiceConfig =
  178. (QUERY_SERVICE_CONFIGW*)MyAlloc(cbServiceConfig)))
  179. {
  180. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  181. goto Ret;
  182. }
  183. if (FALSE == QueryServiceConfigW(hService, pServiceConfig,
  184. cbServiceConfig, &cbServiceConfig))
  185. {
  186. dwErr = NTE_FAIL;
  187. goto Ret;
  188. }
  189. // get the domain name and the user name
  190. cch = wcslen((LPWSTR)pServiceConfig->lpServiceStartName);
  191. pch = (LPWSTR)pServiceConfig->lpServiceStartName;
  192. for(i=1;i<=cch;i++)
  193. {
  194. // quit when the \ is hit
  195. if (0x005C == pch[i-1])
  196. break;
  197. }
  198. pch = pServiceConfig->lpServiceStartName;
  199. if (NULL == (*ppszDomainName =
  200. (WCHAR*)MyAlloc((i + 1) * sizeof(WCHAR))))
  201. {
  202. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  203. goto Ret;
  204. }
  205. memcpy(*ppszDomainName, pch, (i - 1) * sizeof(WCHAR));
  206. if (NULL == (*ppszUserName =
  207. (WCHAR*)MyAlloc(((cch - i) + 1) * sizeof(WCHAR))))
  208. {
  209. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  210. goto Ret;
  211. }
  212. memcpy(*ppszUserName, &pch[i], (cch - i) * sizeof(WCHAR));
  213. Ret:
  214. if (pServiceConfig)
  215. MyFree(pServiceConfig);
  216. return dwErr;
  217. }
  218. //*************************************************************
  219. //
  220. // TestIfUserProfileLoaded()
  221. //
  222. // Purpose: Test to see if this user's profile is loaded.
  223. //
  224. // Parameters: hToken - user's token
  225. // *pfLoaded - OUT - TRUE if loaded false if not
  226. //
  227. // Return: TRUE if successful
  228. // FALSE if an error occurs
  229. //
  230. // Comments:
  231. //
  232. //*************************************************************
  233. BOOL TestIfUserProfileLoaded(
  234. HANDLE hToken,
  235. BOOL *pfLoaded
  236. )
  237. {
  238. WCHAR szSID[MAX_PATH+1];
  239. DWORD cchSID = sizeof(szSID) / sizeof(WCHAR);
  240. HKEY hRegKey = 0;;
  241. BOOL fRet = FALSE;
  242. *pfLoaded = FALSE;
  243. //
  244. // Get the Sid string for the user
  245. //
  246. if(!ImpersonateLoggedOnUser( hToken ))
  247. goto Ret;
  248. fRet = GetUserTextualSid(szSID, &cchSID);
  249. RevertToSelf();
  250. if( !fRet )
  251. goto Ret;
  252. fRet = FALSE;
  253. if (ERROR_SUCCESS == RegOpenKeyExW(HKEY_USERS, szSID, 0,
  254. MAXIMUM_ALLOWED, &hRegKey))
  255. {
  256. *pfLoaded = TRUE;
  257. }
  258. fRet = TRUE;
  259. Ret:
  260. if(hRegKey)
  261. RegCloseKey(hRegKey);
  262. return fRet;
  263. }
  264. #define SERVICE_KEYNAME_PREFIX L"_SC_"
  265. DWORD LogonToService(
  266. LPWSTR pszServiceName,
  267. HANDLE *phLogonToken,
  268. HANDLE *phProfile
  269. )
  270. {
  271. DWORD dwErr = 0;
  272. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  273. NTSTATUS Status;
  274. LSA_HANDLE hPolicy = 0;
  275. LSA_UNICODE_STRING KeyName;
  276. LPWSTR pszTmpKeyName = NULL;
  277. LSA_UNICODE_STRING *pServicePassword = NULL;
  278. PROFILEINFOW ProfileInfoW;
  279. LPWSTR pszUserName = NULL;
  280. LPWSTR pszDomainName = NULL;
  281. WCHAR rgwchPassword[PWLEN + 1];
  282. BOOL fProfileLoaded = FALSE;
  283. *phLogonToken = 0;
  284. *phProfile = 0;
  285. memset(&ObjectAttributes, 0, sizeof(ObjectAttributes));
  286. memset(&rgwchPassword, 0, sizeof(rgwchPassword));
  287. // set up the key name
  288. if (NULL == (pszTmpKeyName =
  289. (LPWSTR)MyAlloc((sizeof(SERVICE_KEYNAME_PREFIX) +
  290. wcslen(pszServiceName) + 1)
  291. * sizeof(WCHAR))))
  292. {
  293. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  294. goto Ret;
  295. }
  296. wcscpy(pszTmpKeyName, SERVICE_KEYNAME_PREFIX);
  297. wcscat(pszTmpKeyName, pszServiceName);
  298. InitLsaString(&KeyName, pszTmpKeyName);
  299. // open the policy
  300. if (STATUS_SUCCESS != (Status = LsaOpenPolicy(NULL, &ObjectAttributes,
  301. POLICY_GET_PRIVATE_INFORMATION,
  302. &hPolicy)))
  303. {
  304. dwErr = NTE_FAIL;
  305. goto Ret;
  306. }
  307. // get the service password
  308. if ((STATUS_SUCCESS != (Status = LsaRetrievePrivateData(hPolicy, &KeyName, &pServicePassword))) ||
  309. (NULL == pServicePassword))
  310. {
  311. dwErr = NTE_FAIL;
  312. goto Ret;
  313. }
  314. if(pServicePassword->Length > sizeof(rgwchPassword)) {
  315. dwErr = NTE_FAIL;
  316. goto Ret;
  317. }
  318. memcpy(rgwchPassword, pServicePassword->Buffer,
  319. pServicePassword->Length);
  320. // get the username + domain name
  321. if (0 != (dwErr = GetServiceDomain(pszServiceName,
  322. &pszUserName, &pszDomainName)))
  323. {
  324. goto Ret;
  325. }
  326. // log the service on
  327. if (0 == LogonUserW(pszUserName,
  328. pszDomainName,
  329. rgwchPassword,
  330. LOGON32_LOGON_SERVICE,
  331. LOGON32_PROVIDER_DEFAULT,
  332. phLogonToken))
  333. {
  334. dwErr = GetLastError();
  335. goto Ret;
  336. }
  337. // check if the profile is already loaded
  338. if (!TestIfUserProfileLoaded(*phLogonToken, &fProfileLoaded))
  339. {
  340. dwErr = GetLastError();
  341. goto Ret;
  342. }
  343. // if necessary load the hive associated with the service
  344. if (!fProfileLoaded)
  345. {
  346. memset(&ProfileInfoW, 0, sizeof(ProfileInfoW));
  347. ProfileInfoW.dwSize = sizeof(ProfileInfoW);
  348. ProfileInfoW.lpUserName = pszServiceName;
  349. ProfileInfoW.dwFlags = PI_NOUI;
  350. if (FALSE == LoadUserProfileW(*phLogonToken, &ProfileInfoW))
  351. {
  352. dwErr = GetLastError();
  353. goto Ret;
  354. }
  355. *phProfile = ProfileInfoW.hProfile;
  356. }
  357. // impersonate the service
  358. if (FALSE == ImpersonateLoggedOnUser(*phLogonToken))
  359. {
  360. dwErr = GetLastError();
  361. }
  362. Ret:
  363. if (0 != dwErr)
  364. {
  365. if (*phProfile)
  366. UnloadUserProfile(*phLogonToken, *phProfile);
  367. *phProfile = 0;
  368. if (*phLogonToken)
  369. CloseHandle(*phLogonToken);
  370. *phLogonToken = 0;
  371. }
  372. if (pServicePassword) {
  373. ZeroMemory( pServicePassword->Buffer, pServicePassword->Length );
  374. LsaFreeMemory(pServicePassword);
  375. }
  376. if (pszUserName)
  377. MyFree(pszUserName);
  378. if (pszDomainName)
  379. MyFree(pszDomainName);
  380. if (pszTmpKeyName)
  381. MyFree(pszTmpKeyName);
  382. if (hPolicy)
  383. LsaClose(hPolicy);
  384. return dwErr;
  385. }
  386. DWORD LogoffService(
  387. HANDLE hLogonToken,
  388. HANDLE hProfile
  389. )
  390. {
  391. DWORD dwErr = 0;
  392. // revert to self
  393. RevertToSelf();
  394. // unload the profile
  395. if (hProfile)
  396. UnloadUserProfile(hLogonToken, hProfile);
  397. // close the Token handle gotten with LogonUser
  398. if (hLogonToken)
  399. CloseHandle(hLogonToken);
  400. return dwErr;
  401. }
  402. DWORD CheckIfAdmin(
  403. handle_t hRPCBinding
  404. )
  405. {
  406. DWORD dwErr = 0;
  407. if (0 != (dwErr = RpcImpersonateClient((RPC_BINDING_HANDLE)hRPCBinding)))
  408. goto Ret;
  409. if (!IsAdministrator2())
  410. dwErr = (DWORD)NTE_PERM;
  411. Ret:
  412. RpcRevertToSelfEx((RPC_BINDING_HANDLE)hRPCBinding);
  413. return dwErr;
  414. }
  415. DWORD KeySvrImpersonate(
  416. handle_t hRPCBinding,
  417. KEYSVC_CONTEXT *pContext
  418. )
  419. {
  420. DWORD dwErr = 0;
  421. switch(pContext->dwType)
  422. {
  423. case KeySvcMachine:
  424. dwErr = CheckIfAdmin(hRPCBinding);
  425. break;
  426. case KeySvcService:
  427. if (0 != (dwErr = CheckIfAdmin(hRPCBinding)))
  428. goto Ret;
  429. dwErr = LogonToService(pContext->pszServiceName,
  430. &pContext->hLogonToken,
  431. &pContext->hProfile);
  432. break;
  433. }
  434. Ret:
  435. return dwErr;
  436. }
  437. DWORD KeySvrRevert(
  438. handle_t hRPCBinding,
  439. KEYSVC_CONTEXT *pContext
  440. )
  441. {
  442. DWORD dwErr = 0;
  443. if (pContext)
  444. {
  445. switch(pContext->dwType)
  446. {
  447. case KeySvcService:
  448. dwErr = LogoffService(pContext->hLogonToken,
  449. pContext->hProfile);
  450. pContext->hProfile = 0;
  451. pContext->hLogonToken = 0;
  452. break;
  453. }
  454. }
  455. return dwErr;
  456. }
  457. //
  458. // Function: MakeNewHandle
  459. //
  460. // Description: Creates a random key service handle.
  461. //
  462. KEYSVC_HANDLE MakeNewHandle()
  463. {
  464. KEYSVC_HANDLE hKeySvc = 0;
  465. // get a random handle value
  466. RtlGenRandom((BYTE*)&hKeySvc, sizeof(KEYSVC_HANDLE));
  467. return hKeySvc;
  468. }
  469. //
  470. // Function: CheckIfHandleInList
  471. //
  472. // Description: Goes through the link list of contexts and checks
  473. // if the passed in handle is in the list. If so
  474. // the list entry is returned.
  475. //
  476. PCONTEXTLIST CheckIfHandleInList(
  477. KEYSVC_HANDLE hKeySvc
  478. )
  479. {
  480. PCONTEXTLIST pContextList = g_pContextList;
  481. while (1)
  482. {
  483. if ((NULL == pContextList) || (pContextList->hKeySvc == hKeySvc))
  484. {
  485. break;
  486. }
  487. pContextList = pContextList->pNext;
  488. }
  489. return pContextList;
  490. }
  491. //
  492. // Function: MakeKeySvcHandle
  493. //
  494. // Description: The function takes a context pointer and returns a handle
  495. // to that context. An element in the context list is added
  496. // with the handle and the context pointer.
  497. //
  498. KEYSVC_HANDLE MakeKeySvcHandle(
  499. KEYSVC_CONTEXT *pContext
  500. )
  501. {
  502. DWORD dwRet = ERROR_INVALID_PARAMETER;
  503. KEYSVC_HANDLE hKeySvc = 0;
  504. BOOL fIncrementedRefCount = FALSE;
  505. BOOL fInCritSec = FALSE;
  506. PCONTEXTLIST pContextList = NULL;
  507. // allocate a new element for the list
  508. if (NULL == (pContextList = (PCONTEXTLIST)MyAlloc(sizeof(CONTEXTLIST))))
  509. {
  510. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  511. goto Error;
  512. }
  513. pContextList->pContext = pContext;
  514. if (0 >= InterlockedIncrement(&(pContext->iRefCount)))
  515. {
  516. dwRet = ERROR_INVALID_PARAMETER;
  517. goto Error;
  518. }
  519. fIncrementedRefCount = TRUE;
  520. // enter critical section
  521. EnterCriticalSection(&g_ListCritSec);
  522. fInCritSec = TRUE;
  523. __try
  524. {
  525. pContextList->pNext = g_pContextList;
  526. while (1)
  527. {
  528. hKeySvc = MakeNewHandle();
  529. if (NULL == CheckIfHandleInList(hKeySvc))
  530. break;
  531. }
  532. // add new element to the front of the list
  533. pContextList->hKeySvc = hKeySvc;
  534. g_pContextList = pContextList;
  535. }
  536. __except ( EXCEPTION_EXECUTE_HANDLER )
  537. {
  538. hKeySvc = 0;
  539. goto Error;
  540. }
  541. dwRet = ERROR_SUCCESS;
  542. Ret:
  543. // leave critical section
  544. if (fInCritSec)
  545. {
  546. LeaveCriticalSection(&g_ListCritSec);
  547. }
  548. SetLastError(dwRet);
  549. return hKeySvc;
  550. Error:
  551. if (NULL != pContextList) {
  552. MyFree(pContextList);
  553. }
  554. if (fIncrementedRefCount) {
  555. InterlockedDecrement(&(pContext->iRefCount));
  556. }
  557. goto Ret;
  558. }
  559. //
  560. // Function: CheckKeySvcHandle
  561. //
  562. // Description: The function takes a handle and returns the context pointer
  563. // associated with that handle. If the handle is not in the
  564. // list then the function returns NULL.
  565. //
  566. KEYSVC_CONTEXT *CheckKeySvcHandle(
  567. KEYSVC_HANDLE hKeySvc
  568. )
  569. {
  570. PCONTEXTLIST pContextList = NULL;
  571. KEYSVC_CONTEXT *pContext = NULL;
  572. // enter critical section
  573. EnterCriticalSection(&g_ListCritSec);
  574. __try
  575. {
  576. if (NULL != (pContextList = CheckIfHandleInList(hKeySvc)))
  577. {
  578. pContext = pContextList->pContext;
  579. // increment the ref count
  580. if (0 >= InterlockedIncrement(&(pContext->iRefCount)))
  581. {
  582. pContext = NULL;
  583. }
  584. }
  585. }
  586. __except ( EXCEPTION_EXECUTE_HANDLER )
  587. {
  588. goto Ret;
  589. }
  590. Ret:
  591. // leave critical section
  592. LeaveCriticalSection(&g_ListCritSec);
  593. return pContext;
  594. }
  595. //
  596. // Function: FreeContext
  597. //
  598. // Description: The function frees a context pointer.
  599. //
  600. void FreeContext(
  601. KEYSVC_CONTEXT *pContext
  602. )
  603. {
  604. if (NULL != pContext->pszServiceName)
  605. MyFree(pContext->pszServiceName);
  606. MyFree(pContext);
  607. }
  608. //
  609. // Function: FreeContext
  610. //
  611. // Description: The function frees a context pointer if the ref count is 0.
  612. //
  613. void ReleaseContext(
  614. IN KEYSVC_CONTEXT *pContext
  615. )
  616. {
  617. if (NULL != pContext)
  618. {
  619. if (0 >= InterlockedDecrement(&(pContext->iRefCount)))
  620. {
  621. FreeContext(pContext);
  622. }
  623. }
  624. }
  625. //
  626. // Function: RemoveKeySvcHandle
  627. //
  628. // Description: The function takes a handle and removes the element in
  629. // the list associated with this handle.
  630. //
  631. DWORD RemoveKeySvcHandle(
  632. KEYSVC_HANDLE hKeySvc
  633. )
  634. {
  635. PCONTEXTLIST pContextList = g_pContextList;
  636. PCONTEXTLIST pPrevious = NULL;
  637. DWORD dwErr = ERROR_INVALID_PARAMETER;
  638. // enter critical section
  639. EnterCriticalSection(&g_ListCritSec);
  640. __try
  641. {
  642. while (1)
  643. {
  644. // have we hit the end, if so exit without removing anything
  645. if (NULL == pContextList)
  646. {
  647. break;
  648. }
  649. // have we found the list entry
  650. if (hKeySvc == pContextList->hKeySvc)
  651. {
  652. if (pContextList == g_pContextList)
  653. {
  654. g_pContextList = pContextList->pNext;
  655. }
  656. else
  657. {
  658. pPrevious->pNext = pContextList->pNext;
  659. }
  660. // free the memory
  661. ReleaseContext(pContextList->pContext);
  662. MyFree(pContextList);
  663. dwErr = 0;
  664. break;
  665. }
  666. pPrevious = pContextList;
  667. pContextList = pContextList->pNext;
  668. }
  669. }
  670. __except ( EXCEPTION_EXECUTE_HANDLER )
  671. {
  672. goto Ret;
  673. }
  674. Ret:
  675. // leave critical section
  676. LeaveCriticalSection(&g_ListCritSec);
  677. return dwErr;
  678. }
  679. DWORD AllocAndAssignString(
  680. IN PKEYSVC_UNICODE_STRING pUnicodeString,
  681. OUT LPWSTR *ppwsz
  682. )
  683. {
  684. DWORD dwErr = 0;
  685. if ((NULL != pUnicodeString->Buffer) && (0 != pUnicodeString->Length))
  686. {
  687. if ((pUnicodeString->Length > pUnicodeString->MaximumLength) ||
  688. (pUnicodeString->Length & 1) || (pUnicodeString->MaximumLength & 1))
  689. {
  690. dwErr = ERROR_INVALID_PARAMETER;
  691. goto Ret;
  692. }
  693. if (NULL == (*ppwsz = (LPWSTR)MyAlloc(pUnicodeString->MaximumLength +
  694. sizeof(WCHAR))))
  695. {
  696. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  697. goto Ret;
  698. }
  699. memcpy(*ppwsz, pUnicodeString->Buffer, pUnicodeString->Length);
  700. }
  701. Ret:
  702. return dwErr;
  703. }
  704. // key service functions
  705. ULONG s_KeyrOpenKeyService(
  706. /* [in] */ handle_t hRPCBinding,
  707. /* [in] */ KEYSVC_TYPE OwnerType,
  708. /* [in] */ PKEYSVC_UNICODE_STRING pOwnerName,
  709. /* [in] */ ULONG ulDesiredAccess,
  710. /* [in] */ PKEYSVC_BLOB pAuthentication,
  711. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  712. /* [out] */ KEYSVC_HANDLE *phKeySvc)
  713. {
  714. KEYSVC_CONTEXT *pContext = NULL;
  715. BOOL fImpersonated = FALSE;
  716. HANDLE hThread = 0;
  717. HANDLE hToken = 0;
  718. WCHAR pszUserName[UNLEN + 1];
  719. DWORD cbUserName;
  720. DWORD dwErr = 0;
  721. __try
  722. {
  723. *phKeySvc = 0;
  724. if (NULL == ppReserved || NULL != *ppReserved)
  725. {
  726. dwErr = ERROR_INVALID_PARAMETER;
  727. goto Ret;
  728. }
  729. // Return a blob representing the version:
  730. (*ppReserved) = (PKEYSVC_BLOB)MyAlloc(sizeof(KEYSVC_BLOB) + sizeof(KEYSVC_OPEN_KEYSVC_INFO));
  731. if (NULL == (*ppReserved))
  732. {
  733. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  734. goto Ret;
  735. }
  736. (*ppReserved)->cb = sizeof(KEYSVC_OPEN_KEYSVC_INFO);
  737. (*ppReserved)->pb = ((LPBYTE)(*ppReserved)) + sizeof(KEYSVC_BLOB);
  738. KEYSVC_OPEN_KEYSVC_INFO sOpenKeySvcInfo = {
  739. sizeof(KEYSVC_OPEN_KEYSVC_INFO), KEYSVC_VERSION_WHISTLER
  740. };
  741. memcpy((*ppReserved)->pb, &sOpenKeySvcInfo, sizeof(sOpenKeySvcInfo));
  742. // allocate a new context structure
  743. if (NULL == (pContext = (KEYSVC_CONTEXT*)MyAlloc(sizeof(KEYSVC_CONTEXT))))
  744. {
  745. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  746. goto Ret;
  747. }
  748. pContext->dwType = OwnerType;
  749. // take action depending on type of key owner
  750. switch(OwnerType)
  751. {
  752. case KeySvcMachine:
  753. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  754. goto Ret;
  755. fImpersonated = TRUE;
  756. break;
  757. case KeySvcService:
  758. if (0 == pOwnerName->Length)
  759. {
  760. dwErr = ERROR_INVALID_PARAMETER;
  761. goto Ret;
  762. }
  763. if (0 != (dwErr = AllocAndAssignString(
  764. pOwnerName, &pContext->pszServiceName)))
  765. {
  766. goto Ret;
  767. }
  768. // impersonate the service
  769. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  770. goto Ret;
  771. fImpersonated = TRUE;
  772. break;
  773. default:
  774. dwErr = ERROR_INVALID_PARAMETER;
  775. goto Ret;
  776. }
  777. pContext->dwAccess = ulDesiredAccess;
  778. if (0 == (*phKeySvc = MakeKeySvcHandle(pContext)))
  779. {
  780. dwErr = GetLastError();
  781. }
  782. }
  783. __except ( EXCEPTION_EXECUTE_HANDLER )
  784. {
  785. dwErr = ERROR_INVALID_PARAMETER;
  786. goto Ret;
  787. }
  788. Ret:
  789. __try
  790. {
  791. if (hToken)
  792. CloseHandle(hToken);
  793. if (hThread)
  794. CloseHandle(hThread);
  795. if (fImpersonated)
  796. KeySvrRevert(hRPCBinding, pContext);
  797. // if error then free the context if necessary
  798. if (dwErr)
  799. {
  800. if(pContext)
  801. {
  802. FreeContext(pContext);
  803. }
  804. if((*ppReserved))
  805. {
  806. MyFree((*ppReserved));
  807. (*ppReserved) = NULL;
  808. }
  809. }
  810. }
  811. __except ( EXCEPTION_EXECUTE_HANDLER )
  812. {
  813. dwErr = ERROR_INVALID_PARAMETER;
  814. }
  815. return dwErr;
  816. }
  817. ULONG s_KeyrEnumerateProviders(
  818. /* [in] */ handle_t hRPCBinding,
  819. /* [in] */ KEYSVC_HANDLE hKeySvc,
  820. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  821. /* [in, out] */ ULONG *pcProviderCount,
  822. /* [in, out][size_is(,*pcProviderCount)] */
  823. PKEYSVC_PROVIDER_INFO *ppProviders)
  824. {
  825. PTMP_LIST_INFO pStart = NULL;
  826. PTMP_LIST_INFO pTmpList = NULL;
  827. PTMP_LIST_INFO pPrevious = NULL;
  828. PKEYSVC_PROVIDER_INFO pProvInfo;
  829. DWORD dwProvType;
  830. DWORD cbName;
  831. DWORD cbTotal = 0;
  832. DWORD cTypes = 0;
  833. DWORD i;
  834. DWORD j;
  835. BYTE *pb;
  836. KEYSVC_CONTEXT *pContext = NULL;
  837. BOOL fImpersonated = FALSE;
  838. DWORD dwErr = 0;
  839. __try
  840. {
  841. *pcProviderCount = 0;
  842. *ppProviders = NULL;
  843. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  844. {
  845. dwErr = ERROR_INVALID_PARAMETER;
  846. goto Ret;
  847. }
  848. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  849. goto Ret;
  850. fImpersonated = TRUE;
  851. // CryptoAPI enumerates one at a time
  852. // so we must accumulate for total enumeration
  853. for (i=0;;i++)
  854. {
  855. if (!CryptEnumProvidersW(i, NULL, 0, &dwProvType,
  856. NULL, &cbName))
  857. {
  858. if (ERROR_NO_MORE_ITEMS != GetLastError())
  859. {
  860. dwErr = NTE_FAIL;
  861. goto Ret;
  862. }
  863. break;
  864. }
  865. if (NULL == (pTmpList = (PTMP_LIST_INFO)MyAlloc(sizeof(TMP_LIST_INFO))))
  866. {
  867. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  868. goto Ret;
  869. }
  870. if (NULL == (pTmpList->pInfo = MyAlloc(sizeof(KEYSVC_PROVIDER_INFO) +
  871. cbName)))
  872. {
  873. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  874. goto Ret;
  875. }
  876. pProvInfo = (PKEYSVC_PROVIDER_INFO)pTmpList->pInfo;
  877. pProvInfo->Name.Length = (USHORT)cbName;
  878. pProvInfo->Name.MaximumLength = (USHORT)cbName;
  879. pProvInfo->Name.Buffer = (USHORT*)((BYTE*)(pProvInfo) +
  880. sizeof(KEYSVC_PROVIDER_INFO));
  881. if (!CryptEnumProvidersW(i,
  882. NULL,
  883. 0,
  884. &pProvInfo->ProviderType,
  885. pProvInfo->Name.Buffer, &cbName))
  886. {
  887. if (ERROR_NO_MORE_ITEMS != GetLastError())
  888. {
  889. MyFree(pProvInfo);
  890. dwErr = NTE_FAIL;
  891. goto Ret;
  892. }
  893. break;
  894. }
  895. cbTotal += cbName;
  896. if (0 == i)
  897. {
  898. pStart = pTmpList;
  899. }
  900. else
  901. {
  902. pPrevious->pNext = pTmpList;
  903. }
  904. pPrevious = pTmpList;
  905. pTmpList = NULL;
  906. }
  907. // now copy into one big structure
  908. pPrevious = pStart;
  909. if (0 != i)
  910. {
  911. *pcProviderCount = i;
  912. if (NULL == (*ppProviders =
  913. (PKEYSVC_PROVIDER_INFO)MyAlloc((i * sizeof(KEYSVC_PROVIDER_INFO)) +
  914. cbTotal)))
  915. {
  916. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  917. goto Ret;
  918. }
  919. pb = (BYTE*)(*ppProviders) + i * sizeof(KEYSVC_PROVIDER_INFO);
  920. // copy the provider information over
  921. for (j=0;j<i;j++)
  922. {
  923. pProvInfo = (PKEYSVC_PROVIDER_INFO)pPrevious->pInfo;
  924. (*ppProviders)[j].ProviderType = pProvInfo->ProviderType;
  925. (*ppProviders)[j].Name.Length = pProvInfo->Name.Length;
  926. (*ppProviders)[j].Name.MaximumLength = pProvInfo->Name.MaximumLength;
  927. memcpy(pb, (BYTE*)(pProvInfo->Name.Buffer),
  928. (*ppProviders)[j].Name.Length);
  929. (*ppProviders)[j].Name.Buffer = (USHORT*)pb;
  930. pb += (*ppProviders)[j].Name.Length;
  931. pPrevious = pPrevious->pNext;
  932. }
  933. }
  934. }
  935. __except ( EXCEPTION_EXECUTE_HANDLER )
  936. {
  937. dwErr = ERROR_INVALID_PARAMETER;
  938. goto Ret;
  939. }
  940. Ret:
  941. __try
  942. {
  943. if (pTmpList)
  944. MyFree(pTmpList);
  945. // free the list
  946. for (i=0;;i++)
  947. {
  948. if (NULL == pStart)
  949. break;
  950. pPrevious = pStart;
  951. pStart = pPrevious->pNext;
  952. if (pPrevious->pInfo)
  953. MyFree(pPrevious->pInfo);
  954. MyFree(pPrevious);
  955. }
  956. if (fImpersonated)
  957. KeySvrRevert(hRPCBinding, pContext);
  958. if (pContext)
  959. ReleaseContext(pContext);
  960. }
  961. __except ( EXCEPTION_EXECUTE_HANDLER )
  962. {
  963. dwErr = ERROR_INVALID_PARAMETER;
  964. }
  965. return dwErr;
  966. }
  967. ULONG s_KeyrEnumerateProviderTypes(
  968. /* [in] */ handle_t hRPCBinding,
  969. /* [in] */ KEYSVC_HANDLE hKeySvc,
  970. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  971. /* [in, out] */ ULONG *pcProviderCount,
  972. /* [in, out][size_is(,*pcProviderCount)] */
  973. PKEYSVC_PROVIDER_INFO *ppProviders)
  974. {
  975. PTMP_LIST_INFO pStart = NULL;
  976. PTMP_LIST_INFO pTmpList = NULL;
  977. PTMP_LIST_INFO pPrevious = NULL;
  978. PKEYSVC_PROVIDER_INFO pProvInfo;
  979. DWORD dwProvType;
  980. DWORD cbName = 0;;
  981. DWORD cbTotal = 0;
  982. DWORD cTypes = 0;
  983. DWORD i;
  984. DWORD j;
  985. BYTE *pb;
  986. KEYSVC_CONTEXT *pContext = NULL;
  987. BOOL fImpersonated = FALSE;
  988. DWORD dwErr = 0;
  989. __try
  990. {
  991. *pcProviderCount = 0;
  992. *ppProviders = NULL;
  993. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  994. {
  995. dwErr = ERROR_INVALID_PARAMETER;
  996. goto Ret;
  997. }
  998. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  999. goto Ret;
  1000. fImpersonated = TRUE;
  1001. // CryptoAPI enumerates one at a time
  1002. // so we must accumulate for total enumeration
  1003. for (i=0;;i++)
  1004. {
  1005. if (!CryptEnumProviderTypesW(i, NULL, 0, &dwProvType,
  1006. NULL, &cbName))
  1007. {
  1008. if (ERROR_NO_MORE_ITEMS != GetLastError())
  1009. {
  1010. dwErr = NTE_FAIL;
  1011. goto Ret;
  1012. }
  1013. break;
  1014. }
  1015. if (NULL == (pTmpList = (PTMP_LIST_INFO)MyAlloc(sizeof(TMP_LIST_INFO))))
  1016. {
  1017. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1018. goto Ret;
  1019. }
  1020. if (NULL == (pTmpList->pInfo = MyAlloc(sizeof(KEYSVC_PROVIDER_INFO) +
  1021. cbName)))
  1022. {
  1023. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1024. goto Ret;
  1025. }
  1026. pProvInfo = (PKEYSVC_PROVIDER_INFO)pTmpList->pInfo;
  1027. pProvInfo->Name.Length = (USHORT)cbName;
  1028. pProvInfo->Name.MaximumLength = (USHORT)cbName;
  1029. if (0 != cbName)
  1030. {
  1031. pProvInfo->Name.Buffer = (USHORT*)((BYTE*)(pProvInfo) +
  1032. sizeof(KEYSVC_PROVIDER_INFO));
  1033. }
  1034. if (!CryptEnumProviderTypesW(i, NULL, 0, &pProvInfo->ProviderType,
  1035. pProvInfo->Name.Buffer, &cbName))
  1036. {
  1037. if (ERROR_NO_MORE_ITEMS != GetLastError())
  1038. {
  1039. MyFree(pProvInfo);
  1040. dwErr = NTE_FAIL;
  1041. goto Ret;
  1042. }
  1043. break;
  1044. }
  1045. cbTotal += cbName;
  1046. if (0 == i)
  1047. {
  1048. pStart = pTmpList;
  1049. }
  1050. else
  1051. {
  1052. pPrevious->pNext = pTmpList;
  1053. }
  1054. pPrevious = pTmpList;
  1055. pTmpList = NULL;
  1056. }
  1057. // now copy into one big structure
  1058. pPrevious = pStart;
  1059. if (0 != i)
  1060. {
  1061. *pcProviderCount = i;
  1062. if (NULL == (*ppProviders =
  1063. (PKEYSVC_PROVIDER_INFO)MyAlloc((i * sizeof(KEYSVC_PROVIDER_INFO)) +
  1064. cbTotal)))
  1065. {
  1066. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1067. goto Ret;
  1068. }
  1069. pb = (BYTE*)(*ppProviders) + i * sizeof(KEYSVC_PROVIDER_INFO);
  1070. // copy the provider information over
  1071. for (j=0;j<i;j++)
  1072. {
  1073. pProvInfo = (PKEYSVC_PROVIDER_INFO)pPrevious->pInfo;
  1074. (*ppProviders)[j].ProviderType = pProvInfo->ProviderType;
  1075. (*ppProviders)[j].Name.Length = pProvInfo->Name.Length;
  1076. (*ppProviders)[j].Name.MaximumLength = pProvInfo->Name.MaximumLength;
  1077. if (0 != (*ppProviders)[j].Name.Length)
  1078. {
  1079. memcpy(pb, (BYTE*)(pProvInfo->Name.Buffer),
  1080. (*ppProviders)[j].Name.Length);
  1081. (*ppProviders)[j].Name.Buffer = (USHORT*)pb;
  1082. }
  1083. pb += (*ppProviders)[j].Name.Length;
  1084. pPrevious = pPrevious->pNext;
  1085. }
  1086. }
  1087. }
  1088. __except ( EXCEPTION_EXECUTE_HANDLER )
  1089. {
  1090. dwErr = ERROR_INVALID_PARAMETER;
  1091. goto Ret;
  1092. }
  1093. Ret:
  1094. __try
  1095. {
  1096. if (pTmpList)
  1097. MyFree(pTmpList);
  1098. // free the list
  1099. for (i=0;;i++)
  1100. {
  1101. if (NULL == pStart)
  1102. break;
  1103. pPrevious = pStart;
  1104. pStart = pPrevious->pNext;
  1105. if (pPrevious->pInfo)
  1106. MyFree(pPrevious->pInfo);
  1107. MyFree(pPrevious);
  1108. }
  1109. if (fImpersonated)
  1110. KeySvrRevert(hRPCBinding, pContext);
  1111. if (pContext)
  1112. ReleaseContext(pContext);
  1113. }
  1114. __except ( EXCEPTION_EXECUTE_HANDLER )
  1115. {
  1116. dwErr = ERROR_INVALID_PARAMETER;
  1117. }
  1118. return dwErr;
  1119. }
  1120. DWORD GetKeyIDs(
  1121. KEYSVC_PROVIDER_INFO *pProvider,
  1122. LPWSTR pszContainerName,
  1123. DWORD *pcKeyIDs,
  1124. PKEY_ID *ppKeyIDs,
  1125. DWORD dwFlags)
  1126. {
  1127. HCRYPTPROV hProv = 0;
  1128. HCRYPTKEY hKey = 0;
  1129. KEY_ID rgKeyIDs[2];
  1130. DWORD cbData;
  1131. DWORD dwKeySpec;
  1132. DWORD i;
  1133. DWORD dwErr = 0;
  1134. *pcKeyIDs = 0;
  1135. memset(rgKeyIDs, 0, sizeof(rgKeyIDs));
  1136. // acquire the context
  1137. if (!CryptAcquireContextU(&hProv, pszContainerName, pProvider->Name.Buffer,
  1138. pProvider->ProviderType, dwFlags))
  1139. {
  1140. dwErr = GetLastError();
  1141. goto Ret;
  1142. }
  1143. // try and get the AT_SIGNATURE key
  1144. for (i=0;i<2;i++)
  1145. {
  1146. // probably need to enumerate all key specs
  1147. if (0 == i)
  1148. dwKeySpec = AT_SIGNATURE;
  1149. else
  1150. dwKeySpec = AT_KEYEXCHANGE;
  1151. if (CryptGetUserKey(hProv, dwKeySpec, &hKey))
  1152. {
  1153. rgKeyIDs[*pcKeyIDs].dwKeySpec = dwKeySpec;
  1154. cbData = sizeof(ALG_ID);
  1155. if (!CryptGetKeyParam(hKey, KP_ALGID,
  1156. (BYTE*)(&rgKeyIDs[*pcKeyIDs].Algid),
  1157. &cbData, 0))
  1158. {
  1159. dwErr = GetLastError();
  1160. goto Ret;
  1161. }
  1162. (*pcKeyIDs)++;
  1163. CryptDestroyKey(hKey);
  1164. hKey = 0;
  1165. }
  1166. }
  1167. // allocate the final structure to hold the key ids and copy them in
  1168. if (*pcKeyIDs)
  1169. {
  1170. if (NULL == (*ppKeyIDs = (PKEY_ID)MyAlloc(*pcKeyIDs * sizeof(KEY_ID))))
  1171. {
  1172. goto Ret;
  1173. }
  1174. for (i=0;i<*pcKeyIDs;i++)
  1175. {
  1176. memcpy((BYTE*)(&(*ppKeyIDs)[i]), (BYTE*)(&rgKeyIDs[i]), sizeof(KEY_ID));
  1177. }
  1178. }
  1179. Ret:
  1180. if (hKey)
  1181. CryptDestroyKey(hKey);
  1182. if (hProv)
  1183. CryptReleaseContext(hProv, 0);
  1184. return dwErr;
  1185. }
  1186. ULONG s_KeyrEnumerateProvContainers(
  1187. /* [in] */ handle_t hRPCBinding,
  1188. /* [in] */ KEYSVC_HANDLE hKeySvc,
  1189. /* [in] */ KEYSVC_PROVIDER_INFO Provider,
  1190. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  1191. /* [in, out] */ ULONG *pcContainerCount,
  1192. /* [in, out][size_is(,*pcContainerCount)] */
  1193. PKEYSVC_UNICODE_STRING *ppContainers)
  1194. {
  1195. HCRYPTPROV hProv = 0;
  1196. PTMP_LIST_INFO pStart = NULL;
  1197. PTMP_LIST_INFO pTmpList = NULL;
  1198. PTMP_LIST_INFO pPrevious = NULL;
  1199. PKEYSVC_UNICODE_STRING pContainer;
  1200. DWORD i;
  1201. DWORD j;
  1202. BYTE *pb;
  1203. DWORD cbContainerName;
  1204. DWORD cbMaxContainerName = 0;
  1205. LPSTR pszContainerName = NULL;
  1206. DWORD cbContainerTotal = 0;
  1207. KEYSVC_CONTEXT *pContext = NULL;
  1208. DWORD dwFlags = 0;
  1209. DWORD dwMachineFlag = 0;
  1210. BOOL fImpersonated = FALSE;
  1211. BYTE *pbJunk = NULL;
  1212. DWORD cch;
  1213. DWORD dwErr = 0;
  1214. __try
  1215. {
  1216. *pcContainerCount = 0;
  1217. *ppContainers = NULL;
  1218. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  1219. {
  1220. dwErr = ERROR_INVALID_PARAMETER;
  1221. goto Ret;
  1222. }
  1223. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  1224. goto Ret;
  1225. fImpersonated = TRUE;
  1226. if (KeySvcMachine == pContext->dwType)
  1227. {
  1228. dwMachineFlag = CRYPT_MACHINE_KEYSET;
  1229. }
  1230. if (!CryptAcquireContextU(&hProv, NULL, Provider.Name.Buffer,
  1231. Provider.ProviderType,
  1232. dwMachineFlag | CRYPT_VERIFYCONTEXT))
  1233. {
  1234. dwErr = GetLastError();
  1235. goto Ret;
  1236. }
  1237. // CryptoAPI enumerates one at a time
  1238. // so we must accumulate for total enumeration
  1239. CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &cbMaxContainerName,
  1240. CRYPT_FIRST);
  1241. if (cbMaxContainerName > 0)
  1242. {
  1243. if (NULL == (pszContainerName = (LPSTR)MyAlloc(cbMaxContainerName)))
  1244. {
  1245. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1246. goto Ret;
  1247. }
  1248. }
  1249. for (i=0;;i++)
  1250. {
  1251. if (0 == i)
  1252. dwFlags = CRYPT_FIRST;
  1253. else
  1254. dwFlags = CRYPT_NEXT;
  1255. if (NULL == (pTmpList = (PTMP_LIST_INFO)MyAlloc(sizeof(TMP_LIST_INFO))))
  1256. {
  1257. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1258. goto Ret;
  1259. }
  1260. cbContainerName = cbMaxContainerName;
  1261. if (!CryptGetProvParam(hProv, PP_ENUMCONTAINERS, (BYTE*)pszContainerName,
  1262. &cbContainerName, dwFlags))
  1263. {
  1264. // BUG in rsabase - doesn't return correct error code
  1265. // if (ERROR_NO_MORE_ITEMS != GetLastError())
  1266. // {
  1267. // dwErr = NTE_FAIL;
  1268. // goto Ret;
  1269. // }
  1270. break;
  1271. }
  1272. // convert from ansi to unicode
  1273. if (0 == (cch = MultiByteToWideChar(CP_ACP, MB_COMPOSITE,
  1274. pszContainerName,
  1275. -1, NULL, cch)))
  1276. {
  1277. dwErr = GetLastError();
  1278. goto Ret;
  1279. }
  1280. if (NULL == (pTmpList->pInfo = MyAlloc(sizeof(KEYSVC_UNICODE_STRING) +
  1281. (cch + 1) * sizeof(WCHAR))))
  1282. {
  1283. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1284. goto Ret;
  1285. }
  1286. pContainer = (PKEYSVC_UNICODE_STRING)pTmpList->pInfo;
  1287. pContainer->Length = (USHORT)(cch * sizeof(WCHAR));
  1288. pContainer->MaximumLength = (USHORT)((cch + 1) * sizeof(WCHAR));
  1289. pContainer->Buffer = (USHORT*)((BYTE*)(pContainer) +
  1290. sizeof(KEYSVC_UNICODE_STRING));
  1291. if (0 == (cch = MultiByteToWideChar(CP_ACP, MB_COMPOSITE,
  1292. pszContainerName,
  1293. -1, pContainer->Buffer, cch)))
  1294. {
  1295. goto Ret;
  1296. }
  1297. cbContainerTotal += pContainer->Length + sizeof(WCHAR);
  1298. if (0 == i)
  1299. {
  1300. pStart = pTmpList;
  1301. }
  1302. else
  1303. {
  1304. pPrevious->pNext = pTmpList;
  1305. }
  1306. pPrevious = pTmpList;
  1307. pTmpList = NULL;
  1308. }
  1309. // now copy into one big structure
  1310. pPrevious = pStart;
  1311. if (0 != i)
  1312. {
  1313. *pcContainerCount = i;
  1314. if (NULL == (*ppContainers =
  1315. (PKEYSVC_UNICODE_STRING)MyAlloc((i * sizeof(KEYSVC_UNICODE_STRING)) +
  1316. cbContainerTotal)))
  1317. {
  1318. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1319. goto Ret;
  1320. }
  1321. pb = (BYTE*)(*ppContainers) + i * sizeof(KEYSVC_UNICODE_STRING);
  1322. // copy the provider information over
  1323. for (j=0;j<i;j++)
  1324. {
  1325. pContainer = (PKEYSVC_UNICODE_STRING)pPrevious->pInfo;
  1326. (*ppContainers)[j].Length = pContainer->Length;
  1327. (*ppContainers)[j].MaximumLength = pContainer->MaximumLength;
  1328. if (0 != (*ppContainers)[j].Length)
  1329. {
  1330. memcpy(pb, (BYTE*)(pContainer->Buffer),
  1331. (*ppContainers)[j].Length + sizeof(WCHAR));
  1332. (*ppContainers)[j].Buffer = (USHORT*)pb;
  1333. }
  1334. pb += (*ppContainers)[j].Length + sizeof(WCHAR);
  1335. pPrevious = pPrevious->pNext;
  1336. }
  1337. }
  1338. }
  1339. __except ( EXCEPTION_EXECUTE_HANDLER )
  1340. {
  1341. dwErr = ERROR_INVALID_PARAMETER;
  1342. goto Ret;
  1343. }
  1344. Ret:
  1345. __try
  1346. {
  1347. if (pszContainerName)
  1348. MyFree(pszContainerName);
  1349. if (hProv)
  1350. CryptReleaseContext(hProv, 0);
  1351. if (pTmpList)
  1352. MyFree(pTmpList);
  1353. // free the list
  1354. for (i=0;;i++)
  1355. {
  1356. if (NULL == pStart)
  1357. break;
  1358. pPrevious = pStart;
  1359. pStart = pPrevious->pNext;
  1360. if (pPrevious->pInfo)
  1361. MyFree(pPrevious->pInfo);
  1362. MyFree(pPrevious);
  1363. }
  1364. if (fImpersonated)
  1365. KeySvrRevert(hRPCBinding, pContext);
  1366. if (pContext)
  1367. ReleaseContext(pContext);
  1368. }
  1369. __except ( EXCEPTION_EXECUTE_HANDLER )
  1370. {
  1371. dwErr = ERROR_INVALID_PARAMETER;
  1372. }
  1373. return dwErr;
  1374. }
  1375. ULONG s_KeyrCloseKeyService(
  1376. /* [in] */ handle_t hRPCBinding,
  1377. /* [in] */ KEYSVC_HANDLE hKeySvc,
  1378. /* [in, out] */ PKEYSVC_BLOB *ppReserved)
  1379. {
  1380. DWORD dwErr = 0;
  1381. __try
  1382. {
  1383. dwErr = RemoveKeySvcHandle(hKeySvc);
  1384. }
  1385. __except ( EXCEPTION_EXECUTE_HANDLER )
  1386. {
  1387. dwErr = ERROR_INVALID_PARAMETER;
  1388. goto Ret;
  1389. }
  1390. Ret:
  1391. return dwErr;
  1392. }
  1393. ULONG s_KeyrGetDefaultProvider(
  1394. /* [in] */ handle_t hRPCBinding,
  1395. /* [in] */ KEYSVC_HANDLE hKeySvc,
  1396. /* [in] */ ULONG ulProvType,
  1397. /* [in] */ ULONG ulFlags,
  1398. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  1399. /* [out] */ ULONG *pulDefType,
  1400. /* [out] */ PKEYSVC_PROVIDER_INFO *ppProvider)
  1401. {
  1402. KEYSVC_CONTEXT *pContext = NULL;
  1403. BYTE *pb = NULL;
  1404. DWORD cbProvName;
  1405. DWORD dwFlags = CRYPT_USER_DEFAULT;
  1406. PKEYSVC_PROVIDER_INFO pProvInfo = NULL;
  1407. BOOL fImpersonated = FALSE;
  1408. DWORD dwErr = 0;
  1409. __try
  1410. {
  1411. *ppProvider = NULL;
  1412. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  1413. goto Ret;
  1414. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  1415. goto Ret;
  1416. fImpersonated = TRUE;
  1417. // set flag for MACHINE_KEYSET if necessary
  1418. if (KeySvcMachine != pContext->dwType)
  1419. {
  1420. if (!CryptGetDefaultProviderW(ulProvType, NULL, dwFlags,
  1421. NULL, &cbProvName))
  1422. {
  1423. dwFlags = CRYPT_MACHINE_DEFAULT;
  1424. }
  1425. }
  1426. else
  1427. {
  1428. dwFlags = CRYPT_MACHINE_DEFAULT;
  1429. }
  1430. if (CRYPT_MACHINE_DEFAULT == dwFlags)
  1431. {
  1432. if (!CryptGetDefaultProviderW(ulProvType, NULL, dwFlags,
  1433. NULL, &cbProvName))
  1434. {
  1435. dwErr = GetLastError();
  1436. goto Ret;
  1437. }
  1438. }
  1439. // alloc space for and place info into the ppProvider structure
  1440. if (NULL == (*ppProvider =
  1441. (PKEYSVC_PROVIDER_INFO)MyAlloc(sizeof(KEYSVC_PROVIDER_INFO) +
  1442. cbProvName)))
  1443. {
  1444. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1445. goto Ret;
  1446. }
  1447. pb = (BYTE*)(*ppProvider) + sizeof(KEYSVC_PROVIDER_INFO);
  1448. (*ppProvider)->ProviderType = ulProvType;
  1449. (*ppProvider)->Name.Length = (USHORT)cbProvName;
  1450. (*ppProvider)->Name.MaximumLength = (USHORT)cbProvName;
  1451. if (!CryptGetDefaultProviderW(ulProvType, NULL, dwFlags,
  1452. (USHORT*)pb, &cbProvName))
  1453. {
  1454. dwErr = GetLastError();
  1455. goto Ret;
  1456. }
  1457. (*ppProvider)->Name.Buffer = (USHORT*)pb;
  1458. if (CRYPT_MACHINE_DEFAULT == dwFlags)
  1459. {
  1460. *pulDefType = DefMachineProv;
  1461. }
  1462. else
  1463. {
  1464. *pulDefType = DefUserProv;
  1465. }
  1466. }
  1467. __except ( EXCEPTION_EXECUTE_HANDLER )
  1468. {
  1469. dwErr = ERROR_INVALID_PARAMETER;
  1470. goto Ret;
  1471. }
  1472. Ret:
  1473. __try
  1474. {
  1475. if (dwErr && *ppProvider)
  1476. {
  1477. MyFree(*ppProvider);
  1478. *ppProvider = NULL;
  1479. }
  1480. if (fImpersonated)
  1481. KeySvrRevert(hRPCBinding, pContext);
  1482. if (pContext)
  1483. ReleaseContext(pContext);
  1484. }
  1485. __except ( EXCEPTION_EXECUTE_HANDLER )
  1486. {
  1487. dwErr = ERROR_INVALID_PARAMETER;
  1488. }
  1489. return dwErr;
  1490. }
  1491. ULONG s_KeyrSetDefaultProvider(
  1492. /* [in] */ handle_t hRPCBinding,
  1493. /* [in] */ KEYSVC_HANDLE hKeySvc,
  1494. /* [in] */ ULONG ulFlags,
  1495. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  1496. /* [in] */ KEYSVC_PROVIDER_INFO Provider)
  1497. {
  1498. KEYSVC_CONTEXT *pContext = NULL;
  1499. DWORD dwFlags = CRYPT_USER_DEFAULT;
  1500. BOOL fImpersonated = FALSE;
  1501. LPWSTR pwszProvName = NULL;
  1502. DWORD dwErr = 0;
  1503. __try
  1504. {
  1505. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  1506. goto Ret;
  1507. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  1508. goto Ret;
  1509. fImpersonated = TRUE;
  1510. // set flag for MACHINE_KEYSET if necessary
  1511. if (KeySvcMachine == pContext->dwType)
  1512. dwFlags = CRYPT_MACHINE_DEFAULT;
  1513. if (0 != (dwErr = AllocAndAssignString(&(Provider.Name),
  1514. &pwszProvName)))
  1515. {
  1516. goto Ret;
  1517. }
  1518. if (!CryptSetProviderExW(pwszProvName, Provider.ProviderType,
  1519. NULL, dwFlags))
  1520. {
  1521. dwErr = GetLastError();
  1522. goto Ret;
  1523. }
  1524. }
  1525. __except ( EXCEPTION_EXECUTE_HANDLER )
  1526. {
  1527. dwErr = ERROR_INVALID_PARAMETER;
  1528. goto Ret;
  1529. }
  1530. Ret:
  1531. __try
  1532. {
  1533. if (pwszProvName)
  1534. MyFree(pwszProvName);
  1535. if (fImpersonated)
  1536. KeySvrRevert(hRPCBinding, pContext);
  1537. if (pContext)
  1538. ReleaseContext(pContext);
  1539. }
  1540. __except ( EXCEPTION_EXECUTE_HANDLER )
  1541. {
  1542. dwErr = ERROR_INVALID_PARAMETER;
  1543. }
  1544. return dwErr;
  1545. }
  1546. ULONG s_KeyrEnroll(
  1547. /* [in] */ handle_t hRPCBinding,
  1548. /* [in] */ BOOL fKeyService,
  1549. /* [in] */ ULONG ulPurpose,
  1550. /* [in] */ PKEYSVC_UNICODE_STRING pAcctName,
  1551. /* [in] */ PKEYSVC_UNICODE_STRING pCALocation,
  1552. /* [in] */ PKEYSVC_UNICODE_STRING pCAName,
  1553. /* [in] */ BOOL fNewKey,
  1554. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW pKeyNew,
  1555. /* [in] */ PKEYSVC_BLOB __RPC_FAR pCert,
  1556. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW pRenewKey,
  1557. /* [in] */ PKEYSVC_UNICODE_STRING pHashAlg,
  1558. /* [in] */ PKEYSVC_UNICODE_STRING pDesStore,
  1559. /* [in] */ ULONG ulStoreFlags,
  1560. /* [in] */ PKEYSVC_CERT_ENROLL_INFO pRequestInfo,
  1561. /* [in] */ ULONG ulFlags,
  1562. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR *ppReserved,
  1563. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppPKCS7Blob,
  1564. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppHashBlob,
  1565. /* [out] */ ULONG __RPC_FAR *pulStatus)
  1566. {
  1567. CERT_REQUEST_PVK_NEW KeyNew;
  1568. CERT_REQUEST_PVK_NEW RenewKey;
  1569. DWORD cbExtensions;
  1570. PBYTE pbExtensions = NULL;
  1571. PCERT_REQUEST_PVK_NEW pTmpRenewKey = NULL;
  1572. PCERT_REQUEST_PVK_NEW pTmpKeyNew = NULL;
  1573. LPWSTR pwszAcctName = NULL;
  1574. LPWSTR pwszProv = NULL;
  1575. LPWSTR pwszCont = NULL;
  1576. LPWSTR pwszRenewProv = NULL;
  1577. LPWSTR pwszRenewCont = NULL;
  1578. LPWSTR pwszDesStore = NULL;
  1579. LPWSTR pwszAttributes = NULL;
  1580. LPWSTR pwszFriendly = NULL;
  1581. LPWSTR pwszDescription = NULL;
  1582. LPWSTR pwszUsage = NULL;
  1583. LPWSTR pwszCALocation = NULL;
  1584. LPWSTR pwszCertDNName = NULL;
  1585. LPWSTR pwszCAName = NULL;
  1586. LPWSTR pwszHashAlg = NULL;
  1587. HANDLE hLogonToken = 0;
  1588. HANDLE hProfile = 0;
  1589. CERT_BLOB CertBlob;
  1590. CERT_BLOB *pCertBlob = NULL;
  1591. CERT_BLOB PKCS7Blob;
  1592. CERT_BLOB HashBlob;
  1593. CERT_ENROLL_INFO EnrollInfo;
  1594. DWORD dwErr = 0;
  1595. __try
  1596. {
  1597. memset(&KeyNew, 0, sizeof(KeyNew));
  1598. memset(&RenewKey, 0, sizeof(RenewKey));
  1599. memset(&EnrollInfo, 0, sizeof(EnrollInfo));
  1600. memset(&PKCS7Blob, 0, sizeof(PKCS7Blob));
  1601. memset(&HashBlob, 0, sizeof(HashBlob));
  1602. memset(&CertBlob, 0, sizeof(CertBlob));
  1603. *ppPKCS7Blob = NULL;
  1604. *ppHashBlob = NULL;
  1605. // check if the client is an admin
  1606. if (0 != (dwErr = CheckIfAdmin(hRPCBinding)))
  1607. goto Ret;
  1608. // if enrolling for a service account then need to logon and load profile
  1609. if (0 != pAcctName->Length)
  1610. {
  1611. if (0 != (dwErr = AllocAndAssignString(pAcctName, &pwszAcctName)))
  1612. goto Ret;
  1613. if (0 != (dwErr = LogonToService(pwszAcctName, &hLogonToken,
  1614. &hProfile)))
  1615. goto Ret;
  1616. }
  1617. // assign all the values in the passed in structure to the
  1618. // temporary structure
  1619. KeyNew.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  1620. KeyNew.dwProvType = pKeyNew->ulProvType;
  1621. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->Provider,
  1622. &pwszProv)))
  1623. goto Ret;
  1624. KeyNew.pwszProvider = pwszProv;
  1625. KeyNew.dwProviderFlags = pKeyNew->ulProviderFlags;
  1626. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->KeyContainer,
  1627. &pwszCont)))
  1628. goto Ret;
  1629. KeyNew.pwszKeyContainer = pwszCont;
  1630. KeyNew.dwKeySpec = pKeyNew->ulKeySpec;
  1631. KeyNew.dwGenKeyFlags = pKeyNew->ulGenKeyFlags;
  1632. pTmpKeyNew = &KeyNew;
  1633. if (pCert->cb)
  1634. {
  1635. // if necessary assign the cert to be renewed values
  1636. // temporary structure
  1637. CertBlob.cbData = pCert->cb;
  1638. CertBlob.pbData = pCert->pb;
  1639. pCertBlob = &CertBlob;
  1640. }
  1641. if (CRYPTUI_WIZ_CERT_RENEW == ulPurpose)
  1642. {
  1643. // assign all the values in the passed in structure to the
  1644. // temporary structure
  1645. RenewKey.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  1646. RenewKey.dwProvType = pRenewKey->ulProvType;
  1647. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->Provider,
  1648. &pwszRenewProv)))
  1649. goto Ret;
  1650. RenewKey.pwszProvider = pwszRenewProv;
  1651. RenewKey.dwProviderFlags = pRenewKey->ulProviderFlags;
  1652. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->KeyContainer,
  1653. &pwszRenewCont)))
  1654. goto Ret;
  1655. RenewKey.pwszKeyContainer = pwszRenewCont;
  1656. RenewKey.dwKeySpec = pRenewKey->ulKeySpec;
  1657. RenewKey.dwGenKeyFlags = pRenewKey->ulGenKeyFlags;
  1658. pTmpRenewKey = &RenewKey;
  1659. }
  1660. // check if the destination cert store was passed in
  1661. if (0 != (dwErr = AllocAndAssignString(pDesStore, &pwszDesStore)))
  1662. goto Ret;
  1663. // copy over the request info
  1664. EnrollInfo.dwSize = sizeof(EnrollInfo);
  1665. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->UsageOID,
  1666. &pwszUsage)))
  1667. goto Ret;
  1668. EnrollInfo.pwszUsageOID = pwszUsage;
  1669. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->CertDNName,
  1670. &pwszCertDNName)))
  1671. goto Ret;
  1672. EnrollInfo.pwszCertDNName = pwszCertDNName;
  1673. // cast the cert extensions
  1674. EnrollInfo.dwExtensions = pRequestInfo->cExtensions;
  1675. cbExtensions = (sizeof(CERT_EXTENSIONS)+sizeof(PCERT_EXTENSIONS)) * pRequestInfo->cExtensions;
  1676. for (DWORD dwIndex = 0; dwIndex < pRequestInfo->cExtensions; dwIndex++)
  1677. {
  1678. cbExtensions += sizeof(CERT_EXTENSION) *
  1679. pRequestInfo->prgExtensions[dwIndex]->cExtension;
  1680. }
  1681. EnrollInfo.prgExtensions = (PCERT_EXTENSIONS *)MyAlloc(cbExtensions);
  1682. if (NULL == EnrollInfo.prgExtensions)
  1683. {
  1684. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1685. goto Ret;
  1686. }
  1687. pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.dwExtensions);
  1688. for (DWORD dwIndex = 0; dwIndex < EnrollInfo.dwExtensions; dwIndex++)
  1689. {
  1690. EnrollInfo.prgExtensions[dwIndex] = (PCERT_EXTENSIONS)pbExtensions;
  1691. pbExtensions += sizeof(CERT_EXTENSIONS);
  1692. EnrollInfo.prgExtensions[dwIndex]->cExtension = pRequestInfo->prgExtensions[dwIndex]->cExtension;
  1693. EnrollInfo.prgExtensions[dwIndex]->rgExtension = (PCERT_EXTENSION)pbExtensions;
  1694. pbExtensions += sizeof(CERT_EXTENSION) * EnrollInfo.prgExtensions[dwIndex]->cExtension;
  1695. for (DWORD dwSubIndex = 0; dwSubIndex < EnrollInfo.prgExtensions[dwIndex]->cExtension; dwSubIndex++)
  1696. {
  1697. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId =
  1698. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId;
  1699. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical =
  1700. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical;
  1701. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.cbData =
  1702. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].cbData;
  1703. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.pbData =
  1704. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pbData;
  1705. }
  1706. }
  1707. EnrollInfo.dwPostOption = pRequestInfo->ulPostOption;
  1708. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->FriendlyName,
  1709. &pwszFriendly)))
  1710. goto Ret;
  1711. EnrollInfo.pwszFriendlyName = pwszFriendly;
  1712. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Description,
  1713. &pwszDescription)))
  1714. goto Ret;
  1715. EnrollInfo.pwszDescription = pwszDescription;
  1716. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Attributes,
  1717. &pwszAttributes)))
  1718. goto Ret;
  1719. if (0 != (dwErr = AllocAndAssignString(pHashAlg,
  1720. &pwszHashAlg)))
  1721. goto Ret;
  1722. if (0 != (dwErr = AllocAndAssignString(pCALocation,
  1723. &pwszCALocation)))
  1724. goto Ret;
  1725. if (0 != (dwErr = AllocAndAssignString(pCAName,
  1726. &pwszCAName)))
  1727. goto Ret;
  1728. // call the local enrollment API
  1729. __try {
  1730. dwErr = LocalEnroll(0, pwszAttributes, NULL, fKeyService,
  1731. ulPurpose, FALSE, 0, NULL, 0, pwszCALocation,
  1732. pwszCAName, pCertBlob, pTmpRenewKey, fNewKey,
  1733. pTmpKeyNew, pwszHashAlg, pwszDesStore, ulStoreFlags,
  1734. &EnrollInfo, &PKCS7Blob, &HashBlob, pulStatus, NULL);
  1735. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  1736. // TODO: convert to Winerror
  1737. dwErr = GetExceptionCode();
  1738. }
  1739. if( dwErr != 0 )
  1740. goto Ret;
  1741. // alloc and copy for the RPC out parameters
  1742. if (NULL == (*ppPKCS7Blob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  1743. PKCS7Blob.cbData)))
  1744. {
  1745. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1746. goto Ret;
  1747. }
  1748. (*ppPKCS7Blob)->cb = PKCS7Blob.cbData;
  1749. (*ppPKCS7Blob)->pb = (BYTE*)(*ppPKCS7Blob) + sizeof(KEYSVC_BLOB);
  1750. memcpy((*ppPKCS7Blob)->pb, PKCS7Blob.pbData, (*ppPKCS7Blob)->cb);
  1751. if (NULL == (*ppHashBlob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  1752. HashBlob.cbData)))
  1753. {
  1754. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1755. goto Ret;
  1756. }
  1757. (*ppHashBlob)->cb = HashBlob.cbData;
  1758. (*ppHashBlob)->pb = (BYTE*)(*ppHashBlob) + sizeof(KEYSVC_BLOB);
  1759. memcpy((*ppHashBlob)->pb, HashBlob.pbData, (*ppHashBlob)->cb);
  1760. }
  1761. __except ( EXCEPTION_EXECUTE_HANDLER )
  1762. {
  1763. dwErr = ERROR_INVALID_PARAMETER;
  1764. goto Ret;
  1765. }
  1766. Ret:
  1767. __try
  1768. {
  1769. if (pwszAcctName)
  1770. MyFree(pwszAcctName);
  1771. if (pwszProv)
  1772. MyFree(pwszProv);
  1773. if (pwszCont)
  1774. MyFree(pwszCont);
  1775. if (pwszRenewProv)
  1776. MyFree(pwszRenewProv);
  1777. if (pwszRenewCont)
  1778. MyFree(pwszRenewCont);
  1779. if (pwszDesStore)
  1780. MyFree(pwszDesStore);
  1781. if (pwszAttributes)
  1782. MyFree(pwszAttributes);
  1783. if (pwszFriendly)
  1784. MyFree(pwszFriendly);
  1785. if (pwszDescription)
  1786. MyFree(pwszDescription);
  1787. if (pwszUsage)
  1788. MyFree(pwszUsage);
  1789. if (pwszCertDNName)
  1790. MyFree(pwszCertDNName);
  1791. if (pwszCAName)
  1792. MyFree(pwszCAName);
  1793. if (pwszCALocation)
  1794. MyFree(pwszCALocation);
  1795. if (pwszHashAlg)
  1796. MyFree(pwszHashAlg);
  1797. if (PKCS7Blob.pbData)
  1798. {
  1799. MyFree(PKCS7Blob.pbData);
  1800. }
  1801. if (HashBlob.pbData)
  1802. {
  1803. MyFree(HashBlob.pbData);
  1804. }
  1805. if (hLogonToken || hProfile)
  1806. {
  1807. LogoffService(&hLogonToken, &hProfile);
  1808. }
  1809. if (EnrollInfo.prgExtensions)
  1810. MyFree(EnrollInfo.prgExtensions);
  1811. }
  1812. __except ( EXCEPTION_EXECUTE_HANDLER )
  1813. {
  1814. dwErr = ERROR_INVALID_PARAMETER;
  1815. }
  1816. return dwErr;
  1817. }
  1818. DWORD MoveCertsFromSystemToMemStore(
  1819. PKEYSVC_UNICODE_STRING pCertStore,
  1820. DWORD dwStoreFlags,
  1821. ULONG cHashCount,
  1822. KEYSVC_CERT_HASH *pHashes,
  1823. HCERTSTORE *phMemStore
  1824. )
  1825. {
  1826. DWORD i;
  1827. HCERTSTORE hStore = 0;
  1828. PCCERT_CONTEXT pCertContext = NULL;
  1829. CRYPT_HASH_BLOB HashBlob;
  1830. DWORD dwErr = 0;
  1831. if (NULL == (hStore = CertOpenStore(sz_CERT_STORE_PROV_SYSTEM_W,
  1832. 0, 0, dwStoreFlags,
  1833. pCertStore->Buffer)))
  1834. {
  1835. dwErr = GetLastError();
  1836. goto Ret;
  1837. }
  1838. if (NULL == (*phMemStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
  1839. 0, 0, 0, NULL)))
  1840. {
  1841. dwErr = GetLastError();
  1842. goto Ret;
  1843. }
  1844. // get the certs out of the system store and put them in the mem store
  1845. for(i=0;i<cHashCount;i++)
  1846. {
  1847. HashBlob.cbData = 20;
  1848. HashBlob.pbData = pHashes[i].rgb;
  1849. if (NULL == (pCertContext = CertFindCertificateInStore(hStore,
  1850. X509_ASN_ENCODING, CERT_FIND_SHA1_HASH,
  1851. 0, &HashBlob, NULL)))
  1852. {
  1853. dwErr = GetLastError();
  1854. goto Ret;
  1855. }
  1856. if (!CertAddCertificateContextToStore(*phMemStore, pCertContext,
  1857. CERT_STORE_ADD_USE_EXISTING, NULL))
  1858. {
  1859. dwErr = GetLastError();
  1860. goto Ret;
  1861. }
  1862. if (!CertFreeCertificateContext(pCertContext))
  1863. {
  1864. pCertContext = NULL;
  1865. dwErr = GetLastError();
  1866. goto Ret;
  1867. }
  1868. pCertContext = NULL;
  1869. }
  1870. Ret:
  1871. if (pCertContext)
  1872. CertFreeCertificateContext(pCertContext);
  1873. if (hStore)
  1874. CertCloseStore(hStore, 0);
  1875. return dwErr;
  1876. }
  1877. ULONG s_KeyrExportCert(
  1878. /* [in] */ handle_t hRPCBinding,
  1879. /* [in] */ KEYSVC_HANDLE hKeySvc,
  1880. /* [in] */ PKEYSVC_UNICODE_STRING pPassword,
  1881. /* [in] */ PKEYSVC_UNICODE_STRING pCertStore,
  1882. /* [in] */ ULONG cHashCount,
  1883. /* [size_is][in] */
  1884. KEYSVC_CERT_HASH *pHashes,
  1885. /* [in] */ ULONG ulFlags,
  1886. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  1887. /* [out] */ PKEYSVC_BLOB *ppPFXBlob)
  1888. {
  1889. HCERTSTORE hMemStore = 0;
  1890. KEYSVC_CONTEXT *pContext = NULL;
  1891. BOOL fImpersonated = FALSE;
  1892. CRYPT_DATA_BLOB PFXBlob;
  1893. DWORD dwStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  1894. DWORD dwErr = 0;
  1895. __try
  1896. {
  1897. memset(&PFXBlob, 0, sizeof(PFXBlob));
  1898. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  1899. goto Ret;
  1900. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  1901. goto Ret;
  1902. fImpersonated = TRUE;
  1903. // set the cert store information
  1904. if (KeySvcMachine == pContext->dwType)
  1905. {
  1906. dwStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  1907. }
  1908. // move the requested certs from the system store to a memory store
  1909. if (0 != (dwErr = MoveCertsFromSystemToMemStore(pCertStore, dwStoreFlags,
  1910. cHashCount, pHashes, &hMemStore)))
  1911. goto Ret;
  1912. if (!PFXExportCertStore(hMemStore, &PFXBlob, pPassword->Buffer, ulFlags))
  1913. {
  1914. dwErr = GetLastError();
  1915. goto Ret;
  1916. }
  1917. if (NULL == (PFXBlob.pbData = (BYTE*)MyAlloc(PFXBlob.cbData)))
  1918. {
  1919. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1920. goto Ret;
  1921. }
  1922. if (!PFXExportCertStore(hMemStore, &PFXBlob, pPassword->Buffer, ulFlags))
  1923. {
  1924. dwErr = GetLastError();
  1925. goto Ret;
  1926. }
  1927. // set up the blob for return through RPC
  1928. if (NULL == (*ppPFXBlob = (PKEYSVC_BLOB)MyAlloc(sizeof(KEYSVC_BLOB) +
  1929. PFXBlob.cbData)))
  1930. {
  1931. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1932. goto Ret;
  1933. }
  1934. (*ppPFXBlob)->cb = PFXBlob.cbData;
  1935. (*ppPFXBlob)->pb = (BYTE*)*ppPFXBlob + sizeof(KEYSVC_BLOB);
  1936. memcpy((*ppPFXBlob)->pb, PFXBlob.pbData, (*ppPFXBlob)->cb);
  1937. }
  1938. __except ( EXCEPTION_EXECUTE_HANDLER )
  1939. {
  1940. dwErr = ERROR_INVALID_PARAMETER;
  1941. goto Ret;
  1942. }
  1943. Ret:
  1944. __try
  1945. {
  1946. if (PFXBlob.pbData)
  1947. LocalFree(PFXBlob.pbData);
  1948. if (hMemStore)
  1949. CertCloseStore(hMemStore, 0);
  1950. if (fImpersonated)
  1951. KeySvrRevert(hRPCBinding, pContext);
  1952. if (pContext)
  1953. ReleaseContext(pContext);
  1954. }
  1955. __except ( EXCEPTION_EXECUTE_HANDLER )
  1956. {
  1957. dwErr = ERROR_INVALID_PARAMETER;
  1958. }
  1959. return dwErr;
  1960. }
  1961. DWORD MoveCertsFromMemToSystemStore(
  1962. PKEYSVC_UNICODE_STRING pCertStore,
  1963. DWORD dwStoreFlags,
  1964. HCERTSTORE hMemStore
  1965. )
  1966. {
  1967. DWORD i;
  1968. HCERTSTORE hStore = 0;
  1969. PCCERT_CONTEXT pCertContext = NULL;
  1970. PCCERT_CONTEXT pPrevCertContext = NULL;
  1971. DWORD dwErr = 0;
  1972. if (NULL == (hStore = CertOpenStore(sz_CERT_STORE_PROV_SYSTEM_W,
  1973. 0, 0, dwStoreFlags,
  1974. pCertStore->Buffer)))
  1975. {
  1976. dwErr = GetLastError();
  1977. goto Ret;
  1978. }
  1979. // get the certs out of the system store and put them in the mem store
  1980. for(i=0;;i++)
  1981. {
  1982. if (NULL == (pCertContext = CertEnumCertificatesInStore(hMemStore,
  1983. pPrevCertContext)))
  1984. {
  1985. pPrevCertContext = NULL;
  1986. if (CRYPT_E_NOT_FOUND != GetLastError())
  1987. {
  1988. dwErr = GetLastError();
  1989. goto Ret;
  1990. }
  1991. break;
  1992. }
  1993. pPrevCertContext = NULL;
  1994. if (!CertAddCertificateContextToStore(hStore, pCertContext,
  1995. CERT_STORE_ADD_USE_EXISTING, NULL))
  1996. {
  1997. dwErr = GetLastError();
  1998. goto Ret;
  1999. }
  2000. pPrevCertContext = pCertContext;
  2001. }
  2002. Ret:
  2003. if (pCertContext)
  2004. CertFreeCertificateContext(pCertContext);
  2005. if (hStore)
  2006. CertCloseStore(hStore, 0);
  2007. return dwErr;
  2008. }
  2009. ULONG s_KeyrImportCert(
  2010. /* [in] */ handle_t hRPCBinding,
  2011. /* [in] */ KEYSVC_HANDLE hKeySvc,
  2012. /* [in] */ PKEYSVC_UNICODE_STRING pPassword,
  2013. /* [in] */ KEYSVC_UNICODE_STRING *pCertStore,
  2014. /* [in] */ PKEYSVC_BLOB pPFXBlob,
  2015. /* [in] */ ULONG ulFlags,
  2016. /* [in, out] */ PKEYSVC_BLOB *ppReserved)
  2017. {
  2018. HCERTSTORE hMemStore = 0;
  2019. KEYSVC_CONTEXT *pContext = NULL;
  2020. BOOL fImpersonated = FALSE;
  2021. CRYPT_DATA_BLOB PFXBlob;
  2022. DWORD dwStoreFlags = CERT_SYSTEM_STORE_CURRENT_USER;
  2023. DWORD dwErr = 0;
  2024. __try
  2025. {
  2026. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  2027. goto Ret;
  2028. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  2029. goto Ret;
  2030. fImpersonated = TRUE;
  2031. // set the cert store information
  2032. if (KeySvcMachine == pContext->dwType)
  2033. {
  2034. dwStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  2035. }
  2036. PFXBlob.cbData = pPFXBlob->cb;
  2037. PFXBlob.pbData = pPFXBlob->pb;
  2038. if (NULL == (hMemStore = PFXImportCertStore(&PFXBlob, pPassword->Buffer,
  2039. ulFlags)))
  2040. {
  2041. dwErr = GetLastError();
  2042. goto Ret;
  2043. }
  2044. // open the specified store and transfer all the certs into it
  2045. dwErr = MoveCertsFromMemToSystemStore(pCertStore, dwStoreFlags, hMemStore);
  2046. }
  2047. __except ( EXCEPTION_EXECUTE_HANDLER )
  2048. {
  2049. dwErr = ERROR_INVALID_PARAMETER;
  2050. goto Ret;
  2051. }
  2052. Ret:
  2053. __try
  2054. {
  2055. if (hMemStore)
  2056. CertCloseStore(hMemStore, 0);
  2057. if (fImpersonated)
  2058. KeySvrRevert(hRPCBinding, pContext);
  2059. if (pContext)
  2060. ReleaseContext(pContext);
  2061. }
  2062. __except ( EXCEPTION_EXECUTE_HANDLER )
  2063. {
  2064. dwErr = ERROR_INVALID_PARAMETER;
  2065. }
  2066. return dwErr;
  2067. }
  2068. ULONG s_KeyrEnumerateAvailableCertTypes(
  2069. /* [in] */ handle_t hRPCBinding,
  2070. /* [in] */ KEYSVC_HANDLE hKeySvc,
  2071. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  2072. /* [out][in] */ ULONG *pcCertTypeCount,
  2073. /* [in, out][size_is(,*pcCertTypeCount)] */
  2074. PKEYSVC_UNICODE_STRING *ppCertTypes)
  2075. {
  2076. KEYSVC_CONTEXT *pContext = NULL;
  2077. BOOL fImpersonated = FALSE;
  2078. DWORD dwErr = E_UNEXPECTED;
  2079. HCERTTYPE hType = NULL;
  2080. DWORD cTypes = 0;
  2081. DWORD cTrustedTypes = 0;
  2082. DWORD i;
  2083. LPWSTR *awszTrustedTypes = NULL;
  2084. DWORD cbTrustedTypes = 0;
  2085. PKEYSVC_UNICODE_STRING awszResult = NULL;
  2086. LPWSTR wszCurrentName;
  2087. __try
  2088. {
  2089. *pcCertTypeCount = 0;
  2090. *ppCertTypes = NULL;
  2091. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  2092. goto Ret;
  2093. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  2094. goto Ret;
  2095. fImpersonated = TRUE;
  2096. dwErr = CAEnumCertTypes(CT_FIND_LOCAL_SYSTEM | CT_ENUM_MACHINE_TYPES, &hType);
  2097. if(dwErr != S_OK)
  2098. {
  2099. goto Ret;
  2100. }
  2101. cTypes = CACountCertTypes(hType);
  2102. awszTrustedTypes = (LPWSTR *)MyAlloc(sizeof(LPWSTR)*cTypes);
  2103. if(awszTrustedTypes == NULL)
  2104. {
  2105. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2106. goto Ret;
  2107. }
  2108. while(hType)
  2109. {
  2110. HCERTTYPE hNextType = NULL;
  2111. LPWSTR *awszTypeName = NULL;
  2112. dwErr = CAGetCertTypeProperty(hType, CERTTYPE_PROP_DN, &awszTypeName);
  2113. if((dwErr == S_OK) && (awszTypeName))
  2114. {
  2115. if(awszTypeName[0])
  2116. {
  2117. dwErr = CACertTypeAccessCheck(hType, NULL);
  2118. if(dwErr == S_OK)
  2119. {
  2120. awszTrustedTypes[cTrustedTypes] = (LPWSTR)MyAlloc((wcslen(awszTypeName[0])+1)*sizeof(WCHAR));
  2121. if(awszTrustedTypes[cTrustedTypes])
  2122. {
  2123. wcscpy(awszTrustedTypes[cTrustedTypes], awszTypeName[0]);
  2124. cbTrustedTypes += (wcslen(awszTypeName[0])+1)*sizeof(WCHAR);
  2125. cTrustedTypes++;
  2126. }
  2127. }
  2128. }
  2129. CAFreeCertTypeProperty(hType, awszTypeName);
  2130. }
  2131. dwErr = CAEnumNextCertType(hType, &hNextType);
  2132. if(dwErr != S_OK)
  2133. {
  2134. break;
  2135. }
  2136. CACloseCertType(hType);
  2137. hType = hNextType;
  2138. }
  2139. cbTrustedTypes += sizeof(KEYSVC_UNICODE_STRING)*cTrustedTypes;
  2140. awszResult = (PKEYSVC_UNICODE_STRING)MyAlloc(cbTrustedTypes);
  2141. if(awszResult == NULL)
  2142. {
  2143. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2144. goto Ret;
  2145. }
  2146. wszCurrentName = (LPWSTR)(&awszResult[cTrustedTypes]);
  2147. for(i=0; i < cTrustedTypes; i++)
  2148. {
  2149. wcscpy(wszCurrentName, awszTrustedTypes[i]);
  2150. awszResult[i].Length = (wcslen(awszTrustedTypes[i]) + 1)*sizeof(WCHAR);
  2151. awszResult[i].MaximumLength = awszResult[i].Length;
  2152. awszResult[i].Buffer = wszCurrentName;
  2153. wszCurrentName += wcslen(awszTrustedTypes[i]) + 1;
  2154. }
  2155. *pcCertTypeCount = cTrustedTypes;
  2156. *ppCertTypes = awszResult;
  2157. awszResult = NULL;
  2158. dwErr = ERROR_SUCCESS;
  2159. }
  2160. __except ( EXCEPTION_EXECUTE_HANDLER )
  2161. {
  2162. dwErr = _exception_code();
  2163. }
  2164. Ret:
  2165. __try
  2166. {
  2167. // free the list
  2168. if (fImpersonated)
  2169. KeySvrRevert(hRPCBinding, pContext);
  2170. if(awszTrustedTypes)
  2171. {
  2172. for(i=0; i < cTrustedTypes; i++)
  2173. {
  2174. if(awszTrustedTypes[i])
  2175. {
  2176. MyFree(awszTrustedTypes[i]);
  2177. }
  2178. }
  2179. MyFree(awszTrustedTypes);
  2180. }
  2181. if(awszResult)
  2182. {
  2183. MyFree(awszResult);
  2184. }
  2185. if (pContext)
  2186. ReleaseContext(pContext);
  2187. }
  2188. __except ( EXCEPTION_EXECUTE_HANDLER )
  2189. {
  2190. dwErr = ERROR_INVALID_PARAMETER;
  2191. }
  2192. return dwErr;
  2193. }
  2194. ULONG s_KeyrEnumerateCAs(
  2195. /* [in] */ handle_t hRPCBinding,
  2196. /* [in] */ KEYSVC_HANDLE hKeySvc,
  2197. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  2198. /* [in] */ ULONG ulFlags,
  2199. /* [out][in] */ ULONG *pcCACount,
  2200. /* [in, out][size_is(,*pcCACount)] */
  2201. PKEYSVC_UNICODE_STRING *ppCAs)
  2202. {
  2203. KEYSVC_CONTEXT *pContext = NULL;
  2204. BOOL fImpersonated = FALSE;
  2205. DWORD dwErr = E_UNEXPECTED;
  2206. HCAINFO hCA = NULL;
  2207. DWORD cCAs = 0;
  2208. DWORD cTrustedCAs = 0;
  2209. DWORD i;
  2210. LPWSTR *awszTrustedCAs = NULL;
  2211. DWORD cbTrustedCAs = 0;
  2212. PKEYSVC_UNICODE_STRING awszResult = NULL;
  2213. LPWSTR wszCurrentName;
  2214. __try
  2215. {
  2216. *pcCACount = 0;
  2217. *ppCAs = NULL;
  2218. if (NULL == (pContext = CheckKeySvcHandle(hKeySvc)))
  2219. goto Ret;
  2220. if (0 != (dwErr = KeySvrImpersonate(hRPCBinding, pContext)))
  2221. goto Ret;
  2222. fImpersonated = TRUE;
  2223. dwErr = CAEnumFirstCA(NULL, ulFlags, &hCA);
  2224. if(dwErr != S_OK)
  2225. {
  2226. goto Ret;
  2227. }
  2228. cCAs = CACountCAs(hCA);
  2229. awszTrustedCAs = (LPWSTR *)MyAlloc(sizeof(LPWSTR)*cCAs);
  2230. if(awszTrustedCAs == NULL)
  2231. {
  2232. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2233. goto Ret;
  2234. }
  2235. while(hCA)
  2236. {
  2237. HCAINFO hNextCA = NULL;
  2238. LPWSTR *awszCAName = NULL;
  2239. dwErr = CAGetCAProperty(hCA, CA_PROP_NAME, &awszCAName);
  2240. if((dwErr == S_OK) && (awszCAName))
  2241. {
  2242. if(awszCAName[0])
  2243. {
  2244. dwErr = CAAccessCheck(hCA, NULL);
  2245. if(dwErr == S_OK)
  2246. {
  2247. awszTrustedCAs[cTrustedCAs] = (LPWSTR)MyAlloc((wcslen(awszCAName[0])+1)*sizeof(WCHAR));
  2248. if(awszTrustedCAs[cTrustedCAs])
  2249. {
  2250. wcscpy(awszTrustedCAs[cTrustedCAs], awszCAName[0]);
  2251. cbTrustedCAs += (wcslen(awszCAName[0])+1)*sizeof(WCHAR);
  2252. cTrustedCAs++;
  2253. }
  2254. }
  2255. }
  2256. CAFreeCAProperty(hCA, awszCAName);
  2257. }
  2258. dwErr = CAEnumNextCA(hCA, &hNextCA);
  2259. if(dwErr != S_OK)
  2260. {
  2261. break;
  2262. }
  2263. CACloseCA(hCA);
  2264. hCA = hNextCA;
  2265. }
  2266. cbTrustedCAs += sizeof(KEYSVC_UNICODE_STRING)*cTrustedCAs;
  2267. awszResult = (PKEYSVC_UNICODE_STRING)MyAlloc(cbTrustedCAs);
  2268. if(awszResult == NULL)
  2269. {
  2270. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2271. goto Ret;
  2272. }
  2273. wszCurrentName = (LPWSTR)(&awszResult[cTrustedCAs]);
  2274. for(i=0; i < cTrustedCAs; i++)
  2275. {
  2276. wcscpy(wszCurrentName, awszTrustedCAs[i]);
  2277. awszResult[i].Length = (wcslen(awszTrustedCAs[i]) + 1)*sizeof(WCHAR);
  2278. awszResult[i].MaximumLength = awszResult[i].Length;
  2279. awszResult[i].Buffer = wszCurrentName;
  2280. wszCurrentName += wcslen(awszTrustedCAs[i]) + 1;
  2281. }
  2282. *pcCACount = cTrustedCAs;
  2283. *ppCAs = awszResult;
  2284. awszResult = NULL;
  2285. dwErr = ERROR_SUCCESS;
  2286. }
  2287. __except ( EXCEPTION_EXECUTE_HANDLER )
  2288. {
  2289. dwErr = _exception_code();
  2290. }
  2291. Ret:
  2292. __try
  2293. {
  2294. // free the list
  2295. if (fImpersonated)
  2296. KeySvrRevert(hRPCBinding, pContext);
  2297. if(awszTrustedCAs)
  2298. {
  2299. for(i=0; i < cTrustedCAs; i++)
  2300. {
  2301. if(awszTrustedCAs[i])
  2302. {
  2303. MyFree(awszTrustedCAs[i]);
  2304. }
  2305. }
  2306. MyFree(awszTrustedCAs);
  2307. }
  2308. if(awszResult)
  2309. {
  2310. MyFree(awszResult);
  2311. }
  2312. if (pContext)
  2313. ReleaseContext(pContext);
  2314. }
  2315. __except ( EXCEPTION_EXECUTE_HANDLER )
  2316. {
  2317. dwErr = ERROR_INVALID_PARAMETER;
  2318. }
  2319. return dwErr;
  2320. }
  2321. BOOL
  2322. GetTokenUserSid(
  2323. IN HANDLE hToken, // token to query
  2324. IN OUT PSID *ppUserSid // resultant user sid
  2325. )
  2326. /*++
  2327. This function queries the access token specified by the
  2328. hToken parameter, and returns an allocated copy of the
  2329. TokenUser information on success.
  2330. The access token specified by hToken must be opened for
  2331. TOKEN_QUERY access.
  2332. On success, the return value is TRUE. The caller is
  2333. responsible for freeing the resultant UserSid via a call
  2334. to MyFree().
  2335. On failure, the return value is FALSE. The caller does
  2336. not need to free any buffer.
  2337. --*/
  2338. {
  2339. BYTE FastBuffer[256];
  2340. LPBYTE SlowBuffer = NULL;
  2341. PTOKEN_USER ptgUser;
  2342. DWORD cbBuffer;
  2343. BOOL fSuccess = FALSE;
  2344. *ppUserSid = NULL;
  2345. //
  2346. // try querying based on a fast stack based buffer first.
  2347. //
  2348. ptgUser = (PTOKEN_USER)FastBuffer;
  2349. cbBuffer = sizeof(FastBuffer);
  2350. fSuccess = GetTokenInformation(
  2351. hToken, // identifies access token
  2352. TokenUser, // TokenUser info type
  2353. ptgUser, // retrieved info buffer
  2354. cbBuffer, // size of buffer passed-in
  2355. &cbBuffer // required buffer size
  2356. );
  2357. if(!fSuccess) {
  2358. if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  2359. //
  2360. // try again with the specified buffer size
  2361. //
  2362. SlowBuffer = (LPBYTE)MyAlloc(cbBuffer);
  2363. if(SlowBuffer != NULL) {
  2364. ptgUser = (PTOKEN_USER)SlowBuffer;
  2365. fSuccess = GetTokenInformation(
  2366. hToken, // identifies access token
  2367. TokenUser, // TokenUser info type
  2368. ptgUser, // retrieved info buffer
  2369. cbBuffer, // size of buffer passed-in
  2370. &cbBuffer // required buffer size
  2371. );
  2372. }
  2373. }
  2374. }
  2375. //
  2376. // if we got the token info successfully, copy the
  2377. // relevant element for the caller.
  2378. //
  2379. if(fSuccess) {
  2380. DWORD cbSid;
  2381. // reset to assume failure
  2382. fSuccess = FALSE;
  2383. cbSid = GetLengthSid(ptgUser->User.Sid);
  2384. *ppUserSid = MyAlloc( cbSid );
  2385. if(*ppUserSid != NULL) {
  2386. fSuccess = CopySid(cbSid, *ppUserSid, ptgUser->User.Sid);
  2387. }
  2388. }
  2389. if(!fSuccess) {
  2390. if(*ppUserSid) {
  2391. MyFree(*ppUserSid);
  2392. *ppUserSid = NULL;
  2393. }
  2394. }
  2395. if(SlowBuffer)
  2396. MyFree(SlowBuffer);
  2397. return fSuccess;
  2398. }
  2399. BOOL
  2400. GetUserTextualSid(
  2401. IN OUT LPWSTR lpBuffer,
  2402. IN OUT LPDWORD nSize
  2403. )
  2404. {
  2405. HANDLE hToken;
  2406. PSID pSidUser = NULL;
  2407. BOOL fSuccess = FALSE;
  2408. if(!OpenThreadToken(
  2409. GetCurrentThread(),
  2410. TOKEN_QUERY,
  2411. TRUE,
  2412. &hToken
  2413. ))
  2414. {
  2415. return FALSE;
  2416. }
  2417. fSuccess = GetTokenUserSid(hToken, &pSidUser);
  2418. if(fSuccess) {
  2419. //
  2420. // obtain the textual representaion of the Sid
  2421. //
  2422. fSuccess = GetTextualSid(
  2423. pSidUser, // user binary Sid
  2424. lpBuffer, // buffer for TextualSid
  2425. nSize // required/result buffer size in chars (including NULL)
  2426. );
  2427. }
  2428. if(pSidUser)
  2429. MyFree(pSidUser);
  2430. CloseHandle(hToken);
  2431. return fSuccess;
  2432. }
  2433. BOOL
  2434. GetTextualSid(
  2435. IN PSID pSid, // binary Sid
  2436. IN OUT LPWSTR TextualSid, // buffer for Textual representaion of Sid
  2437. IN OUT LPDWORD dwBufferLen // required/provided TextualSid buffersize
  2438. )
  2439. {
  2440. PSID_IDENTIFIER_AUTHORITY psia;
  2441. DWORD dwSubAuthorities;
  2442. DWORD dwCounter;
  2443. DWORD dwSidSize;
  2444. if(!IsValidSid(pSid)) return FALSE;
  2445. // obtain SidIdentifierAuthority
  2446. psia = GetSidIdentifierAuthority(pSid);
  2447. // obtain sidsubauthority count
  2448. dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
  2449. //
  2450. // compute buffer length (conservative guess)
  2451. // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
  2452. //
  2453. dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(WCHAR);
  2454. //
  2455. // check provided buffer length.
  2456. // If not large enough, indicate proper size and setlasterror
  2457. //
  2458. if(*dwBufferLen < dwSidSize) {
  2459. *dwBufferLen = dwSidSize;
  2460. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2461. return FALSE;
  2462. }
  2463. //
  2464. // prepare S-SID_REVISION-
  2465. //
  2466. dwSidSize = wsprintfW(TextualSid, L"S-%lu-", SID_REVISION );
  2467. //
  2468. // prepare SidIdentifierAuthority
  2469. //
  2470. if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
  2471. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  2472. L"0x%02hx%02hx%02hx%02hx%02hx%02hx",
  2473. (USHORT)psia->Value[0],
  2474. (USHORT)psia->Value[1],
  2475. (USHORT)psia->Value[2],
  2476. (USHORT)psia->Value[3],
  2477. (USHORT)psia->Value[4],
  2478. (USHORT)psia->Value[5]);
  2479. } else {
  2480. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  2481. L"%lu",
  2482. (ULONG)(psia->Value[5] ) +
  2483. (ULONG)(psia->Value[4] << 8) +
  2484. (ULONG)(psia->Value[3] << 16) +
  2485. (ULONG)(psia->Value[2] << 24) );
  2486. }
  2487. //
  2488. // loop through SidSubAuthorities
  2489. //
  2490. for (dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++) {
  2491. dwSidSize += wsprintfW(TextualSid + dwSidSize,
  2492. L"-%lu", *GetSidSubAuthority(pSid, dwCounter) );
  2493. }
  2494. *dwBufferLen = dwSidSize + 1; // tell caller how many chars (include NULL)
  2495. return TRUE;
  2496. }
  2497. void
  2498. InitLsaString(
  2499. PLSA_UNICODE_STRING LsaString,
  2500. LPWSTR String
  2501. )
  2502. {
  2503. DWORD StringLength;
  2504. if(String == NULL) {
  2505. LsaString->Buffer = NULL;
  2506. LsaString->Length = 0;
  2507. LsaString->MaximumLength = 0;
  2508. return;
  2509. }
  2510. StringLength = lstrlenW(String);
  2511. LsaString->Buffer = String;
  2512. LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
  2513. LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
  2514. }
  2515. ULONG s_KeyrEnroll_V2
  2516. (/* [in] */ handle_t hRPCBinding,
  2517. /* [in] */ BOOL fKeyService,
  2518. /* [in] */ ULONG ulPurpose,
  2519. /* [in] */ ULONG ulFlags,
  2520. /* [in] */ PKEYSVC_UNICODE_STRING pAcctName,
  2521. /* [in] */ PKEYSVC_UNICODE_STRING pCALocation,
  2522. /* [in] */ PKEYSVC_UNICODE_STRING pCAName,
  2523. /* [in] */ BOOL fNewKey,
  2524. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW_V2 pKeyNew,
  2525. /* [in] */ PKEYSVC_BLOB __RPC_FAR pCert,
  2526. /* [in] */ PKEYSVC_CERT_REQUEST_PVK_NEW_V2 pRenewKey,
  2527. /* [in] */ PKEYSVC_UNICODE_STRING pHashAlg,
  2528. /* [in] */ PKEYSVC_UNICODE_STRING pDesStore,
  2529. /* [in] */ ULONG ulStoreFlags,
  2530. /* [in] */ PKEYSVC_CERT_ENROLL_INFO pRequestInfo,
  2531. /* [in] */ ULONG ulReservedFlags,
  2532. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR *ppReserved,
  2533. /* [out][in] */ PKEYSVC_BLOB __RPC_FAR *ppRequest,
  2534. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppPKCS7Blob,
  2535. /* [out] */ PKEYSVC_BLOB __RPC_FAR *ppHashBlob,
  2536. /* [out] */ ULONG __RPC_FAR *pulStatus)
  2537. {
  2538. CERT_REQUEST_PVK_NEW KeyNew;
  2539. CERT_REQUEST_PVK_NEW RenewKey;
  2540. DWORD cbExtensions;
  2541. PBYTE pbExtensions = NULL;
  2542. PCERT_REQUEST_PVK_NEW pTmpRenewKey = NULL;
  2543. PCERT_REQUEST_PVK_NEW pTmpKeyNew = NULL;
  2544. LPWSTR pwszAcctName = NULL;
  2545. LPWSTR pwszProv = NULL;
  2546. LPWSTR pwszCont = NULL;
  2547. LPWSTR pwszRenewProv = NULL;
  2548. LPWSTR pwszRenewCont = NULL;
  2549. LPWSTR pwszDesStore = NULL;
  2550. LPWSTR pwszAttributes = NULL;
  2551. LPWSTR pwszFriendly = NULL;
  2552. LPWSTR pwszDescription = NULL;
  2553. LPWSTR pwszUsage = NULL;
  2554. LPWSTR pwszCALocation = NULL;
  2555. LPWSTR pwszCertDNName = NULL;
  2556. LPWSTR pwszCAName = NULL;
  2557. LPWSTR pwszHashAlg = NULL;
  2558. HANDLE hLogonToken = 0;
  2559. HANDLE hProfile = 0;
  2560. CERT_BLOB CertBlob;
  2561. CERT_BLOB *pCertBlob = NULL;
  2562. CERT_BLOB PKCS7Blob;
  2563. CERT_BLOB HashBlob;
  2564. CERT_ENROLL_INFO EnrollInfo;
  2565. DWORD dwErr = 0;
  2566. HANDLE hRequest = *ppRequest;
  2567. KEYSVC_BLOB ReservedBlob;
  2568. BOOL fCreateRequest = 0 == (ulFlags & (CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY));
  2569. BOOL fFreeRequest = 0 == (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY));
  2570. BOOL fSubmitRequest = 0 == (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_FREE_ONLY));
  2571. __try
  2572. {
  2573. //////////////////////////////////////////////////////////////
  2574. //
  2575. // INITIALIZATION:
  2576. //
  2577. //////////////////////////////////////////////////////////////
  2578. memset(&KeyNew, 0, sizeof(KeyNew));
  2579. memset(&RenewKey, 0, sizeof(RenewKey));
  2580. memset(&EnrollInfo, 0, sizeof(EnrollInfo));
  2581. memset(&PKCS7Blob, 0, sizeof(PKCS7Blob));
  2582. memset(&HashBlob, 0, sizeof(HashBlob));
  2583. memset(&CertBlob, 0, sizeof(CertBlob));
  2584. memset(&ReservedBlob, 0, sizeof(ReservedBlob));
  2585. *ppPKCS7Blob = NULL;
  2586. *ppHashBlob = NULL;
  2587. //////////////////////////////////////////////////////////////
  2588. //
  2589. // INPUT VALIDATION:
  2590. //
  2591. //////////////////////////////////////////////////////////////
  2592. BOOL fValidInput = TRUE;
  2593. fValidInput &= fCreateRequest || fSubmitRequest || fFreeRequest;
  2594. switch (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY))
  2595. {
  2596. case CRYPTUI_WIZ_CREATE_ONLY:
  2597. fValidInput &= NULL == *ppRequest;
  2598. break;
  2599. case CRYPTUI_WIZ_SUBMIT_ONLY:
  2600. case CRYPTUI_WIZ_FREE_ONLY:
  2601. fValidInput &= NULL != *ppRequest;
  2602. break;
  2603. case 0:
  2604. default:
  2605. ;
  2606. }
  2607. if (FALSE == fValidInput)
  2608. {
  2609. dwErr = ERROR_INVALID_PARAMETER;
  2610. goto Ret;
  2611. }
  2612. //////////////////////////////////////////////////////////////
  2613. //
  2614. // PROCEDURE BODY:
  2615. //
  2616. //////////////////////////////////////////////////////////////
  2617. // check if the client is an admin
  2618. if (0 != (dwErr = CheckIfAdmin(hRPCBinding)))
  2619. goto Ret;
  2620. // if enrolling for a service account then need to logon and load profile
  2621. if (0 != pAcctName->Length)
  2622. {
  2623. if (0 != (dwErr = AllocAndAssignString(pAcctName, &pwszAcctName)))
  2624. goto Ret;
  2625. if (0 != (dwErr = LogonToService(pwszAcctName, &hLogonToken,
  2626. &hProfile)))
  2627. goto Ret;
  2628. }
  2629. // assign all the values in the passed in structure to the
  2630. // temporary structure
  2631. KeyNew.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  2632. KeyNew.dwProvType = pKeyNew->ulProvType;
  2633. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->Provider,
  2634. &pwszProv)))
  2635. goto Ret;
  2636. KeyNew.pwszProvider = pwszProv;
  2637. KeyNew.dwProviderFlags = pKeyNew->ulProviderFlags;
  2638. if (0 != (dwErr = AllocAndAssignString(&pKeyNew->KeyContainer,
  2639. &pwszCont)))
  2640. goto Ret;
  2641. KeyNew.pwszKeyContainer = pwszCont;
  2642. KeyNew.dwKeySpec = pKeyNew->ulKeySpec;
  2643. KeyNew.dwGenKeyFlags = pKeyNew->ulGenKeyFlags;
  2644. KeyNew.dwEnrollmentFlags = pKeyNew->ulEnrollmentFlags;
  2645. KeyNew.dwSubjectNameFlags = pKeyNew->ulSubjectNameFlags;
  2646. KeyNew.dwPrivateKeyFlags = pKeyNew->ulPrivateKeyFlags;
  2647. KeyNew.dwGeneralFlags = pKeyNew->ulGeneralFlags;
  2648. pTmpKeyNew = &KeyNew;
  2649. if (pCert->cb)
  2650. {
  2651. // if necessary assign the cert to be renewed values
  2652. // temporary structure
  2653. CertBlob.cbData = pCert->cb;
  2654. CertBlob.pbData = pCert->pb;
  2655. pCertBlob = &CertBlob;
  2656. }
  2657. if (CRYPTUI_WIZ_CERT_RENEW == ulPurpose)
  2658. {
  2659. // assign all the values in the passed in structure to the
  2660. // temporary structure
  2661. RenewKey.dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  2662. RenewKey.dwProvType = pRenewKey->ulProvType;
  2663. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->Provider,
  2664. &pwszRenewProv)))
  2665. goto Ret;
  2666. RenewKey.pwszProvider = pwszRenewProv;
  2667. RenewKey.dwProviderFlags = pRenewKey->ulProviderFlags;
  2668. if (0 != (dwErr = AllocAndAssignString(&pRenewKey->KeyContainer,
  2669. &pwszRenewCont)))
  2670. goto Ret;
  2671. RenewKey.pwszKeyContainer = pwszRenewCont;
  2672. RenewKey.dwKeySpec = pRenewKey->ulKeySpec;
  2673. RenewKey.dwGenKeyFlags = pRenewKey->ulGenKeyFlags;
  2674. RenewKey.dwEnrollmentFlags = pRenewKey->ulEnrollmentFlags;
  2675. RenewKey.dwSubjectNameFlags = pRenewKey->ulSubjectNameFlags;
  2676. RenewKey.dwPrivateKeyFlags = pRenewKey->ulPrivateKeyFlags;
  2677. RenewKey.dwGeneralFlags = pRenewKey->ulGeneralFlags;
  2678. pTmpRenewKey = &RenewKey;
  2679. }
  2680. // For SUBMIT and FREE operations, hRequest is an IN parameter.
  2681. if (0 != ((CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY) & ulFlags))
  2682. {
  2683. memcpy(&hRequest, (*ppRequest)->pb, sizeof(hRequest));
  2684. }
  2685. // check if the destination cert store was passed in
  2686. if (0 != (dwErr = AllocAndAssignString(pDesStore, &pwszDesStore)))
  2687. goto Ret;
  2688. // copy over the request info
  2689. EnrollInfo.dwSize = sizeof(EnrollInfo);
  2690. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->UsageOID,
  2691. &pwszUsage)))
  2692. goto Ret;
  2693. EnrollInfo.pwszUsageOID = pwszUsage;
  2694. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->CertDNName,
  2695. &pwszCertDNName)))
  2696. goto Ret;
  2697. EnrollInfo.pwszCertDNName = pwszCertDNName;
  2698. // cast the cert extensions
  2699. EnrollInfo.dwExtensions = pRequestInfo->cExtensions;
  2700. cbExtensions = (sizeof(CERT_EXTENSIONS)+sizeof(PCERT_EXTENSIONS)) * pRequestInfo->cExtensions;
  2701. for (DWORD dwIndex = 0; dwIndex < pRequestInfo->cExtensions; dwIndex++)
  2702. {
  2703. cbExtensions += sizeof(CERT_EXTENSION) *
  2704. pRequestInfo->prgExtensions[dwIndex]->cExtension;
  2705. }
  2706. EnrollInfo.prgExtensions = (PCERT_EXTENSIONS *)MyAlloc(cbExtensions);
  2707. if (NULL == EnrollInfo.prgExtensions)
  2708. {
  2709. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2710. goto Ret;
  2711. }
  2712. pbExtensions = (PBYTE)(EnrollInfo.prgExtensions + EnrollInfo.dwExtensions);
  2713. for (DWORD dwIndex = 0; dwIndex < EnrollInfo.dwExtensions; dwIndex++)
  2714. {
  2715. EnrollInfo.prgExtensions[dwIndex] = (PCERT_EXTENSIONS)pbExtensions;
  2716. pbExtensions += sizeof(CERT_EXTENSIONS);
  2717. EnrollInfo.prgExtensions[dwIndex]->cExtension = pRequestInfo->prgExtensions[dwIndex]->cExtension;
  2718. EnrollInfo.prgExtensions[dwIndex]->rgExtension = (PCERT_EXTENSION)pbExtensions;
  2719. pbExtensions += sizeof(CERT_EXTENSION) * EnrollInfo.prgExtensions[dwIndex]->cExtension;
  2720. for (DWORD dwSubIndex = 0; dwSubIndex < EnrollInfo.prgExtensions[dwIndex]->cExtension; dwSubIndex++)
  2721. {
  2722. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId =
  2723. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pszObjId;
  2724. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical =
  2725. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].fCritical;
  2726. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.cbData =
  2727. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].cbData;
  2728. EnrollInfo.prgExtensions[dwIndex]->rgExtension[dwSubIndex].Value.pbData =
  2729. pRequestInfo->prgExtensions[dwIndex]->rgExtension[dwSubIndex].pbData;
  2730. }
  2731. }
  2732. EnrollInfo.dwPostOption = pRequestInfo->ulPostOption;
  2733. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->FriendlyName,
  2734. &pwszFriendly)))
  2735. goto Ret;
  2736. EnrollInfo.pwszFriendlyName = pwszFriendly;
  2737. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Description,
  2738. &pwszDescription)))
  2739. goto Ret;
  2740. EnrollInfo.pwszDescription = pwszDescription;
  2741. if (0 != (dwErr = AllocAndAssignString(&pRequestInfo->Attributes,
  2742. &pwszAttributes)))
  2743. goto Ret;
  2744. if (0 != (dwErr = AllocAndAssignString(pHashAlg,
  2745. &pwszHashAlg)))
  2746. goto Ret;
  2747. if (0 != (dwErr = AllocAndAssignString(pCALocation,
  2748. &pwszCALocation)))
  2749. goto Ret;
  2750. if (0 != (dwErr = AllocAndAssignString(pCAName,
  2751. &pwszCAName)))
  2752. goto Ret;
  2753. // call the local enrollment API
  2754. __try {
  2755. dwErr = LocalEnrollNoDS(ulFlags, pwszAttributes, NULL, fKeyService,
  2756. ulPurpose, FALSE, 0, NULL, 0, pwszCALocation,
  2757. pwszCAName, pCertBlob, pTmpRenewKey, fNewKey,
  2758. pTmpKeyNew, pwszHashAlg, pwszDesStore, ulStoreFlags,
  2759. &EnrollInfo, &PKCS7Blob, &HashBlob, pulStatus, &hRequest);
  2760. } __except( EXCEPTION_EXECUTE_HANDLER ) {
  2761. // TODO: convert to Winerror
  2762. dwErr = GetExceptionCode();
  2763. }
  2764. if( dwErr != 0 )
  2765. goto Ret;
  2766. // Assign OUT parameters based on what kind of request we've just made.
  2767. // Possible requests are:
  2768. //
  2769. // 1) CREATE only // Assign "ppRequest" to contain a HANDLE to the cert request.
  2770. // 2) SUBMIT only // Assign "ppPKCS7Blob" and "ppHashBlob" to the values returned from LocalEnrollNoDS()
  2771. // 3) FREE only // No need to assign OUT params.
  2772. // 4) Complete (all 3).
  2773. switch (ulFlags & (CRYPTUI_WIZ_CREATE_ONLY | CRYPTUI_WIZ_SUBMIT_ONLY | CRYPTUI_WIZ_FREE_ONLY))
  2774. {
  2775. case CRYPTUI_WIZ_CREATE_ONLY:
  2776. // We've done the request creation portion of a 3-stage request,
  2777. // assign the "request" out parameter now:
  2778. if (NULL == (*ppRequest = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB)+
  2779. sizeof(hRequest))))
  2780. {
  2781. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2782. goto Ret;
  2783. }
  2784. (*ppRequest)->cb = sizeof(hRequest);
  2785. (*ppRequest)->pb = (BYTE*)(*ppRequest) + sizeof(KEYSVC_BLOB);
  2786. memcpy((*ppRequest)->pb, &hRequest, sizeof(hRequest));
  2787. break;
  2788. case CRYPTUI_WIZ_SUBMIT_ONLY:
  2789. case 0:
  2790. // We've done the request submittal portion of a 3-stage request,
  2791. // or we've done a 1-stage request. Assign the "certificate" out parameters now:
  2792. // alloc and copy for the RPC out parameters
  2793. if (NULL == (*ppPKCS7Blob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  2794. PKCS7Blob.cbData)))
  2795. {
  2796. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2797. goto Ret;
  2798. }
  2799. (*ppPKCS7Blob)->cb = PKCS7Blob.cbData;
  2800. (*ppPKCS7Blob)->pb = (BYTE*)(*ppPKCS7Blob) + sizeof(KEYSVC_BLOB);
  2801. memcpy((*ppPKCS7Blob)->pb, PKCS7Blob.pbData, (*ppPKCS7Blob)->cb);
  2802. if (NULL == (*ppHashBlob = (KEYSVC_BLOB*)MyAlloc(sizeof(KEYSVC_BLOB) +
  2803. HashBlob.cbData)))
  2804. {
  2805. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  2806. goto Ret;
  2807. }
  2808. (*ppHashBlob)->cb = HashBlob.cbData;
  2809. (*ppHashBlob)->pb = (BYTE*)(*ppHashBlob) + sizeof(KEYSVC_BLOB);
  2810. memcpy((*ppHashBlob)->pb, HashBlob.pbData, (*ppHashBlob)->cb);
  2811. break;
  2812. case CRYPTUI_WIZ_FREE_ONLY:
  2813. default:
  2814. *ppRequest = NULL;
  2815. break;
  2816. }
  2817. }
  2818. __except ( EXCEPTION_EXECUTE_HANDLER )
  2819. {
  2820. dwErr = ERROR_INVALID_PARAMETER;
  2821. goto Ret;
  2822. }
  2823. Ret:
  2824. __try
  2825. {
  2826. if (pwszAcctName)
  2827. MyFree(pwszAcctName);
  2828. if (pwszProv)
  2829. MyFree(pwszProv);
  2830. if (pwszCont)
  2831. MyFree(pwszCont);
  2832. if (pwszRenewProv)
  2833. MyFree(pwszRenewProv);
  2834. if (pwszRenewCont)
  2835. MyFree(pwszRenewCont);
  2836. if (pwszDesStore)
  2837. MyFree(pwszDesStore);
  2838. if (pwszAttributes)
  2839. MyFree(pwszAttributes);
  2840. if (pwszFriendly)
  2841. MyFree(pwszFriendly);
  2842. if (pwszDescription)
  2843. MyFree(pwszDescription);
  2844. if (pwszUsage)
  2845. MyFree(pwszUsage);
  2846. if (pwszCertDNName)
  2847. MyFree(pwszCertDNName);
  2848. if (pwszCAName)
  2849. MyFree(pwszCAName);
  2850. if (pwszCALocation)
  2851. MyFree(pwszCALocation);
  2852. if (pwszHashAlg)
  2853. MyFree(pwszHashAlg);
  2854. if (PKCS7Blob.pbData)
  2855. {
  2856. MyFree(PKCS7Blob.pbData);
  2857. }
  2858. if (HashBlob.pbData)
  2859. {
  2860. MyFree(HashBlob.pbData);
  2861. }
  2862. if (hLogonToken || hProfile)
  2863. {
  2864. LogoffService(&hLogonToken, &hProfile);
  2865. }
  2866. if (EnrollInfo.prgExtensions)
  2867. MyFree(EnrollInfo.prgExtensions);
  2868. }
  2869. __except ( EXCEPTION_EXECUTE_HANDLER )
  2870. {
  2871. dwErr = ERROR_INVALID_PARAMETER;
  2872. }
  2873. return dwErr;
  2874. }
  2875. ULONG s_KeyrQueryRequestStatus
  2876. (/* [in] */ handle_t hRPCBinding,
  2877. /* [in] */ unsigned __int64 u64Request,
  2878. /* [out, ref] */ KEYSVC_QUERY_CERT_REQUEST_INFO *pQueryInfo)
  2879. {
  2880. CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO QueryInfo;
  2881. DWORD dwErr = 0;
  2882. HANDLE hRequest = (HANDLE)u64Request;
  2883. __try
  2884. {
  2885. // check if the client is an admin
  2886. if (0 != (dwErr = CheckIfAdmin(hRPCBinding)))
  2887. goto Ret;
  2888. // We have the permission necessary to query the request. Proceed.
  2889. ZeroMemory(&QueryInfo, sizeof(QueryInfo));
  2890. // Query the request.
  2891. dwErr = LocalEnrollNoDS(CRYPTUI_WIZ_QUERY_ONLY, NULL, &QueryInfo, FALSE, 0, FALSE, NULL, NULL,
  2892. 0, NULL, NULL, NULL, NULL, FALSE, NULL, NULL, NULL,
  2893. 0, NULL, NULL, NULL, NULL, &hRequest);
  2894. if (ERROR_SUCCESS != dwErr)
  2895. goto Ret;
  2896. }
  2897. __except ( EXCEPTION_EXECUTE_HANDLER )
  2898. {
  2899. dwErr = ERROR_INVALID_PARAMETER;
  2900. goto Ret;
  2901. }
  2902. pQueryInfo->ulSize = QueryInfo.dwSize;
  2903. pQueryInfo->ulStatus = QueryInfo.dwStatus;
  2904. Ret:
  2905. return dwErr;
  2906. }
  2907. ULONG s_RKeyrPFXInstall
  2908. (/* [in] */ handle_t hRPCBinding,
  2909. /* [in] */ PKEYSVC_BLOB pPFX,
  2910. /* [in] */ PKEYSVC_UNICODE_STRING pPassword,
  2911. /* [in] */ ULONG ulFlags)
  2912. {
  2913. BOOL fIsImpersonatingClient = FALSE;
  2914. CRYPT_DATA_BLOB PFXBlob;
  2915. DWORD dwCertOpenStoreFlags;
  2916. DWORD dwData;
  2917. DWORD dwResult;
  2918. HCERTSTORE hSrcStore = NULL;
  2919. HCERTSTORE hCAStore = NULL;
  2920. HCERTSTORE hMyStore = NULL;
  2921. HCERTSTORE hRootStore = NULL;
  2922. LPWSTR pwszPassword = NULL;
  2923. PCCERT_CONTEXT pCertContext = NULL;
  2924. struct Stores {
  2925. HANDLE *phStore;
  2926. LPCWSTR pwszStoreName;
  2927. } rgStores[] = {
  2928. { &hMyStore, L"my" },
  2929. { &hCAStore, L"ca" },
  2930. { &hRootStore, L"root" }
  2931. };
  2932. __try
  2933. {
  2934. // Initialize locals:
  2935. PFXBlob.cbData = pPFX->cb;
  2936. PFXBlob.pbData = pPFX->pb;
  2937. switch (ulFlags & (CRYPT_MACHINE_KEYSET | CRYPT_USER_KEYSET))
  2938. {
  2939. case CRYPT_MACHINE_KEYSET:
  2940. dwCertOpenStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  2941. break;
  2942. case CRYPT_USER_KEYSET: // not supported
  2943. default:
  2944. dwResult = ERROR_INVALID_PARAMETER;
  2945. goto error;
  2946. }
  2947. dwResult = RpcImpersonateClient(hRPCBinding);
  2948. if (RPC_S_OK != dwResult)
  2949. goto error;
  2950. fIsImpersonatingClient = TRUE;
  2951. if (ERROR_SUCCESS != (dwResult = AllocAndAssignString((PKEYSVC_UNICODE_STRING)pPassword, &pwszPassword)))
  2952. goto error;
  2953. // Get an in-memory store which contains all of the certs in the PFX
  2954. // blob.
  2955. if (NULL == (hSrcStore = PFXImportCertStore(&PFXBlob, pwszPassword, ulFlags)))
  2956. {
  2957. dwResult = GetLastError();
  2958. goto error;
  2959. }
  2960. // Open the stores we'll need:
  2961. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStores); dwIndex++)
  2962. {
  2963. *(rgStores[dwIndex].phStore) = CertOpenStore
  2964. (CERT_STORE_PROV_SYSTEM_W, // store provider type
  2965. PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, // cert encoding type
  2966. NULL, // hCryptProv
  2967. dwCertOpenStoreFlags, // open store flags
  2968. rgStores[dwIndex].pwszStoreName // store name
  2969. );
  2970. if (NULL == *(rgStores[dwIndex].phStore))
  2971. {
  2972. dwResult = GetLastError();
  2973. goto error;
  2974. }
  2975. }
  2976. // Enumerate the certs in the in-memory store, and add them to the local machine's
  2977. // "my" store. NOTE: CertEnumCertificatesInStore frees the previous cert context
  2978. // before returning the new context.
  2979. while (NULL != (pCertContext = CertEnumCertificatesInStore(hSrcStore, pCertContext)))
  2980. {
  2981. HCERTSTORE hCertStore;
  2982. // check if the certificate has the property on it
  2983. // make sure the private key matches the certificate
  2984. // search for both machine key and user keys
  2985. if (CertGetCertificateContextProperty
  2986. (pCertContext,
  2987. CERT_KEY_PROV_INFO_PROP_ID,
  2988. NULL,
  2989. &dwData) &&
  2990. CryptFindCertificateKeyProvInfo
  2991. (pCertContext,
  2992. 0,
  2993. NULL))
  2994. {
  2995. hCertStore = hMyStore;
  2996. }
  2997. else if (TrustIsCertificateSelfSigned
  2998. (pCertContext,
  2999. pCertContext->dwCertEncodingType,
  3000. 0))
  3001. {
  3002. hCertStore = hRootStore;
  3003. }
  3004. else
  3005. {
  3006. hCertStore = hCAStore;
  3007. }
  3008. if (!CertAddCertificateContextToStore
  3009. (hCertStore,
  3010. pCertContext,
  3011. CERT_STORE_ADD_NEW,
  3012. NULL))
  3013. {
  3014. dwResult = GetLastError();
  3015. goto error;
  3016. }
  3017. }
  3018. }
  3019. __except (EXCEPTION_EXECUTE_HANDLER)
  3020. {
  3021. dwResult = GetExceptionCode();
  3022. goto error;
  3023. }
  3024. // We're done!
  3025. dwResult = ERROR_SUCCESS;
  3026. error:
  3027. if (fIsImpersonatingClient) { RpcRevertToSelfEx(hRPCBinding); }
  3028. if (NULL != hSrcStore) { CertCloseStore(hSrcStore, 0); }
  3029. // Close all of the destination stores we've opened.
  3030. for (DWORD dwIndex = 0; dwIndex < ARRAYSIZE(rgStores); dwIndex++)
  3031. if (NULL != *(rgStores[dwIndex].phStore))
  3032. CertCloseStore(*(rgStores[dwIndex].phStore), 0);
  3033. if (NULL != pwszPassword) { MyFree(pwszPassword); }
  3034. if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
  3035. return dwResult;
  3036. }
  3037. ULONG s_RKeyrOpenKeyService(
  3038. /* [in] */ handle_t hRPCBinding,
  3039. /* [in] */ KEYSVC_TYPE OwnerType,
  3040. /* [in] */ PKEYSVC_UNICODE_STRING pOwnerName,
  3041. /* [in] */ ULONG ulDesiredAccess,
  3042. /* [in] */ PKEYSVC_BLOB pAuthentication,
  3043. /* [in, out] */ PKEYSVC_BLOB *ppReserved,
  3044. /* [out] */ KEYSVC_HANDLE *phKeySvc)
  3045. {
  3046. return s_KeyrOpenKeyService
  3047. (hRPCBinding,
  3048. OwnerType,
  3049. pOwnerName,
  3050. ulDesiredAccess,
  3051. pAuthentication,
  3052. ppReserved,
  3053. phKeySvc);
  3054. }
  3055. ULONG s_RKeyrCloseKeyService(
  3056. /* [in] */ handle_t hRPCBinding,
  3057. /* [in] */ KEYSVC_HANDLE hKeySvc,
  3058. /* [in, out] */ PKEYSVC_BLOB *ppReserved)
  3059. {
  3060. return s_KeyrCloseKeyService
  3061. (hRPCBinding,
  3062. hKeySvc,
  3063. ppReserved);
  3064. }