Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1762 lines
49 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1999
  3. Module Name:
  4. ScLogon2
  5. Abstract:
  6. Author:
  7. reidk
  8. Environment:
  9. Win32, C++ w/ Exceptions
  10. --*/
  11. /////////////////////////////////////////////////////////////////////////////
  12. //
  13. // Includes
  14. #if !defined(_X86_) && !defined(_AMD64_) && !defined(_IA64_)
  15. #define _X86_ 1
  16. #endif
  17. #ifndef _WIN32_WINNT
  18. #define _WIN32_WINNT 0x0400
  19. #ifndef UNICODE
  20. #define UNICODE
  21. #endif
  22. #endif
  23. #ifndef WIN32_LEAN_AND_MEAN
  24. #define WIN32_LEAN_AND_MEAN 1
  25. #endif
  26. extern "C" {
  27. #include <nt.h>
  28. #include <ntrtl.h>
  29. #include <nturtl.h>
  30. #include <ntlsa.h>
  31. }
  32. #include <windows.h>
  33. #include <winscard.h>
  34. #include <wincrypt.h>
  35. #include <softpub.h>
  36. #include <stddef.h>
  37. #include <crtdbg.h>
  38. #include "sclogon.h"
  39. #include "sclogon2.h"
  40. #include "unicodes.h"
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <time.h>
  44. #include <tchar.h>
  45. #include "sclgnrpc.h"
  46. typedef struct _KERB_PUBLIC_KEY_HPROV {
  47. RPC_BINDING_HANDLE hRPCBinding;
  48. BINDING_CONTEXT hCertAndKey;
  49. } KERB_PUBLIC_KEY_HPROV, *PKERB_PUBLIC_KEY_HPROV;
  50. //
  51. // from secpkg.h
  52. //
  53. typedef NTSTATUS (NTAPI LSA_IMPERSONATE_CLIENT) (VOID);
  54. typedef LSA_IMPERSONATE_CLIENT * PLSA_IMPERSONATE_CLIENT;
  55. bool
  56. GetImpersonationToken(HANDLE *phThreadToken)
  57. {
  58. bool ret = false;
  59. //
  60. // This will fail if not impersonating.
  61. //
  62. if (OpenThreadToken(
  63. GetCurrentThread(),
  64. TOKEN_IMPERSONATE | TOKEN_QUERY,
  65. TRUE,
  66. phThreadToken))
  67. {
  68. ret = true;
  69. }
  70. else if (GetLastError() == ERROR_NO_TOKEN)
  71. {
  72. ret = true;
  73. }
  74. else
  75. {
  76. DbgPrint("OpenThreadToken failed - %lx\n", GetLastError());
  77. }
  78. return (ret);
  79. }
  80. DWORD
  81. GetTSSessionID(HANDLE hThreadToken)
  82. {
  83. bool fRet = false;
  84. PLIST_ENTRY Module;
  85. PLDR_DATA_TABLE_ENTRY Entry;
  86. BOOL fRunningInLsa = false;
  87. HMODULE hLsa = NULL;
  88. PLSA_IMPERSONATE_CLIENT pLsaImpersonateClient = NULL;
  89. bool bImpersonating = false;
  90. HANDLE hLocalThreadToken = INVALID_HANDLE_VALUE;
  91. DWORD dwTSSessionID = 0;
  92. DWORD dwSize;
  93. bool fAlreadyImpersonating;
  94. //
  95. // Make sure we are running in LSA
  96. //
  97. Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
  98. Entry = CONTAINING_RECORD(Module,
  99. LDR_DATA_TABLE_ENTRY,
  100. InLoadOrderLinks);
  101. fRunningInLsa = (0 == _wcsicmp(Entry->BaseDllName.Buffer, L"lsass.exe"));
  102. if (!fRunningInLsa)
  103. {
  104. return (0);
  105. }
  106. //
  107. // Check to see if we are already impersonating by checking the thread token passed in
  108. //
  109. if(hThreadToken == INVALID_HANDLE_VALUE)
  110. {
  111. //
  112. // If we aren't already impernonating, then we need to call the special LssImpersonateClient
  113. //
  114. hLsa = GetModuleHandleW(L"lsasrv.dll");
  115. if (hLsa == NULL)
  116. {
  117. DbgPrint("failed to get lsa module handle\n");
  118. goto Return;
  119. }
  120. pLsaImpersonateClient = (PLSA_IMPERSONATE_CLIENT) GetProcAddress(hLsa, "LsaIImpersonateClient");
  121. if (pLsaImpersonateClient == NULL)
  122. {
  123. DbgPrint("failed to get proc address\n");
  124. goto Return;
  125. }
  126. if (pLsaImpersonateClient() != STATUS_SUCCESS)
  127. {
  128. DbgPrint("failed to impersonate\n");
  129. goto Return;
  130. }
  131. bImpersonating = true;
  132. if (!OpenThreadToken(
  133. GetCurrentThread(),
  134. TOKEN_QUERY,
  135. FALSE,
  136. &hLocalThreadToken))
  137. {
  138. DbgPrint("OpenThreadToken failed\n");
  139. goto Return;
  140. }
  141. }
  142. //
  143. // see if the calling thread token has a TS session ID...
  144. // if so, then we are being called on behalf of a process in a TS session
  145. //
  146. if (!GetTokenInformation(
  147. (hThreadToken == INVALID_HANDLE_VALUE) ? hLocalThreadToken : hThreadToken,
  148. TokenSessionId,
  149. &dwTSSessionID,
  150. sizeof(dwTSSessionID),
  151. &dwSize))
  152. {
  153. DbgPrint("GetTokenInformation failed\n");
  154. }
  155. Return:
  156. if (hLocalThreadToken != INVALID_HANDLE_VALUE)
  157. {
  158. CloseHandle(hLocalThreadToken);
  159. }
  160. if (bImpersonating)
  161. {
  162. RevertToSelf();
  163. }
  164. return (dwTSSessionID);
  165. }
  166. void
  167. _TeardownRPCConnection(
  168. RPC_BINDING_HANDLE *phRPCBinding)
  169. {
  170. __try
  171. {
  172. RpcBindingFree(phRPCBinding);
  173. }
  174. __except (EXCEPTION_EXECUTE_HANDLER)
  175. {
  176. DbgPrint("Exception occurred during RpcBindingFree - %lx\n", _exception_code());
  177. }
  178. }
  179. NTSTATUS
  180. _SetupRPCConnection(
  181. RPC_BINDING_HANDLE *phRPCBinding,
  182. HANDLE hThreadToken)
  183. {
  184. LPWSTR pStringBinding = NULL;
  185. NTSTATUS status = STATUS_SUCCESS;
  186. RPC_STATUS rpcStatus = RPC_S_OK;
  187. DWORD dwTSSessionID = 0;
  188. WCHAR wszLocalEndpoint[256];
  189. LPWSTR pwszLocalEndpoint = NULL;
  190. RPC_SECURITY_QOS RpcSecurityQOS;
  191. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  192. PSID pSID = NULL;
  193. WCHAR szName[64]; // SYSTEM
  194. DWORD cbName = 64;
  195. WCHAR szDomainName[256]; // max domain is 255
  196. DWORD cbDomainName = 256;
  197. SID_NAME_USE Use;
  198. //
  199. // Get the ID of the winlogon RPC server to connect to
  200. //
  201. dwTSSessionID = GetTSSessionID(hThreadToken);
  202. if (dwTSSessionID != 0)
  203. {
  204. wsprintfW(
  205. wszLocalEndpoint,
  206. SZ_ENDPOINT_NAME_FORMAT,
  207. SCLOGONRPC_LOCAL_ENDPOINT,
  208. dwTSSessionID);
  209. pwszLocalEndpoint = wszLocalEndpoint;
  210. }
  211. else
  212. {
  213. pwszLocalEndpoint = SCLOGONRPC_LOCAL_ENDPOINT;
  214. }
  215. //
  216. // get a binding handle
  217. //
  218. if (RPC_S_OK != (rpcStatus = RpcStringBindingComposeW(
  219. NULL,
  220. SCLOGONRPC_LOCAL_PROT_SEQ,
  221. NULL, //LPC - no machine name
  222. pwszLocalEndpoint,
  223. 0,
  224. &pStringBinding)))
  225. {
  226. DbgPrint("RpcStringBindingComposeW failed\n");
  227. status = I_RpcMapWin32Status(rpcStatus);
  228. //
  229. // if I_RpcMapWin32Status() can't map the error code it returns
  230. // the same error back, so check for that
  231. //
  232. if (status == rpcStatus)
  233. {
  234. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  235. }
  236. goto Return;
  237. }
  238. if (RPC_S_OK != (rpcStatus = RpcBindingFromStringBindingW(
  239. pStringBinding,
  240. phRPCBinding)))
  241. {
  242. DbgPrint("RpcBindingFromStringBindingW failed\n");
  243. status = I_RpcMapWin32Status(rpcStatus);
  244. //
  245. // if I_RpcMapWin32Status() can't map the error code it returns
  246. // the same error back, so check for that
  247. //
  248. if (status == rpcStatus)
  249. {
  250. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  251. }
  252. goto Return;
  253. }
  254. if (RPC_S_OK != (rpcStatus = RpcEpResolveBinding(
  255. *phRPCBinding,
  256. IRPCSCLogon_v1_0_c_ifspec)))
  257. {
  258. DbgPrint("RpcEpResolveBinding failed\n");
  259. status = I_RpcMapWin32Status(rpcStatus);
  260. //
  261. // if I_RpcMapWin32Status() can't map the error code it returns
  262. // the same error back, so check for that
  263. //
  264. if (status == rpcStatus)
  265. {
  266. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  267. }
  268. _TeardownRPCConnection(phRPCBinding);
  269. goto Return;
  270. }
  271. //
  272. // Set the autorization so that we will only call a Local System process
  273. //
  274. memset(&RpcSecurityQOS, 0, sizeof(RpcSecurityQOS));
  275. RpcSecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
  276. RpcSecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  277. RpcSecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  278. RpcSecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_DELEGATE;
  279. if (AllocateAndInitializeSid(&SIDAuth, 1,
  280. SECURITY_LOCAL_SYSTEM_RID,
  281. 0, 0, 0, 0, 0, 0, 0,
  282. &pSID) == 0)
  283. {
  284. DbgPrint("AllocateAndInitializeSid failed\n");
  285. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  286. goto Return;
  287. }
  288. if (LookupAccountSid(NULL,
  289. pSID,
  290. szName,
  291. &cbName,
  292. szDomainName,
  293. &cbDomainName,
  294. &Use) == 0)
  295. {
  296. DbgPrint("LookupAccountSid failed\n");
  297. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  298. goto Return;
  299. }
  300. if (RPC_S_OK != (rpcStatus = RpcBindingSetAuthInfoEx(
  301. *phRPCBinding,
  302. szName,
  303. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  304. RPC_C_AUTHN_WINNT,
  305. NULL,
  306. 0,
  307. &RpcSecurityQOS)))
  308. {
  309. DbgPrint("RpcBindingSetAuthInfoEx failed\n");
  310. status = I_RpcMapWin32Status(rpcStatus);
  311. goto Return;
  312. }
  313. Return:
  314. if (pStringBinding != NULL)
  315. {
  316. RpcStringFreeW(&pStringBinding);
  317. }
  318. if (pSID != NULL)
  319. {
  320. FreeSid( pSID );
  321. }
  322. return (status);
  323. }
  324. typedef struct _SCLOGON_PIPE
  325. {
  326. RPC_BINDING_HANDLE hRPCBinding;
  327. BINDING_CONTEXT BindingContext;
  328. } SCLOGON_PIPE;
  329. ///////////////////////////////////////////////////////////////////////////////
  330. //
  331. // ScLogon APIs
  332. //
  333. //***************************************************************************************
  334. //
  335. // __ScHelperInitializeContext:
  336. //
  337. //***************************************************************************************
  338. NTSTATUS WINAPI
  339. __ScHelperInitializeContext(
  340. IN OUT PBYTE pbLogonInfo,
  341. IN ULONG cbLogonInfo
  342. )
  343. {
  344. SCLOGON_PIPE *pSCLogonPipe;
  345. NTSTATUS status = STATUS_SUCCESS;
  346. BOOL fRPCBindingInitialized = FALSE;
  347. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  348. if ((cbLogonInfo < sizeof(ULONG)) ||
  349. (cbLogonInfo != pLI->dwLogonInfoLen))
  350. {
  351. return(STATUS_INVALID_PARAMETER);
  352. }
  353. pLI->ContextInformation = malloc(sizeof(SCLOGON_PIPE));
  354. if (pLI->ContextInformation == NULL)
  355. {
  356. return(STATUS_INSUFFICIENT_RESOURCES);
  357. }
  358. pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  359. status = _SetupRPCConnection(&(pSCLogonPipe->hRPCBinding), INVALID_HANDLE_VALUE);
  360. if (!NT_SUCCESS(status))
  361. {
  362. goto ErrorReturn;
  363. }
  364. fRPCBindingInitialized = TRUE;
  365. pSCLogonPipe->BindingContext = NULL;
  366. __try
  367. {
  368. status = RPC_ScHelperInitializeContext(
  369. pSCLogonPipe->hRPCBinding,
  370. cbLogonInfo,
  371. pbLogonInfo,
  372. &(pSCLogonPipe->BindingContext));
  373. }
  374. __except (EXCEPTION_EXECUTE_HANDLER)
  375. {
  376. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  377. DbgPrint("Exception occurred during RPC_ScHelperInitializeContext - %lx\n", _exception_code());
  378. }
  379. if (!NT_SUCCESS(status))
  380. {
  381. DbgPrint("RPC_ScHelperInitializeContext failed - %lx\n", status);
  382. goto ErrorReturn;
  383. }
  384. Return:
  385. return (status);
  386. ErrorReturn:
  387. if (pSCLogonPipe != NULL)
  388. {
  389. if (fRPCBindingInitialized)
  390. {
  391. _TeardownRPCConnection(&(pSCLogonPipe->hRPCBinding));
  392. }
  393. free(pSCLogonPipe);
  394. }
  395. goto Return;
  396. }
  397. //***************************************************************************************
  398. //
  399. // __ScHelperRelease:
  400. //
  401. //***************************************************************************************
  402. VOID WINAPI
  403. __ScHelperRelease(
  404. IN OUT PBYTE pbLogonInfo
  405. )
  406. {
  407. _ASSERTE(NULL != pbLogonInfo);
  408. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  409. SCLOGON_PIPE * pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  410. BOOL fReleaseFailed = TRUE;
  411. if (pSCLogonPipe != NULL)
  412. {
  413. __try
  414. {
  415. RPC_ScHelperRelease(
  416. pSCLogonPipe->hRPCBinding,
  417. &(pSCLogonPipe->BindingContext));
  418. fReleaseFailed = FALSE;
  419. }
  420. __except (EXCEPTION_EXECUTE_HANDLER)
  421. {
  422. DbgPrint("Exception occurred during RPC_ScHelperRelease - %lx\n", _exception_code());
  423. }
  424. //
  425. // RPC_ScHelperRelease will throw an exception if the winlogon process it is trying
  426. // to talk to has gone away. If that is the case, then we need to manually free
  427. // the BINDING_CONTEXT since it won't get free'd by RPC.
  428. //
  429. // NOTE: RPC will free the BINDING_CONTEXT when the server sets it to NULL, which
  430. // does happen if the RPC_ScHelperRelease function executes
  431. //
  432. if (fReleaseFailed)
  433. {
  434. __try
  435. {
  436. RpcSsDestroyClientContext(&(pSCLogonPipe->BindingContext));
  437. }
  438. __except (EXCEPTION_EXECUTE_HANDLER)
  439. {
  440. DbgPrint("Exception occurred during RpcSsDestroyClientContext - %lx\n", _exception_code());
  441. }
  442. }
  443. _TeardownRPCConnection(&(pSCLogonPipe->hRPCBinding));
  444. free(pSCLogonPipe);
  445. pLI->ContextInformation = NULL;
  446. }
  447. }
  448. //***************************************************************************************
  449. //
  450. // __ScHelperGetCertFromLogonInfo:
  451. //
  452. //***************************************************************************************
  453. NTSTATUS WINAPI
  454. __ScHelperGetCertFromLogonInfo(
  455. IN PBYTE pbLogonInfo,
  456. IN PUNICODE_STRING pucPIN,
  457. OUT PCCERT_CONTEXT *CertificateContext
  458. )
  459. {
  460. _ASSERTE(NULL != pbLogonInfo);
  461. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  462. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  463. NTSTATUS status = STATUS_SUCCESS;
  464. PCCERT_CONTEXT pCertCtx = NULL;
  465. OUT_BUFFER1 CertBytes;
  466. CUnicodeString szPIN(pucPIN);
  467. memset(&CertBytes, 0, sizeof(CertBytes));
  468. //
  469. // Make sure pin got initialized correctly in constructor
  470. //
  471. if (NULL != pucPIN)
  472. {
  473. if (!szPIN.Valid())
  474. {
  475. status = STATUS_INSUFFICIENT_RESOURCES;
  476. goto Return;
  477. }
  478. }
  479. //
  480. // Make the call
  481. //
  482. __try
  483. {
  484. status = RPC_ScHelperGetCertFromLogonInfo(
  485. pSCLogonPipe->hRPCBinding,
  486. pSCLogonPipe->BindingContext,
  487. (LPCWSTR)szPIN,
  488. &CertBytes);
  489. }
  490. __except (EXCEPTION_EXECUTE_HANDLER)
  491. {
  492. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  493. DbgPrint("Exception occurred during RPC_ScHelperGetCertFromLogonInfo - %lx\n", _exception_code());
  494. }
  495. if (!NT_SUCCESS(status))
  496. {
  497. DbgPrint("RPC_ScHelperGetCertFromLogonInfo failed - %lx\n", status);
  498. goto Return;
  499. }
  500. //
  501. // Create the return CertContext based on the bytes returned
  502. //
  503. pCertCtx = CertCreateCertificateContext(
  504. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  505. CertBytes.pb,
  506. CertBytes.cb);
  507. if (pCertCtx == NULL)
  508. {
  509. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  510. }
  511. Return:
  512. if (CertBytes.pb != NULL)
  513. {
  514. MIDL_user_free(CertBytes.pb);
  515. }
  516. *CertificateContext = pCertCtx;
  517. return (status);
  518. }
  519. //***************************************************************************************
  520. //
  521. // __ScHelperGetProvParam:
  522. //
  523. //***************************************************************************************
  524. NTSTATUS WINAPI
  525. __ScHelperGetProvParam(
  526. IN PUNICODE_STRING pucPIN,
  527. IN PBYTE pbLogonInfo,
  528. IN ULONG_PTR KerbHProv,
  529. DWORD dwParam,
  530. BYTE *pbData,
  531. DWORD *pdwDataLen,
  532. DWORD dwFlags
  533. )
  534. {
  535. _ASSERTE(NULL != pbLogonInfo);
  536. LogonInfo *pLI;
  537. SCLOGON_PIPE *pSCLogonPipe;
  538. NTSTATUS status = STATUS_SUCCESS;
  539. CUnicodeString szPIN(pucPIN);
  540. OUT_BUFFER1 Data;
  541. PKERB_PUBLIC_KEY_HPROV pKerbHProv;
  542. handle_t hRPCBinding;
  543. BINDING_CONTEXT BindingContext;
  544. BOOL fBindingIsCertAndKey = FALSE;
  545. //
  546. // Decide which rpc binding to use
  547. //
  548. if (KerbHProv != NULL)
  549. {
  550. pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  551. hRPCBinding = pKerbHProv->hRPCBinding;
  552. BindingContext = pKerbHProv->hCertAndKey;
  553. fBindingIsCertAndKey = TRUE;
  554. }
  555. else
  556. {
  557. pLI = (LogonInfo *)pbLogonInfo;
  558. pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  559. hRPCBinding = pSCLogonPipe->hRPCBinding;
  560. BindingContext = pSCLogonPipe->BindingContext;
  561. }
  562. memset(&Data, 0, sizeof(Data));
  563. //
  564. // Make sure pin got initialized correctly in constructor
  565. //
  566. if (NULL != pucPIN)
  567. {
  568. if (!szPIN.Valid())
  569. {
  570. status = STATUS_INSUFFICIENT_RESOURCES;
  571. goto Return;
  572. }
  573. }
  574. //
  575. // Make the call
  576. //
  577. __try
  578. {
  579. status = RPC_ScHelperGetProvParam(
  580. hRPCBinding,
  581. BindingContext,
  582. (LPCWSTR)szPIN,
  583. fBindingIsCertAndKey,
  584. dwParam,
  585. pdwDataLen,
  586. &Data,
  587. dwFlags);
  588. }
  589. __except (EXCEPTION_EXECUTE_HANDLER)
  590. {
  591. if ((_exception_code() == RPC_S_CALL_FAILED_DNE) ||
  592. (_exception_code() == RPC_S_SERVER_UNAVAILABLE))
  593. {
  594. // Special case to trigger the balloon when the session
  595. // went away (transfer of credentials case)
  596. status = STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED;
  597. }
  598. else
  599. {
  600. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  601. }
  602. DbgPrint("Exception occurred during RPC_ScHelperGetProvParam - %lx\n", _exception_code());
  603. }
  604. if (!NT_SUCCESS(status))
  605. {
  606. DbgPrint("RPC_ScHelperGetProvParam failed - %lx\n", status);
  607. goto Return;
  608. }
  609. //
  610. // if Data.cb is not 0, then the called is getting back data
  611. //
  612. if (Data.cb != 0)
  613. {
  614. memcpy(pbData, Data.pb, Data.cb);
  615. }
  616. Return:
  617. if (Data.pb != NULL)
  618. {
  619. MIDL_user_free(Data.pb);
  620. }
  621. return (status);
  622. }
  623. //***************************************************************************************
  624. //
  625. // __ScHelperGenRandBits:
  626. //
  627. //***************************************************************************************
  628. NTSTATUS WINAPI
  629. __ScHelperGenRandBits(
  630. IN PBYTE pbLogonInfo,
  631. IN OUT ScHelper_RandomCredBits* psc_rcb
  632. )
  633. {
  634. _ASSERTE(NULL != pbLogonInfo);
  635. NTSTATUS status = STATUS_SUCCESS;
  636. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  637. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  638. __try
  639. {
  640. status = RPC_ScHelperGenRandBits(
  641. pSCLogonPipe->hRPCBinding,
  642. pSCLogonPipe->BindingContext,
  643. psc_rcb->bR1,
  644. psc_rcb->bR2);
  645. }
  646. __except (EXCEPTION_EXECUTE_HANDLER)
  647. {
  648. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  649. DbgPrint("Exception occurred during RPC_ScHelperGenRandBits - %lx\n", _exception_code());
  650. }
  651. return (status);
  652. }
  653. //***************************************************************************************
  654. //
  655. // __ScHelperVerifyCardAndCreds:
  656. //
  657. //***************************************************************************************
  658. NTSTATUS WINAPI
  659. __ScHelperVerifyCardAndCreds(
  660. IN PUNICODE_STRING pucPIN,
  661. IN PCCERT_CONTEXT CertificateContext,
  662. IN PBYTE pbLogonInfo,
  663. IN PBYTE EncryptedData,
  664. IN ULONG EncryptedDataSize,
  665. OUT OPTIONAL PBYTE CleartextData,
  666. OUT PULONG CleartextDataSize
  667. )
  668. {
  669. _ASSERTE(NULL != pbLogonInfo);
  670. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  671. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  672. NTSTATUS status = STATUS_SUCCESS;
  673. CUnicodeString szPIN(pucPIN);
  674. OUT_BUFFER2 CleartextDataBuffer;
  675. memset(&CleartextDataBuffer, 0, sizeof(CleartextDataBuffer));
  676. //
  677. // Make sure pin got initialized correctly in constructor
  678. //
  679. if (NULL != pucPIN)
  680. {
  681. if (!szPIN.Valid())
  682. {
  683. status = STATUS_INSUFFICIENT_RESOURCES;
  684. goto Return;
  685. }
  686. }
  687. //
  688. // Make the call
  689. //
  690. __try
  691. {
  692. status = RPC_ScHelperVerifyCardAndCreds(
  693. pSCLogonPipe->hRPCBinding,
  694. pSCLogonPipe->BindingContext,
  695. (LPCWSTR)szPIN,
  696. EncryptedDataSize,
  697. EncryptedData,
  698. CleartextDataSize,
  699. &CleartextDataBuffer);
  700. }
  701. __except (EXCEPTION_EXECUTE_HANDLER)
  702. {
  703. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  704. DbgPrint("Exception occurred during RPC_ScHelperVerifyCardAndCreds - %lx\n", _exception_code());
  705. }
  706. if (!NT_SUCCESS(status))
  707. {
  708. DbgPrint("RPC_ScHelperVerifyCardAndCreds failed - %lx\n", status);
  709. goto Return;
  710. }
  711. //
  712. // if CleartextData.cb is not 0, then the called is getting back data
  713. //
  714. if (CleartextDataBuffer.cb != 0)
  715. {
  716. memcpy(CleartextData, CleartextDataBuffer.pb, CleartextDataBuffer.cb);
  717. }
  718. Return:
  719. if (CleartextDataBuffer.pb != NULL)
  720. {
  721. MIDL_user_free(CleartextDataBuffer.pb);
  722. }
  723. return (status);
  724. }
  725. //***************************************************************************************
  726. //
  727. // __ScHelperEncryptCredentials:
  728. //
  729. //***************************************************************************************
  730. NTSTATUS WINAPI
  731. __ScHelperEncryptCredentials(
  732. IN PUNICODE_STRING pucPIN,
  733. IN PCCERT_CONTEXT CertificateContext,
  734. IN ScHelper_RandomCredBits* psch_rcb,
  735. IN PBYTE pbLogonInfo,
  736. IN PBYTE CleartextData,
  737. IN ULONG CleartextDataSize,
  738. OUT OPTIONAL PBYTE EncryptedData,
  739. OUT PULONG EncryptedDataSize)
  740. {
  741. _ASSERTE(NULL != pbLogonInfo);
  742. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  743. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  744. NTSTATUS status = STATUS_SUCCESS;
  745. CUnicodeString szPIN(pucPIN);
  746. OUT_BUFFER2 EncryptedDataBuffer;
  747. memset(&EncryptedDataBuffer, 0, sizeof(EncryptedDataBuffer));
  748. //
  749. // Make sure pin got initialized correctly in constructor
  750. //
  751. if (NULL != pucPIN)
  752. {
  753. if (!szPIN.Valid())
  754. {
  755. status = STATUS_INSUFFICIENT_RESOURCES;
  756. goto Return;
  757. }
  758. }
  759. //
  760. // Make the call
  761. //
  762. __try
  763. {
  764. status = RPC_ScHelperEncryptCredentials(
  765. pSCLogonPipe->hRPCBinding,
  766. pSCLogonPipe->BindingContext,
  767. (LPCWSTR)szPIN,
  768. psch_rcb->bR1,
  769. psch_rcb->bR2,
  770. CleartextDataSize,
  771. CleartextData,
  772. EncryptedDataSize,
  773. &EncryptedDataBuffer);
  774. }
  775. __except (EXCEPTION_EXECUTE_HANDLER)
  776. {
  777. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  778. DbgPrint("Exception occurred during RPC_ScHelperEncryptCredentials - %lx\n", _exception_code());
  779. }
  780. if (!NT_SUCCESS(status))
  781. {
  782. if (status != STATUS_BUFFER_TOO_SMALL)
  783. {
  784. DbgPrint("RPC_ScHelperEncryptCredentials failed - %lx\n", status);
  785. }
  786. goto Return;
  787. }
  788. //
  789. // if EncryptedDataBuffer.cb is not 0, then the called is getting back data
  790. //
  791. if (EncryptedDataBuffer.cb != 0)
  792. {
  793. memcpy(EncryptedData, EncryptedDataBuffer.pb, EncryptedDataBuffer.cb);
  794. }
  795. Return:
  796. if (EncryptedDataBuffer.pb != NULL)
  797. {
  798. MIDL_user_free(EncryptedDataBuffer.pb);
  799. }
  800. return (status);
  801. }
  802. //***************************************************************************************
  803. //
  804. // __ScHelperSignMessage:
  805. //
  806. //***************************************************************************************
  807. NTSTATUS WINAPI
  808. __ScHelperSignMessage(
  809. IN PUNICODE_STRING pucPIN,
  810. IN OPTIONAL PBYTE pbLogonInfo,
  811. IN OPTIONAL ULONG_PTR KerbHProv,
  812. IN ULONG Algorithm,
  813. IN PBYTE Buffer,
  814. IN ULONG BufferLength,
  815. OUT PBYTE Signature,
  816. OUT PULONG SignatureLength
  817. )
  818. {
  819. LogonInfo *pLI;
  820. SCLOGON_PIPE *pSCLogonPipe;
  821. NTSTATUS status = STATUS_SUCCESS;
  822. CUnicodeString szPIN(pucPIN);
  823. OUT_BUFFER2 SignatureBuffer;
  824. PKERB_PUBLIC_KEY_HPROV pKerbHProv;
  825. handle_t hRPCBinding;
  826. BINDING_CONTEXT BindingContext;
  827. BOOL fBindingIsCertAndKey = FALSE;
  828. //
  829. // Decide which rpc binding to use
  830. //
  831. if (KerbHProv != NULL)
  832. {
  833. pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  834. hRPCBinding = pKerbHProv->hRPCBinding;
  835. BindingContext = pKerbHProv->hCertAndKey;
  836. fBindingIsCertAndKey = TRUE;
  837. }
  838. else
  839. {
  840. pLI = (LogonInfo *)pbLogonInfo;
  841. pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  842. hRPCBinding = pSCLogonPipe->hRPCBinding;
  843. BindingContext = pSCLogonPipe->BindingContext;
  844. }
  845. memset(&SignatureBuffer, 0, sizeof(SignatureBuffer));
  846. //
  847. // Make sure pin got initialized correctly in constructor
  848. //
  849. if (NULL != pucPIN)
  850. {
  851. if (!szPIN.Valid())
  852. {
  853. status = STATUS_INSUFFICIENT_RESOURCES;
  854. goto Return;
  855. }
  856. }
  857. //
  858. // Make the call
  859. //
  860. __try
  861. {
  862. status = RPC_ScHelperSignMessage(
  863. hRPCBinding,
  864. BindingContext,
  865. (LPCWSTR)szPIN,
  866. fBindingIsCertAndKey,
  867. Algorithm,
  868. BufferLength,
  869. Buffer,
  870. SignatureLength,
  871. &SignatureBuffer);
  872. }
  873. __except (EXCEPTION_EXECUTE_HANDLER)
  874. {
  875. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  876. DbgPrint("Exception occurred during RPC_ScHelperSignMessage - %lx\n", _exception_code());
  877. }
  878. if (!NT_SUCCESS(status))
  879. {
  880. DbgPrint("RPC_ScHelperSignMessage failed - %lx\n", status);
  881. goto Return;
  882. }
  883. //
  884. // if SignatureBuffer.cb is not 0, then the called is getting back data
  885. //
  886. if (SignatureBuffer.cb != 0)
  887. {
  888. memcpy(Signature, SignatureBuffer.pb, SignatureBuffer.cb);
  889. }
  890. Return:
  891. if (SignatureBuffer.pb != NULL)
  892. {
  893. MIDL_user_free(SignatureBuffer.pb);
  894. }
  895. return (status);
  896. }
  897. //***************************************************************************************
  898. //
  899. // __ScHelperVerifyMessage:
  900. //
  901. //***************************************************************************************
  902. NTSTATUS WINAPI
  903. __ScHelperVerifyMessage(
  904. IN OPTIONAL PBYTE pbLogonInfo,
  905. IN PCCERT_CONTEXT CertificateContext,
  906. IN ULONG Algorithm,
  907. IN PBYTE Buffer,
  908. IN ULONG BufferLength,
  909. IN PBYTE Signature,
  910. IN ULONG SignatureLength
  911. )
  912. {
  913. _ASSERTE(NULL != pbLogonInfo);
  914. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  915. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  916. NTSTATUS status = STATUS_SUCCESS;
  917. __try
  918. {
  919. status = RPC_ScHelperVerifyMessage(
  920. pSCLogonPipe->hRPCBinding,
  921. pSCLogonPipe->BindingContext,
  922. Algorithm,
  923. BufferLength,
  924. Buffer,
  925. SignatureLength,
  926. Signature);
  927. }
  928. __except (EXCEPTION_EXECUTE_HANDLER)
  929. {
  930. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  931. DbgPrint("Exception occurred during RPC_ScHelperVerifyMessage - %lx\n", _exception_code());
  932. }
  933. return (status);
  934. }
  935. //***************************************************************************************
  936. //
  937. // __ScHelperSignPkcsMessage:
  938. //
  939. //***************************************************************************************
  940. NTSTATUS WINAPI
  941. __ScHelperSignPkcsMessage(
  942. IN OPTIONAL PUNICODE_STRING pucPIN,
  943. IN OPTIONAL PBYTE pbLogonInfo,
  944. IN OPTIONAL ULONG_PTR KerbHProv,
  945. IN PCCERT_CONTEXT Certificate,
  946. IN PCRYPT_ALGORITHM_IDENTIFIER Algorithm,
  947. IN DWORD dwSignMessageFlags,
  948. IN PBYTE Buffer,
  949. IN ULONG BufferLength,
  950. OUT OPTIONAL PBYTE SignedBuffer,
  951. OUT OPTIONAL PULONG SignedBufferLength
  952. )
  953. {
  954. LogonInfo *pLI;
  955. SCLOGON_PIPE *pSCLogonPipe;
  956. NTSTATUS status = STATUS_SUCCESS;
  957. CUnicodeString szPIN(pucPIN);
  958. OUT_BUFFER2 SignedBufferBuffer;
  959. PKERB_PUBLIC_KEY_HPROV pKerbHProv;
  960. handle_t hRPCBinding;
  961. BINDING_CONTEXT BindingContext;
  962. BOOL fBindingIsCertAndKey = FALSE;
  963. //
  964. // Decide which rpc binding to use
  965. //
  966. if (KerbHProv != NULL)
  967. {
  968. pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  969. hRPCBinding = pKerbHProv->hRPCBinding;
  970. BindingContext = pKerbHProv->hCertAndKey;
  971. fBindingIsCertAndKey = TRUE;
  972. }
  973. else
  974. {
  975. pLI = (LogonInfo *)pbLogonInfo;
  976. pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  977. hRPCBinding = pSCLogonPipe->hRPCBinding;
  978. BindingContext = pSCLogonPipe->BindingContext;
  979. }
  980. memset(&SignedBufferBuffer, 0, sizeof(SignedBufferBuffer));
  981. //
  982. // Make sure pin got initialized correctly in constructor
  983. //
  984. if (NULL != pucPIN)
  985. {
  986. if (!szPIN.Valid())
  987. {
  988. status = STATUS_INSUFFICIENT_RESOURCES;
  989. goto Return;
  990. }
  991. }
  992. //
  993. // Make the call
  994. //
  995. __try
  996. {
  997. status = RPC_ScHelperSignPkcsMessage(
  998. hRPCBinding,
  999. BindingContext,
  1000. (LPCWSTR)szPIN,
  1001. fBindingIsCertAndKey,
  1002. Algorithm->pszObjId,
  1003. Algorithm->Parameters.cbData,
  1004. Algorithm->Parameters.pbData,
  1005. dwSignMessageFlags,
  1006. BufferLength,
  1007. Buffer,
  1008. SignedBufferLength,
  1009. &SignedBufferBuffer);
  1010. }
  1011. __except (EXCEPTION_EXECUTE_HANDLER)
  1012. {
  1013. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1014. DbgPrint("Exception occurred during RPC_ScHelperSignPkcsMessage - %lx\n", _exception_code());
  1015. }
  1016. if (!NT_SUCCESS(status))
  1017. {
  1018. if (status != STATUS_BUFFER_TOO_SMALL)
  1019. {
  1020. DbgPrint("RPC_ScHelperSignPkcsMessage failed - %lx\n", status);
  1021. }
  1022. goto Return;
  1023. }
  1024. //
  1025. // if SignedBufferBuffer.cb is not 0, then the called is getting back data
  1026. //
  1027. if (SignedBufferBuffer.cb != 0)
  1028. {
  1029. memcpy(SignedBuffer, SignedBufferBuffer.pb, SignedBufferBuffer.cb);
  1030. }
  1031. Return:
  1032. if (SignedBufferBuffer.pb != NULL)
  1033. {
  1034. MIDL_user_free(SignedBufferBuffer.pb);
  1035. }
  1036. return (status);
  1037. }
  1038. //***************************************************************************************
  1039. //
  1040. // __ScHelperVerifyPkcsMessage:
  1041. //
  1042. //***************************************************************************************
  1043. /*NTSTATUS WINAPI
  1044. __ScHelperVerifyPkcsMessage(
  1045. IN OPTIONAL PBYTE pbLogonInfo,
  1046. IN OPTIONAL HCRYPTPROV Provider,
  1047. IN PBYTE Buffer,
  1048. IN ULONG BufferLength,
  1049. OUT OPTIONAL PBYTE DecodedBuffer,
  1050. OUT OPTIONAL PULONG DecodedBufferLength,
  1051. OUT OPTIONAL PCCERT_CONTEXT * CertificateContext
  1052. )
  1053. {
  1054. if (Provider != NULL)
  1055. {
  1056. return (ScHelperVerifyPkcsMessage(
  1057. pbLogonInfo,
  1058. Provider,
  1059. Buffer,
  1060. BufferLength,
  1061. DecodedBuffer,
  1062. DecodedBufferLength,
  1063. CertificateContext));
  1064. }
  1065. _ASSERTE(NULL != pbLogonInfo);
  1066. LogonInfo *pLI = (LogonInfo *)pbLogonInfo;
  1067. SCLOGON_PIPE *pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  1068. NTSTATUS status = STATUS_SUCCESS;
  1069. PCCERT_CONTEXT pCertCtx = NULL;
  1070. OUT_BUFFER2 DecodedBufferBuffer;
  1071. OUT_BUFFER1 CertBytes;
  1072. BOOL fCertificateContextRequested = (CertificateContext != NULL);
  1073. memset(&DecodedBufferBuffer, 0, sizeof(DecodedBufferBuffer));
  1074. memset(&CertBytes, 0, sizeof(CertBytes));
  1075. //
  1076. // Make the call
  1077. //
  1078. __try
  1079. {
  1080. status = RPC_ScHelperVerifyPkcsMessage(
  1081. pSCLogonPipe->hRPCBinding,
  1082. pSCLogonPipe->BindingContext,
  1083. BufferLength,
  1084. Buffer,
  1085. DecodedBufferLength,
  1086. &DecodedBufferBuffer,
  1087. fCertificateContextRequested,
  1088. &CertBytes);
  1089. }
  1090. __except (EXCEPTION_EXECUTE_HANDLER)
  1091. {
  1092. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1093. DbgPrint("Exception occurred during RPC_ScHelperVerifyPkcsMessage - %lx\n", _exception_code());
  1094. }
  1095. if (!NT_SUCCESS(status))
  1096. {
  1097. goto Return;
  1098. }
  1099. //
  1100. // Create the return CertContext based on the bytes returned
  1101. //
  1102. if (fCertificateContextRequested)
  1103. {
  1104. pCertCtx = CertCreateCertificateContext(
  1105. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1106. CertBytes.pb,
  1107. CertBytes.cb);
  1108. if (pCertCtx == NULL)
  1109. {
  1110. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1111. goto Return;
  1112. }
  1113. }
  1114. //
  1115. // if DecodedBufferBuffer.cb is not 0, then the called is getting back data
  1116. //
  1117. if (DecodedBufferBuffer.cb != 0)
  1118. {
  1119. memcpy(DecodedBuffer, DecodedBufferBuffer.pb, DecodedBufferBuffer.cb);
  1120. }
  1121. Return:
  1122. if (fCertificateContextRequested)
  1123. {
  1124. *CertificateContext = pCertCtx;
  1125. }
  1126. if (DecodedBufferBuffer.pb != NULL)
  1127. {
  1128. MIDL_user_free(DecodedBufferBuffer.pb);
  1129. }
  1130. if (CertBytes.pb != NULL)
  1131. {
  1132. MIDL_user_free(CertBytes.pb);
  1133. }
  1134. return (status);
  1135. }*/
  1136. //***************************************************************************************
  1137. //
  1138. // __ScHelperDecryptMessage:
  1139. //
  1140. //***************************************************************************************
  1141. NTSTATUS WINAPI
  1142. __ScHelperDecryptMessage(
  1143. IN PUNICODE_STRING pucPIN,
  1144. IN OPTIONAL PBYTE pbLogonInfo,
  1145. IN OPTIONAL ULONG_PTR KerbHProv,
  1146. IN PCCERT_CONTEXT CertificateContext,
  1147. IN PBYTE CipherText, // Supplies formatted CipherText
  1148. IN ULONG CipherLength, // Supplies the length of the CiperText
  1149. OUT PBYTE ClearText, // Receives decrypted message
  1150. IN OUT PULONG pClearLength // Supplies length of buffer, receives actual length
  1151. )
  1152. {
  1153. LogonInfo *pLI;
  1154. SCLOGON_PIPE *pSCLogonPipe;
  1155. NTSTATUS status = STATUS_SUCCESS;
  1156. CUnicodeString szPIN(pucPIN);
  1157. OUT_BUFFER2 ClearTextBuffer;
  1158. PKERB_PUBLIC_KEY_HPROV pKerbHProv;
  1159. handle_t hRPCBinding;
  1160. BINDING_CONTEXT BindingContext;
  1161. BOOL fBindingIsCertAndKey = FALSE;
  1162. //
  1163. // Decide which rpc binding to use
  1164. //
  1165. if (KerbHProv != NULL)
  1166. {
  1167. pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  1168. hRPCBinding = pKerbHProv->hRPCBinding;
  1169. BindingContext = pKerbHProv->hCertAndKey;
  1170. fBindingIsCertAndKey = TRUE;
  1171. }
  1172. else
  1173. {
  1174. pLI = (LogonInfo *)pbLogonInfo;
  1175. pSCLogonPipe = (SCLOGON_PIPE *) pLI->ContextInformation;
  1176. hRPCBinding = pSCLogonPipe->hRPCBinding;
  1177. BindingContext = pSCLogonPipe->BindingContext;
  1178. }
  1179. memset(&ClearTextBuffer, 0, sizeof(ClearTextBuffer));
  1180. //
  1181. // Make sure pin got initialized correctly in constructor
  1182. //
  1183. if (NULL != pucPIN)
  1184. {
  1185. if (!szPIN.Valid())
  1186. {
  1187. status = STATUS_INSUFFICIENT_RESOURCES;
  1188. goto Return;
  1189. }
  1190. }
  1191. //
  1192. // Make the call
  1193. //
  1194. __try
  1195. {
  1196. status = RPC_ScHelperDecryptMessage(
  1197. hRPCBinding,
  1198. BindingContext,
  1199. (LPCWSTR)szPIN,
  1200. fBindingIsCertAndKey,
  1201. CipherLength,
  1202. CipherText,
  1203. pClearLength,
  1204. &ClearTextBuffer);
  1205. }
  1206. __except (EXCEPTION_EXECUTE_HANDLER)
  1207. {
  1208. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1209. DbgPrint("Exception occurred during RPC_ScHelperDecryptMessage - %lx\n", _exception_code());
  1210. }
  1211. if (!NT_SUCCESS(status))
  1212. {
  1213. if (status != STATUS_BUFFER_TOO_SMALL)
  1214. {
  1215. DbgPrint("RPC_ScHelperDecryptMessage failed - %lx\n", status);
  1216. }
  1217. goto Return;
  1218. }
  1219. //
  1220. // if ClearTextBuffer.cb is not 0, then the call is getting back data
  1221. //
  1222. if (ClearTextBuffer.cb != 0)
  1223. {
  1224. memcpy(ClearText, ClearTextBuffer.pb, ClearTextBuffer.cb);
  1225. }
  1226. Return:
  1227. if (ClearTextBuffer.pb != NULL)
  1228. {
  1229. MIDL_user_free(ClearTextBuffer.pb);
  1230. }
  1231. return (status);
  1232. }
  1233. //***************************************************************************************
  1234. //
  1235. // __ScHelper_CryptAcquireCertificatePrivateKey:
  1236. //
  1237. //***************************************************************************************
  1238. NTSTATUS WINAPI
  1239. __ScHelper_CryptAcquireCertificatePrivateKey(
  1240. IN PCCERT_CONTEXT CertificateContext,
  1241. OUT ULONG_PTR *pKerbHProv,
  1242. OUT DWORD *pLastError
  1243. )
  1244. {
  1245. NTSTATUS status = STATUS_SUCCESS;
  1246. PKERB_PUBLIC_KEY_HPROV pProv = NULL;
  1247. BOOL fRPCBindingInitialized = FALSE;
  1248. CRYPT_KEY_PROV_INFO *pKeyProvInfo = NULL;
  1249. DWORD cbKeyProvInfo = 0;
  1250. HANDLE hThreadToken = INVALID_HANDLE_VALUE;
  1251. BOOL fImpersonatingAnonymous = FALSE;
  1252. HANDLE hNULL = NULL;
  1253. *pLastError = 0;
  1254. //
  1255. // If we are already impersonating, then we need to do things slightly
  1256. // differently... starting with getting the current thread token
  1257. //
  1258. if (!GetImpersonationToken(&hThreadToken))
  1259. {
  1260. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1261. goto Return;
  1262. }
  1263. //
  1264. // If we are impersonating, then revert to anonymous
  1265. //
  1266. if (hThreadToken != INVALID_HANDLE_VALUE)
  1267. {
  1268. if (!SetThreadToken(NULL, NULL))
  1269. {
  1270. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1271. goto Return;
  1272. }
  1273. fImpersonatingAnonymous = TRUE;
  1274. }
  1275. //
  1276. // Allocate the new KERB_PUBLIC_KEY_HPROV struct
  1277. //
  1278. pProv = (PKERB_PUBLIC_KEY_HPROV) MIDL_user_allocate(sizeof(KERB_PUBLIC_KEY_HPROV));
  1279. if (pProv == NULL)
  1280. {
  1281. *pLastError = ERROR_NOT_ENOUGH_MEMORY;
  1282. status = STATUS_INSUFFICIENT_RESOURCES;
  1283. goto Return;
  1284. }
  1285. pProv->hCertAndKey = NULL;
  1286. //
  1287. // Setup the RPC binding
  1288. //
  1289. status = _SetupRPCConnection(&(pProv->hRPCBinding), hThreadToken);
  1290. if (!NT_SUCCESS(status))
  1291. {
  1292. goto Return;
  1293. }
  1294. fRPCBindingInitialized = TRUE;
  1295. //
  1296. // Get the key prov info from the cert context
  1297. //
  1298. if (!CertGetCertificateContextProperty(
  1299. CertificateContext,
  1300. CERT_KEY_PROV_INFO_PROP_ID,
  1301. NULL,
  1302. &cbKeyProvInfo))
  1303. {
  1304. *pLastError = GetLastError();
  1305. status = STATUS_INSUFFICIENT_RESOURCES;
  1306. goto Return;
  1307. }
  1308. pKeyProvInfo = (CRYPT_KEY_PROV_INFO *) MIDL_user_allocate(cbKeyProvInfo);
  1309. if (pKeyProvInfo == NULL)
  1310. {
  1311. *pLastError = ERROR_NOT_ENOUGH_MEMORY;
  1312. status = STATUS_INSUFFICIENT_RESOURCES;
  1313. goto Return;
  1314. }
  1315. if (!CertGetCertificateContextProperty(
  1316. CertificateContext,
  1317. CERT_KEY_PROV_INFO_PROP_ID,
  1318. pKeyProvInfo,
  1319. &cbKeyProvInfo))
  1320. {
  1321. *pLastError = GetLastError();
  1322. status = STATUS_INSUFFICIENT_RESOURCES;
  1323. goto Return;
  1324. }
  1325. //
  1326. // Create the hProv in the winlogon process
  1327. //
  1328. __try
  1329. {
  1330. status = RPC_ScHelper_CryptAcquireCertificatePrivateKey(
  1331. pProv->hRPCBinding,
  1332. CertificateContext->cbCertEncoded,
  1333. CertificateContext->pbCertEncoded,
  1334. pKeyProvInfo->pwszContainerName,
  1335. pKeyProvInfo->pwszProvName,
  1336. pKeyProvInfo->dwProvType,
  1337. pKeyProvInfo->dwFlags,
  1338. pKeyProvInfo->dwKeySpec,
  1339. &(pProv->hCertAndKey),
  1340. pLastError);
  1341. }
  1342. __except (EXCEPTION_EXECUTE_HANDLER)
  1343. {
  1344. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1345. DbgPrint("Exception occurred during RPC_ScHelper_CryptAcquireCertificatePrivateKey - %lx\n", _exception_code());
  1346. }
  1347. Return:
  1348. if (NT_SUCCESS(status))
  1349. {
  1350. *pKerbHProv = (ULONG_PTR) pProv;
  1351. }
  1352. else
  1353. {
  1354. DbgPrint("RPC_ScHelper_CryptAcquireCertificatePrivateKey failed - %lx\n", status);
  1355. if (fRPCBindingInitialized)
  1356. {
  1357. _TeardownRPCConnection(&(pProv->hRPCBinding));
  1358. }
  1359. if (pProv != NULL)
  1360. {
  1361. MIDL_user_free(pProv);
  1362. }
  1363. }
  1364. if (pKeyProvInfo != NULL)
  1365. {
  1366. MIDL_user_free(pKeyProvInfo);
  1367. }
  1368. //
  1369. // Reset impersonation if needed
  1370. //
  1371. if (fImpersonatingAnonymous)
  1372. {
  1373. if (!SetThreadToken(NULL, hThreadToken))
  1374. {
  1375. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1376. DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
  1377. }
  1378. }
  1379. if (hThreadToken != INVALID_HANDLE_VALUE)
  1380. {
  1381. CloseHandle(hThreadToken);
  1382. }
  1383. return (status);
  1384. }
  1385. //***************************************************************************************
  1386. //
  1387. // __ScHelper_CryptSetProvParam:
  1388. //
  1389. //***************************************************************************************
  1390. NTSTATUS WINAPI
  1391. __ScHelper_CryptSetProvParam(
  1392. IN ULONG_PTR KerbHProv,
  1393. IN LPSTR pszPIN,
  1394. OUT DWORD *pLastError
  1395. )
  1396. {
  1397. NTSTATUS status = STATUS_SUCCESS;
  1398. PKERB_PUBLIC_KEY_HPROV pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  1399. HANDLE hThreadToken = INVALID_HANDLE_VALUE;
  1400. BOOL fImpersonatingAnonymous = FALSE;
  1401. HANDLE hNULL = NULL;
  1402. *pLastError = 0;
  1403. //
  1404. // If we are already impersonating, then we need to do things slightly
  1405. // differently... starting with getting the current thread token
  1406. //
  1407. if (!GetImpersonationToken(&hThreadToken))
  1408. {
  1409. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1410. goto Return;
  1411. }
  1412. //
  1413. // If we are impersonating, then revert to anonymous
  1414. //
  1415. if (hThreadToken != INVALID_HANDLE_VALUE)
  1416. {
  1417. if (!SetThreadToken(NULL, NULL))
  1418. {
  1419. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1420. goto Return;
  1421. }
  1422. fImpersonatingAnonymous = TRUE;
  1423. }
  1424. //
  1425. // Set the prov param on the hProv in the winlogon process
  1426. //
  1427. __try
  1428. {
  1429. status = RPC_ScHelper_CryptSetProvParam(
  1430. pKerbHProv->hRPCBinding,
  1431. pKerbHProv->hCertAndKey,
  1432. pszPIN,
  1433. pLastError);
  1434. }
  1435. __except (EXCEPTION_EXECUTE_HANDLER)
  1436. {
  1437. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1438. DbgPrint("Exception occurred during RPC_ScHelper_CryptSetProvParam - %lx\n", _exception_code());
  1439. goto Return;
  1440. }
  1441. Return:
  1442. //
  1443. // Reset impersonation if needed
  1444. //
  1445. if (fImpersonatingAnonymous)
  1446. {
  1447. if (!SetThreadToken(NULL, hThreadToken))
  1448. {
  1449. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1450. DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
  1451. }
  1452. }
  1453. if (hThreadToken != INVALID_HANDLE_VALUE)
  1454. {
  1455. CloseHandle(hThreadToken);
  1456. }
  1457. return (status);
  1458. }
  1459. //***************************************************************************************
  1460. //
  1461. // __ScHelper_CryptReleaseContext:
  1462. //
  1463. //***************************************************************************************
  1464. NTSTATUS WINAPI
  1465. __ScHelper_CryptReleaseContext(
  1466. IN ULONG_PTR KerbHProv
  1467. )
  1468. {
  1469. NTSTATUS status = STATUS_SUCCESS;
  1470. PKERB_PUBLIC_KEY_HPROV pKerbHProv = (PKERB_PUBLIC_KEY_HPROV) KerbHProv;
  1471. HANDLE hThreadToken = INVALID_HANDLE_VALUE;
  1472. BOOL fImpersonatingAnonymous = FALSE;
  1473. HANDLE hNULL = NULL;
  1474. //
  1475. // If we are already impersonating, then we need to do things slightly
  1476. // differently... starting with getting the current thread token
  1477. //
  1478. if (!GetImpersonationToken(&hThreadToken))
  1479. {
  1480. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1481. goto Return;
  1482. }
  1483. //
  1484. // If we are impersonating, then revert to anonymous
  1485. //
  1486. if (hThreadToken != INVALID_HANDLE_VALUE)
  1487. {
  1488. if (!SetThreadToken(NULL, NULL))
  1489. {
  1490. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1491. goto Return;
  1492. }
  1493. fImpersonatingAnonymous = TRUE;
  1494. }
  1495. //
  1496. // release hProv in the winlogon process
  1497. //
  1498. __try
  1499. {
  1500. status = RPC_ScHelper_CryptReleaseContext(
  1501. pKerbHProv->hRPCBinding,
  1502. &(pKerbHProv->hCertAndKey));
  1503. }
  1504. __except (EXCEPTION_EXECUTE_HANDLER)
  1505. {
  1506. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1507. DbgPrint("Exception occurred during RPC_ScHelper_CryptReleaseContext - %lx\n", _exception_code());
  1508. goto Return;
  1509. }
  1510. Return:
  1511. _TeardownRPCConnection(&(pKerbHProv->hRPCBinding));
  1512. MIDL_user_free(pKerbHProv);
  1513. //
  1514. // Reset impersonation if needed
  1515. //
  1516. if (fImpersonatingAnonymous)
  1517. {
  1518. if (!SetThreadToken(NULL, hThreadToken))
  1519. {
  1520. status = STATUS_SMARTCARD_SUBSYSTEM_FAILURE;
  1521. DbgPrint("SetThreadToken failed, we are now in a BOGUS STATE!! - %lx\n", status);
  1522. }
  1523. }
  1524. if (hThreadToken != INVALID_HANDLE_VALUE)
  1525. {
  1526. CloseHandle(hThreadToken);
  1527. }
  1528. return (status);
  1529. }