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.

1657 lines
45 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: callback.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 09-23-97 jbanes Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "sslp.h"
  18. SECURITY_STATUS
  19. NTAPI
  20. SPSignatureCallback(
  21. ULONG_PTR hProv,
  22. ULONG_PTR aiHash,
  23. SecBuffer *pInput,
  24. SecBuffer *pOutput);
  25. SECURITY_STATUS
  26. NTAPI
  27. UploadCertContextCallback(
  28. ULONG_PTR Argument1,
  29. ULONG_PTR Argument2,
  30. SecBuffer *pInput,
  31. SecBuffer *pOutput);
  32. SECURITY_STATUS
  33. NTAPI
  34. UploadCertStoreCallback(
  35. ULONG_PTR Argument1,
  36. ULONG_PTR Argument2,
  37. SecBuffer *pInput,
  38. SecBuffer *pOutput);
  39. SECURITY_STATUS
  40. NTAPI
  41. RemoteCryptAcquireContextCallback(
  42. ULONG_PTR dwProvType,
  43. ULONG_PTR dwFlags,
  44. SecBuffer *pInput,
  45. SecBuffer *pOutput);
  46. SECURITY_STATUS
  47. RemoteCryptReleaseContextCallback(
  48. ULONG_PTR hProv,
  49. ULONG_PTR dwFlags,
  50. SecBuffer *pInput,
  51. SecBuffer *pOutput);
  52. SECURITY_STATUS
  53. DownloadCertContextCallback(
  54. ULONG_PTR Argument1,
  55. ULONG_PTR Argument2,
  56. SecBuffer *pInput,
  57. SecBuffer *pOutput);
  58. SECURITY_STATUS
  59. NTAPI
  60. GetUserKeysCallback(
  61. ULONG_PTR dwLsaContext,
  62. ULONG_PTR dwFlags,
  63. SecBuffer *pInput,
  64. SecBuffer *pOutput);
  65. SCH_CALLBACK_LIST g_SchannelCallbacks[] =
  66. {
  67. { SCH_SIGNATURE_CALLBACK, SPSignatureCallback },
  68. { SCH_UPLOAD_CREDENTIAL_CALLBACK, UploadCertContextCallback },
  69. { SCH_UPLOAD_CERT_STORE_CALLBACK, UploadCertStoreCallback },
  70. { SCH_ACQUIRE_CONTEXT_CALLBACK, RemoteCryptAcquireContextCallback },
  71. { SCH_RELEASE_CONTEXT_CALLBACK, RemoteCryptReleaseContextCallback },
  72. { SCH_DOWNLOAD_CERT_CALLBACK, DownloadCertContextCallback },
  73. { SCH_GET_USER_KEYS, GetUserKeysCallback },
  74. };
  75. DWORD g_cSchannelCallbacks = sizeof(g_SchannelCallbacks) / sizeof(SCH_CALLBACK_LIST);
  76. //+---------------------------------------------------------------------------
  77. //
  78. // Function: PerformApplicationCallback
  79. //
  80. // Synopsis: Call back to the application process.
  81. //
  82. // Arguments: [dwCallback] -- Callback function number.
  83. // [dwArg1] --
  84. // [dwArg2] --
  85. // [pInput] --
  86. // [pOutput] --
  87. //
  88. // History: 09-23-97 jbanes Created
  89. //
  90. // Notes:
  91. //
  92. //----------------------------------------------------------------------------
  93. SECURITY_STATUS
  94. PerformApplicationCallback(
  95. DWORD dwCallback,
  96. ULONG_PTR dwArg1,
  97. ULONG_PTR dwArg2,
  98. SecBuffer *pInput,
  99. SecBuffer *pOutput,
  100. BOOL fExpectOutput)
  101. {
  102. SECURITY_STATUS Status;
  103. PVOID pvBuffer;
  104. if(LsaTable == NULL)
  105. {
  106. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  107. }
  108. pOutput->BufferType = SECBUFFER_EMPTY;
  109. pOutput->pvBuffer = NULL;
  110. pOutput->cbBuffer = 0;
  111. try
  112. {
  113. Status = LsaTable->ClientCallback((PCHAR)ULongToPtr(dwCallback), // Sundown: dwCallback is a function number.
  114. dwArg1,
  115. dwArg2,
  116. pInput,
  117. pOutput);
  118. }
  119. except(EXCEPTION_EXECUTE_HANDLER)
  120. {
  121. Status = SP_LOG_RESULT(SEC_E_UNSUPPORTED_FUNCTION);
  122. }
  123. if ( !NT_SUCCESS( Status ) )
  124. {
  125. return SP_LOG_RESULT( Status );
  126. }
  127. if(Status != SEC_E_OK)
  128. {
  129. SP_LOG_RESULT( Status );
  130. return SEC_E_INTERNAL_ERROR;
  131. }
  132. if(pOutput->pvBuffer && pOutput->cbBuffer)
  133. {
  134. pvBuffer = SPExternalAlloc(pOutput->cbBuffer);
  135. if(pvBuffer == NULL)
  136. {
  137. return SP_LOG_RESULT( SEC_E_INSUFFICIENT_MEMORY );
  138. }
  139. Status = LsaTable->CopyFromClientBuffer(NULL,
  140. pOutput->cbBuffer,
  141. pvBuffer,
  142. pOutput->pvBuffer );
  143. if ( !NT_SUCCESS( Status ) )
  144. {
  145. SPExternalFree(pvBuffer);
  146. return SP_LOG_RESULT( Status );
  147. }
  148. Status = SPFreeUserAllocMemory(pOutput->pvBuffer, pOutput->cbBuffer);
  149. if ( !NT_SUCCESS( Status ) )
  150. {
  151. SPExternalFree(pvBuffer);
  152. return SP_LOG_RESULT( Status );
  153. }
  154. pOutput->pvBuffer = pvBuffer;
  155. }
  156. else if(fExpectOutput)
  157. {
  158. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  159. }
  160. return Status;
  161. }
  162. #if 0
  163. // This helper function is called by the LSA process in order to duplicate
  164. // a handle belonging to the application process.
  165. BOOL
  166. DuplicateApplicationHandle(
  167. HANDLE hAppHandle,
  168. LPHANDLE phLsaHandle)
  169. {
  170. SECPKG_CALL_INFO CallInfo;
  171. HANDLE hAppProcess;
  172. HANDLE hLsaProcess;
  173. BOOL fResult;
  174. // Get handle to application process.
  175. if(!LsaTable->GetCallInfo(&CallInfo))
  176. {
  177. return FALSE;
  178. }
  179. hAppProcess = OpenProcess(PROCESS_DUP_HANDLE,
  180. FALSE,
  181. CallInfo.ProcessId);
  182. if(hAppProcess == NULL)
  183. {
  184. return FALSE;
  185. }
  186. // Get handle to lsa process.
  187. hLsaProcess = GetCurrentProcess();
  188. // Duplicate handle
  189. fResult = DuplicateHandle(hAppProcess,
  190. hAppHandle,
  191. hLsaProcess,
  192. phLsaHandle,
  193. 0, FALSE,
  194. DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
  195. CloseHandle(hAppProcess);
  196. CloseHandle(hLsaProcess);
  197. return fResult;
  198. }
  199. #endif
  200. //+---------------------------------------------------------------------------
  201. //
  202. // Function: RemoteCryptAcquireContextCallback
  203. //
  204. // Synopsis: Obtain a CSP context handle, using the information passed
  205. // in the input buffer.
  206. //
  207. // Arguments: [dwProvType] -- Provider type.
  208. // [dwFlags] -- Flags.
  209. // [pInput] -- Buffer containing provider info.
  210. // [pOutput] -- Buffer containing CSP context handle.
  211. //
  212. // History: 09-24-97 jbanes Created
  213. //
  214. // Notes: The structure of the input buffer is as follows:
  215. //
  216. // cbContainerName
  217. // cbProvName
  218. // wszContainerName
  219. // wszProvName
  220. //
  221. // This function always uses an actual CSP.
  222. //
  223. //----------------------------------------------------------------------------
  224. SECURITY_STATUS
  225. RemoteCryptAcquireContextCallback(
  226. ULONG_PTR dwProvType, // in
  227. ULONG_PTR dwFlags, // in
  228. SecBuffer *pInput, // in
  229. SecBuffer *pOutput) // out
  230. {
  231. LPWSTR pwszContainerName;
  232. DWORD cbContainerName;
  233. LPWSTR pwszProvName;
  234. DWORD cbProvName;
  235. HCRYPTPROV hProv;
  236. LPBYTE pbBuffer;
  237. DWORD cbBuffer;
  238. if(!SchannelInit(TRUE))
  239. {
  240. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  241. }
  242. DebugLog((DEB_TRACE, "RemoteCryptAcquireContextCallback\n"));
  243. pOutput->BufferType = SECBUFFER_DATA;
  244. pOutput->cbBuffer = 0;
  245. pOutput->pvBuffer = NULL;
  246. if(pInput->pvBuffer == NULL)
  247. {
  248. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  249. }
  250. // Parse input buffer.
  251. pbBuffer = pInput->pvBuffer;
  252. cbBuffer = pInput->cbBuffer;
  253. if(cbBuffer < sizeof(DWORD) * 2)
  254. {
  255. return SP_LOG_RESULT(SEC_E_INCOMPLETE_MESSAGE);
  256. }
  257. cbContainerName = *(DWORD *)pbBuffer;
  258. pbBuffer += sizeof(DWORD);
  259. cbProvName = *(DWORD *)pbBuffer;
  260. pbBuffer += sizeof(DWORD);
  261. if(cbBuffer < sizeof(DWORD) * 2 + cbContainerName + cbProvName)
  262. {
  263. return SP_LOG_RESULT(SEC_E_INCOMPLETE_MESSAGE);
  264. }
  265. if(cbContainerName)
  266. {
  267. pwszContainerName = (LPWSTR)pbBuffer;
  268. }
  269. else
  270. {
  271. pwszContainerName = NULL;
  272. }
  273. pbBuffer += cbContainerName;
  274. if(cbProvName)
  275. {
  276. pwszProvName = (LPWSTR)pbBuffer;
  277. }
  278. else
  279. {
  280. pwszProvName = NULL;
  281. }
  282. // HACKHACK - clear the smart-card specific flag.
  283. dwFlags &= ~CERT_SET_KEY_CONTEXT_PROP_ID;
  284. DebugLog((SP_LOG_TRACE, "Container:%ls\n", pwszContainerName));
  285. DebugLog((SP_LOG_TRACE, "Provider: %ls\n", pwszProvName));
  286. DebugLog((SP_LOG_TRACE, "Type: 0x%8.8x\n", dwProvType));
  287. DebugLog((SP_LOG_TRACE, "Flags: 0x%8.8x\n", dwFlags));
  288. // Attempt to get CSP context handle.
  289. if(!CryptAcquireContextW(&hProv,
  290. pwszContainerName,
  291. pwszProvName,
  292. (DWORD) dwProvType,
  293. (DWORD) dwFlags))
  294. {
  295. return SP_LOG_RESULT(GetLastError());
  296. }
  297. // Allocate memory for the output buffer.
  298. pOutput->BufferType = SECBUFFER_DATA;
  299. pOutput->cbBuffer = sizeof(HCRYPTPROV);
  300. pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer);
  301. if(pOutput->pvBuffer == NULL)
  302. {
  303. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  304. }
  305. // Place hProv in output buffer.
  306. *(HCRYPTPROV *)pOutput->pvBuffer = hProv;
  307. return SEC_E_OK;
  308. }
  309. NTSTATUS
  310. RemoteCryptAcquireContextW(
  311. HCRYPTPROV *phProv,
  312. LPCWSTR pwszContainerName,
  313. LPCWSTR pwszProvName,
  314. DWORD dwProvType,
  315. DWORD dwFlags)
  316. {
  317. SecBuffer Input;
  318. SecBuffer Output;
  319. DWORD cbContainerName;
  320. DWORD cbProvName;
  321. PBYTE pbBuffer;
  322. SECURITY_STATUS scRet;
  323. // Build input buffer.
  324. if(pwszContainerName)
  325. {
  326. cbContainerName = (lstrlenW(pwszContainerName) + 1) * sizeof(WCHAR);
  327. }
  328. else
  329. {
  330. cbContainerName = 0;
  331. }
  332. if(pwszProvName)
  333. {
  334. cbProvName = (lstrlenW(pwszProvName) + 1) * sizeof(WCHAR);
  335. }
  336. else
  337. {
  338. cbProvName = 0;
  339. }
  340. Input.BufferType = SECBUFFER_DATA;
  341. Input.cbBuffer = sizeof(DWORD) +
  342. sizeof(DWORD) +
  343. cbContainerName +
  344. cbProvName;
  345. SafeAllocaAllocate(Input.pvBuffer, Input.cbBuffer);
  346. if(Input.pvBuffer == NULL)
  347. {
  348. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  349. }
  350. pbBuffer = Input.pvBuffer;
  351. *(DWORD *)pbBuffer = cbContainerName;
  352. pbBuffer += sizeof(DWORD);
  353. *(DWORD *)pbBuffer = cbProvName;
  354. pbBuffer += sizeof(DWORD);
  355. CopyMemory(pbBuffer, pwszContainerName, cbContainerName);
  356. pbBuffer += cbContainerName;
  357. CopyMemory(pbBuffer, pwszProvName, cbProvName);
  358. pbBuffer += cbProvName;
  359. // Do callback.
  360. scRet = PerformApplicationCallback( SCH_ACQUIRE_CONTEXT_CALLBACK,
  361. dwProvType,
  362. dwFlags,
  363. &Input,
  364. &Output,
  365. TRUE);
  366. if(!NT_SUCCESS(scRet))
  367. {
  368. DebugLog((SP_LOG_ERROR, "Error 0x%x calling remote CryptAcquireContext\n", scRet));
  369. SafeAllocaFree(Input.pvBuffer);
  370. return scRet;
  371. }
  372. // Get hProv from output buffer.
  373. *phProv = *(HCRYPTPROV *)Output.pvBuffer;
  374. DebugLog((SP_LOG_TRACE, "Remote CSP handle retrieved (0x%x)\n", *phProv));
  375. SafeAllocaFree(Input.pvBuffer);
  376. SPExternalFree(Output.pvBuffer);
  377. return SEC_E_OK;
  378. }
  379. SECURITY_STATUS
  380. RemoteCryptReleaseContextCallback(
  381. ULONG_PTR hProv, // in
  382. ULONG_PTR dwFlags, // in
  383. SecBuffer *pInput, // in
  384. SecBuffer *pOutput) // out
  385. {
  386. UNREFERENCED_PARAMETER(pInput);
  387. if(!SchannelInit(TRUE))
  388. {
  389. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  390. }
  391. DebugLog((DEB_TRACE, "RemoteCryptReleaseContextCallback\n"));
  392. pOutput->BufferType = SECBUFFER_DATA;
  393. pOutput->cbBuffer = 0;
  394. pOutput->pvBuffer = NULL;
  395. if(!CryptReleaseContext((HCRYPTPROV)hProv, (DWORD)dwFlags))
  396. {
  397. return SP_LOG_RESULT(GetLastError());
  398. }
  399. return SEC_E_OK;
  400. }
  401. BOOL
  402. RemoteCryptReleaseContext(
  403. HCRYPTPROV hProv,
  404. DWORD dwFlags)
  405. {
  406. SecBuffer Input;
  407. SecBuffer Output;
  408. DWORD Status;
  409. Input.BufferType = SECBUFFER_DATA;
  410. Input.cbBuffer = 0;
  411. Input.pvBuffer = NULL;
  412. Status = PerformApplicationCallback(SCH_RELEASE_CONTEXT_CALLBACK,
  413. (ULONG_PTR) hProv,
  414. (ULONG_PTR) dwFlags,
  415. &Input,
  416. &Output,
  417. FALSE);
  418. if(!NT_SUCCESS(Status))
  419. {
  420. DebugLog((SP_LOG_ERROR, "Error 0x%x releasing crypto context!\n", Status));
  421. SetLastError(Status);
  422. return FALSE;
  423. }
  424. return TRUE;
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // Function: UploadCertContextCallback
  429. //
  430. // Synopsis: Transfer a cert context structure from the application
  431. // process to the LSA process.
  432. //
  433. // Arguments: [Argument1] -- Not used.
  434. // [Argument2] -- Not used.
  435. //
  436. // [pInput] -- Buffer containing a cert context structure.
  437. //
  438. // [pOutput] -- Buffer containing the serialized certificate
  439. // context, etc.
  440. //
  441. // History: 09-23-97 jbanes Created
  442. //
  443. // Notes: The structure of the output buffer is as follows:
  444. //
  445. // HCRYPTPROV hProv;
  446. // DWORD cbSerializedCertContext;
  447. // PVOID pvSerializedCertContext;
  448. //
  449. // This function always uses an actual CSP.
  450. //
  451. //----------------------------------------------------------------------------
  452. SECURITY_STATUS
  453. UploadCertContextCallback(
  454. ULONG_PTR Argument1, // in
  455. ULONG_PTR Argument2, // in
  456. SecBuffer *pInput, // in
  457. SecBuffer *pOutput) // out
  458. {
  459. PCCERT_CONTEXT pCertContext;
  460. HCRYPTPROV hProv;
  461. DWORD cbProvHandle;
  462. DWORD cbCertContext;
  463. PBYTE pbBuffer;
  464. SECURITY_STATUS scRet = SEC_E_UNKNOWN_CREDENTIALS;
  465. UNREFERENCED_PARAMETER(Argument1);
  466. UNREFERENCED_PARAMETER(Argument2);
  467. if(!SchannelInit(TRUE))
  468. {
  469. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  470. }
  471. DebugLog((DEB_TRACE, "UploadCertContextCallback\n"));
  472. if(pInput->cbBuffer != sizeof(PCCERT_CONTEXT *) || pInput->pvBuffer == NULL)
  473. {
  474. return SP_LOG_RESULT(SEC_E_INCOMPLETE_MESSAGE);
  475. }
  476. pCertContext = *(PCCERT_CONTEXT *)pInput->pvBuffer;
  477. pOutput->cbBuffer = 0;
  478. pOutput->pvBuffer = NULL;
  479. pOutput->BufferType = SECBUFFER_DATA;
  480. // Attempt to read the hProv associated with the cert context.
  481. cbProvHandle = sizeof(HCRYPTPROV);
  482. if(!CertGetCertificateContextProperty(pCertContext,
  483. CERT_KEY_PROV_HANDLE_PROP_ID,
  484. (PVOID)&hProv,
  485. &cbProvHandle))
  486. {
  487. hProv = 0;
  488. cbProvHandle = sizeof(HCRYPTPROV);
  489. }
  490. // Determine the size of the serialized cert context.
  491. if(!CertSerializeCertificateStoreElement(
  492. pCertContext,
  493. 0,
  494. NULL,
  495. &cbCertContext))
  496. {
  497. scRet = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  498. goto Return;
  499. }
  500. //
  501. // Build output buffer.
  502. //
  503. // Allocate memory for the output buffer.
  504. pOutput->cbBuffer = sizeof(HCRYPTPROV) +
  505. sizeof(DWORD) + cbCertContext;
  506. pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer);
  507. if(pOutput->pvBuffer == NULL)
  508. {
  509. scRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  510. goto Return;
  511. }
  512. pbBuffer = pOutput->pvBuffer;
  513. // Place hProv in output buffer.
  514. *(HCRYPTPROV *)pbBuffer = hProv;
  515. pbBuffer += sizeof(HCRYPTPROV);
  516. // Place certificate context in output buffer.
  517. *(DWORD *)pbBuffer = cbCertContext;
  518. if(!CertSerializeCertificateStoreElement(
  519. pCertContext,
  520. 0,
  521. pbBuffer + sizeof(DWORD),
  522. &cbCertContext))
  523. {
  524. scRet = SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  525. goto Return;
  526. }
  527. scRet = SEC_E_OK;
  528. Return:
  529. if(!NT_SUCCESS(scRet) && (NULL != pOutput->pvBuffer))
  530. {
  531. SECURITY_STATUS Status;
  532. Status = FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  533. SP_ASSERT(NT_SUCCESS(Status));
  534. }
  535. return scRet;
  536. }
  537. //+---------------------------------------------------------------------------
  538. //
  539. // Function: UploadCertStoreCallback
  540. //
  541. // Synopsis: Transfer a cert store from the application
  542. // process to the LSA process, in the form of a serialized
  543. // certificate store.
  544. //
  545. // Arguments: [Argument1] -- Not used.
  546. // [Argument2] -- Not used.
  547. //
  548. // [pInput] -- Buffer containing a HCERTSTORE handle.
  549. //
  550. // [pOutput] -- Buffer containing the serialized cert store.
  551. //
  552. // History: 02-03-98 jbanes Created
  553. //
  554. // Notes: The structure of the output buffer is as follows:
  555. //
  556. // DWORD cbSerializedCertStore;
  557. // PVOID pvSerializedCertStore;
  558. //
  559. // This function always uses an actual CSP.
  560. //
  561. //----------------------------------------------------------------------------
  562. SECURITY_STATUS
  563. UploadCertStoreCallback(
  564. ULONG_PTR Argument1, // in
  565. ULONG_PTR Argument2, // in
  566. SecBuffer *pInput, // in
  567. SecBuffer *pOutput) // out
  568. {
  569. HCERTSTORE hStore;
  570. CRYPT_DATA_BLOB SaveBlob;
  571. DWORD cbCertStore;
  572. PBYTE pbBuffer;
  573. UNREFERENCED_PARAMETER(Argument1);
  574. UNREFERENCED_PARAMETER(Argument2);
  575. if(!SchannelInit(TRUE))
  576. {
  577. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  578. }
  579. DebugLog((DEB_TRACE, "UploadCertStoreCallback\n"));
  580. pOutput->cbBuffer = 0;
  581. pOutput->pvBuffer = NULL;
  582. pOutput->BufferType = SECBUFFER_DATA;
  583. if(pInput->cbBuffer != sizeof(HCERTSTORE) || pInput->pvBuffer == NULL)
  584. {
  585. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  586. }
  587. hStore = *(HCERTSTORE *)pInput->pvBuffer;
  588. // Determine the size of the serialized store.
  589. SaveBlob.cbData = 0;
  590. SaveBlob.pbData = NULL;
  591. if(!CertSaveStore(hStore,
  592. X509_ASN_ENCODING,
  593. CERT_STORE_SAVE_AS_STORE,
  594. CERT_STORE_SAVE_TO_MEMORY,
  595. (PVOID)&SaveBlob,
  596. 0))
  597. {
  598. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  599. }
  600. cbCertStore = SaveBlob.cbData;
  601. //
  602. // Build output buffer.
  603. //
  604. // Allocate memory for the output buffer.
  605. pOutput->cbBuffer = sizeof(DWORD) + cbCertStore;
  606. pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer);
  607. if(pOutput->pvBuffer == NULL)
  608. {
  609. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  610. }
  611. pbBuffer = pOutput->pvBuffer;
  612. // Place certificate store in output buffer.
  613. *(DWORD *)pbBuffer = cbCertStore;
  614. SaveBlob.cbData = cbCertStore;
  615. SaveBlob.pbData = pbBuffer + sizeof(DWORD);
  616. if(!CertSaveStore(hStore,
  617. X509_ASN_ENCODING,
  618. CERT_STORE_SAVE_AS_STORE,
  619. CERT_STORE_SAVE_TO_MEMORY,
  620. (PVOID)&SaveBlob,
  621. 0))
  622. {
  623. FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  624. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  625. }
  626. return SEC_E_OK;
  627. }
  628. SP_STATUS
  629. SignHashUsingCallback(
  630. HCRYPTPROV hProv,
  631. DWORD dwKeySpec,
  632. ALG_ID aiHash,
  633. PBYTE pbHash,
  634. DWORD cbHash,
  635. PBYTE pbSignature,
  636. PDWORD pcbSignature,
  637. DWORD fHashData)
  638. {
  639. SecBuffer Input;
  640. SecBuffer Output;
  641. SP_STATUS pctRet;
  642. //
  643. // Build input buffer.
  644. //
  645. Input.BufferType = SECBUFFER_DATA;
  646. Input.cbBuffer = sizeof(DWORD) * 2 + cbHash;
  647. Input.pvBuffer = SPExternalAlloc(Input.cbBuffer);
  648. if(Input.pvBuffer == NULL)
  649. {
  650. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  651. }
  652. memcpy(Input.pvBuffer, (PBYTE)&dwKeySpec, sizeof(DWORD));
  653. memcpy((PBYTE)Input.pvBuffer + sizeof(DWORD), (PBYTE)&fHashData, sizeof(DWORD));
  654. memcpy((PBYTE)Input.pvBuffer + sizeof(DWORD) * 2,
  655. pbHash,
  656. cbHash);
  657. //
  658. // Callback into application process.
  659. //
  660. pctRet = PerformApplicationCallback(SCH_SIGNATURE_CALLBACK,
  661. hProv,
  662. aiHash,
  663. &Input,
  664. &Output,
  665. TRUE);
  666. SPExternalFree(Input.pvBuffer);
  667. if(pctRet != PCT_ERR_OK)
  668. {
  669. return pctRet;
  670. }
  671. if(Output.cbBuffer > *pcbSignature)
  672. {
  673. *pcbSignature = Output.cbBuffer;
  674. SPExternalFree(Output.pvBuffer);
  675. return SP_LOG_RESULT(SEC_E_BUFFER_TOO_SMALL);
  676. }
  677. *pcbSignature = Output.cbBuffer;
  678. memcpy(pbSignature, Output.pvBuffer, Output.cbBuffer);
  679. SPExternalFree(Output.pvBuffer);
  680. return PCT_ERR_OK;
  681. }
  682. //+---------------------------------------------------------------------------
  683. //
  684. // Function: SPSignatureCallback
  685. //
  686. // Synopsis: Perform signature, using application's hProv
  687. //
  688. // Arguments: [hProv] --
  689. // [aiHash] --
  690. // [pInput] --
  691. // [pOutput] --
  692. //
  693. // History: 09-23-97 jbanes Created
  694. //
  695. // Notes: This function always uses an actual CSP.
  696. //
  697. //----------------------------------------------------------------------------
  698. SECURITY_STATUS
  699. SPSignatureCallback(ULONG_PTR hProv, // in
  700. ULONG_PTR aiHash, // in
  701. SecBuffer *pInput, // in
  702. SecBuffer *pOutput) // out
  703. {
  704. HCRYPTHASH hHash;
  705. DWORD dwKeySpec;
  706. DWORD fHashData;
  707. PBYTE pbHash;
  708. DWORD cbHash;
  709. SP_STATUS pctRet;
  710. if(!SchannelInit(TRUE))
  711. {
  712. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  713. }
  714. DebugLog((DEB_TRACE, "SPSignatureCallback\n"));
  715. //
  716. // Parse input buffer.
  717. //
  718. if(pInput->cbBuffer < sizeof(DWORD) * 2)
  719. {
  720. return SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  721. }
  722. memcpy(&dwKeySpec, pInput->pvBuffer, sizeof(DWORD));
  723. memcpy(&fHashData, (PBYTE)pInput->pvBuffer + sizeof(DWORD), sizeof(DWORD));
  724. pbHash = (PBYTE)pInput->pvBuffer + sizeof(DWORD) * 2;
  725. cbHash = pInput->cbBuffer - sizeof(DWORD) * 2;
  726. //
  727. // Prepare hash object.
  728. //
  729. if(!CryptCreateHash(hProv, (ALG_ID)aiHash, 0, 0, &hHash))
  730. {
  731. SP_LOG_RESULT( GetLastError() );
  732. return PCT_ERR_ILLEGAL_MESSAGE;
  733. }
  734. if(!fHashData)
  735. {
  736. // set hash value
  737. if(!CryptSetHashParam(hHash, HP_HASHVAL, pbHash, 0))
  738. {
  739. SP_LOG_RESULT( GetLastError() );
  740. CryptDestroyHash(hHash);
  741. return PCT_ERR_ILLEGAL_MESSAGE;
  742. }
  743. }
  744. else
  745. {
  746. if(!CryptHashData(hHash, pbHash, cbHash, 0))
  747. {
  748. SP_LOG_RESULT( GetLastError() );
  749. CryptDestroyHash(hHash);
  750. return PCT_ERR_ILLEGAL_MESSAGE;
  751. }
  752. }
  753. //
  754. // Sign hash.
  755. //
  756. pOutput->BufferType = SECBUFFER_DATA;
  757. // Get size of signature
  758. if(!CryptSignHash(hHash, dwKeySpec, NULL, 0, NULL, &pOutput->cbBuffer))
  759. {
  760. pctRet = SP_LOG_RESULT(GetLastError());
  761. CryptDestroyHash(hHash);
  762. return pctRet;
  763. }
  764. // Allocate memory
  765. pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer);
  766. if(pOutput->pvBuffer == NULL)
  767. {
  768. CryptDestroyHash(hHash);
  769. return SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  770. }
  771. // Sign hash.
  772. if(!CryptSignHash(hHash, dwKeySpec, NULL, 0, pOutput->pvBuffer, &pOutput->cbBuffer))
  773. {
  774. pctRet = SP_LOG_RESULT(GetLastError());
  775. CryptDestroyHash(hHash);
  776. FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  777. return pctRet;
  778. }
  779. CryptDestroyHash(hHash);
  780. return PCT_ERR_OK;
  781. }
  782. //+---------------------------------------------------------------------------
  783. //
  784. // Function: DownloadCertContextCallBack
  785. //
  786. // Synopsis: Transfer a cert context structure from the application
  787. // process to the LSA process, in the form of a serialized
  788. // certificate store.
  789. //
  790. // Arguments: [Argument1] -- Not used.
  791. // [Argument2] -- Not used.
  792. // [pInput] --
  793. // [pOutput] --
  794. //
  795. // History: 09-26-97 jbanes Created
  796. //
  797. // Notes: The structure of the input buffer is as follows:
  798. //
  799. // DWORD cbSerializedCertStore;
  800. // PVOID pvSerializedCertStore;
  801. // DWORD cbSerializedCertContext;
  802. // PVOID pvSerializedCertContext;
  803. //
  804. // This function always uses an actual CSP.
  805. //
  806. //----------------------------------------------------------------------------
  807. SECURITY_STATUS
  808. DownloadCertContextCallback(
  809. ULONG_PTR Argument1, // in
  810. ULONG_PTR Argument2, // in
  811. SecBuffer *pInput, // in
  812. SecBuffer *pOutput) // out
  813. {
  814. PCCERT_CONTEXT pCertContext;
  815. SECURITY_STATUS scRet;
  816. UNREFERENCED_PARAMETER(Argument1);
  817. UNREFERENCED_PARAMETER(Argument2);
  818. if(!SchannelInit(TRUE))
  819. {
  820. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  821. }
  822. DebugLog((DEB_TRACE, "DownloadCertContextCallback\n"));
  823. // Allocate memory for output buffer.
  824. pOutput->BufferType = SECBUFFER_DATA;
  825. pOutput->cbBuffer = sizeof(PVOID);
  826. pOutput->pvBuffer = PvExtVirtualAlloc(pOutput->cbBuffer);
  827. if(pOutput->pvBuffer == NULL)
  828. {
  829. return SP_LOG_RESULT( SEC_E_INSUFFICIENT_MEMORY );
  830. }
  831. // Deserialize buffer.
  832. scRet = DeserializeCertContext(&pCertContext,
  833. pInput->pvBuffer,
  834. pInput->cbBuffer);
  835. if(FAILED(scRet))
  836. {
  837. FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  838. return SP_LOG_RESULT( scRet );
  839. }
  840. // Place cert context pointer in output buffer.
  841. *(PCCERT_CONTEXT *)pOutput->pvBuffer = pCertContext;
  842. return SEC_E_OK;
  843. }
  844. //+---------------------------------------------------------------------------
  845. //
  846. // Function: SerializeCertContext
  847. //
  848. // Synopsis: Serialize the specified certificate context, along with its
  849. // associated certificate store.
  850. //
  851. // Arguments: [pCertContext] --
  852. // [pbBuffer] --
  853. // [pcbBuffer] --
  854. //
  855. // History: 09-26-97 jbanes Created
  856. //
  857. // Notes: The structure of the output buffer is as follows:
  858. //
  859. // DWORD cbSerializedCertStore
  860. // PVOID pvSerializedCertStore
  861. // DWORD cbSerializedCertContext
  862. // PVOID pvSerializedCertContext
  863. //
  864. //----------------------------------------------------------------------------
  865. SECURITY_STATUS
  866. SerializeCertContext(
  867. PCCERT_CONTEXT pCertContext, // in
  868. PBYTE pbBuffer, // out
  869. PDWORD pcbBuffer) // out
  870. {
  871. CRYPT_DATA_BLOB SaveBlob;
  872. DWORD cbCertContext;
  873. DWORD cbCertStore;
  874. DWORD cbBuffer;
  875. if(pCertContext == NULL)
  876. {
  877. *pcbBuffer = 0;
  878. return SEC_E_OK;
  879. }
  880. // Determine the size of the serialized cert context.
  881. if(!CertSerializeCertificateStoreElement(
  882. pCertContext,
  883. 0,
  884. NULL,
  885. &cbCertContext))
  886. {
  887. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  888. }
  889. // Determine the size of the serialized store.
  890. if(pCertContext->hCertStore)
  891. {
  892. SaveBlob.cbData = 0;
  893. SaveBlob.pbData = NULL;
  894. if(!CertSaveStore(pCertContext->hCertStore,
  895. X509_ASN_ENCODING,
  896. CERT_STORE_SAVE_AS_STORE,
  897. CERT_STORE_SAVE_TO_MEMORY,
  898. (PVOID)&SaveBlob,
  899. 0))
  900. {
  901. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  902. }
  903. cbCertStore = SaveBlob.cbData;
  904. }
  905. else
  906. {
  907. cbCertStore = 0;
  908. }
  909. cbBuffer = sizeof(DWORD) + cbCertContext +
  910. sizeof(DWORD) + cbCertStore;
  911. if(pbBuffer == NULL)
  912. {
  913. *pcbBuffer = cbBuffer;
  914. return SEC_E_OK;
  915. }
  916. if(*pcbBuffer < cbBuffer)
  917. {
  918. return SP_LOG_RESULT(SEC_E_BUFFER_TOO_SMALL);
  919. }
  920. // Set output values.
  921. *pcbBuffer = cbBuffer;
  922. // Place certificate store in output buffer.
  923. *(DWORD *)pbBuffer = cbCertStore;
  924. if(pCertContext->hCertStore)
  925. {
  926. SaveBlob.cbData = cbCertStore;
  927. SaveBlob.pbData = pbBuffer + sizeof(DWORD);
  928. if(!CertSaveStore(pCertContext->hCertStore,
  929. X509_ASN_ENCODING,
  930. CERT_STORE_SAVE_AS_STORE,
  931. CERT_STORE_SAVE_TO_MEMORY,
  932. (PVOID)&SaveBlob,
  933. 0))
  934. {
  935. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  936. }
  937. }
  938. pbBuffer += sizeof(DWORD) + cbCertStore;
  939. // Place certificate context in output buffer.
  940. *(DWORD UNALIGNED *)pbBuffer = cbCertContext;
  941. if(!CertSerializeCertificateStoreElement(
  942. pCertContext,
  943. 0,
  944. pbBuffer + sizeof(DWORD),
  945. &cbCertContext))
  946. {
  947. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  948. }
  949. return SEC_E_OK;
  950. }
  951. SECURITY_STATUS
  952. DeserializeCertContext(
  953. PCCERT_CONTEXT *ppCertContext, // out
  954. PBYTE pbBuffer, // in
  955. DWORD cbBuffer) // in
  956. {
  957. CRYPT_DATA_BLOB Serialized;
  958. HCERTSTORE hStore;
  959. DWORD cbCertContext;
  960. if(cbBuffer < sizeof(DWORD))
  961. {
  962. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  963. }
  964. //
  965. // Deserialize certificate store.
  966. //
  967. Serialized.cbData = *(DWORD *)pbBuffer;
  968. Serialized.pbData = pbBuffer + sizeof(DWORD);
  969. if(cbBuffer < sizeof(DWORD) + Serialized.cbData)
  970. {
  971. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  972. }
  973. hStore = CertOpenStore( CERT_STORE_PROV_SERIALIZED,
  974. X509_ASN_ENCODING,
  975. 0,
  976. CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
  977. &Serialized);
  978. if(hStore == NULL)
  979. {
  980. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  981. }
  982. pbBuffer += sizeof(DWORD) + Serialized.cbData;
  983. cbBuffer -= sizeof(DWORD) + Serialized.cbData;
  984. //
  985. // Deserialize certificate context.
  986. //
  987. if(cbBuffer < sizeof(DWORD))
  988. {
  989. CertCloseStore(hStore, 0);
  990. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  991. }
  992. cbCertContext = *(DWORD UNALIGNED *)pbBuffer;
  993. if(cbBuffer < sizeof(DWORD) + cbCertContext)
  994. {
  995. CertCloseStore(hStore, 0);
  996. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  997. }
  998. if(!CertAddSerializedElementToStore(hStore,
  999. pbBuffer + sizeof(DWORD),
  1000. cbCertContext,
  1001. CERT_STORE_ADD_USE_EXISTING,
  1002. 0,
  1003. CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
  1004. NULL,
  1005. ppCertContext))
  1006. {
  1007. CertCloseStore(hStore, 0);
  1008. return SP_LOG_RESULT(SEC_E_UNKNOWN_CREDENTIALS);
  1009. }
  1010. if(!CertCloseStore(hStore, 0))
  1011. {
  1012. SP_LOG_RESULT(GetLastError());
  1013. }
  1014. return SEC_E_OK;
  1015. }
  1016. //+---------------------------------------------------------------------------
  1017. //
  1018. // Function: SPGetApplicationKeys
  1019. //
  1020. // Synopsis: Callback to the user process and retrieve the user encryption
  1021. // keys.
  1022. //
  1023. // Arguments: [pContext] -- Schannel context.
  1024. // [dwFlags] -- SCH_FLAG_READ_KEY, SCH_FLAG_WRITE_KEY
  1025. //
  1026. // History: 10-17-97 jbanes Created
  1027. //
  1028. // Notes:
  1029. //
  1030. //----------------------------------------------------------------------------
  1031. SP_STATUS
  1032. SPGetUserKeys(
  1033. PSPContext pContext,
  1034. DWORD dwFlags)
  1035. {
  1036. PBYTE pbBuffer;
  1037. PBYTE pbReadKey;
  1038. DWORD cbReadKey;
  1039. PBYTE pbWriteKey;
  1040. DWORD cbWriteKey;
  1041. SecBuffer Input;
  1042. SecBuffer Output;
  1043. SECURITY_STATUS scRet;
  1044. BOOL fWow64Client = FALSE;
  1045. #ifdef _WIN64
  1046. SECPKG_CALL_INFO CallInfo;
  1047. #endif
  1048. //
  1049. // Call back into the application process and get the keys, in the
  1050. // form of 2 opaque blobs.
  1051. //
  1052. DebugLog((SP_LOG_TRACE, "SPGetUserKeys: 0x%p, %d\n", pContext, dwFlags));
  1053. if(LsaTable == NULL)
  1054. {
  1055. // We're probably being called from the application process.
  1056. return SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
  1057. }
  1058. #ifdef _WIN64
  1059. if(!LsaTable->GetCallInfo(&CallInfo))
  1060. {
  1061. scRet = STATUS_INTERNAL_ERROR;
  1062. return SP_LOG_RESULT(scRet);
  1063. }
  1064. fWow64Client = (CallInfo.Attributes & SECPKG_CALL_WOWCLIENT) != 0;
  1065. #endif
  1066. if(fWow64Client)
  1067. {
  1068. Input.BufferType = SECBUFFER_DATA;
  1069. Input.cbBuffer = sizeof(pContext->ContextThumbprint);
  1070. Input.pvBuffer = &pContext->ContextThumbprint;
  1071. }
  1072. else
  1073. {
  1074. Input.BufferType = SECBUFFER_DATA;
  1075. Input.cbBuffer = 0;
  1076. Input.pvBuffer = NULL;
  1077. }
  1078. scRet = PerformApplicationCallback( SCH_GET_USER_KEYS,
  1079. (ULONG_PTR) pContext,
  1080. (ULONG_PTR) dwFlags,
  1081. &Input,
  1082. &Output,
  1083. TRUE);
  1084. if(!NT_SUCCESS(scRet))
  1085. {
  1086. DebugLog((SP_LOG_ERROR, "Error 0x%x retrieving user keys\n", scRet));
  1087. return SP_LOG_RESULT(PCT_INT_INTERNAL_ERROR);
  1088. }
  1089. //
  1090. // Parse output buffer
  1091. //
  1092. pbBuffer = Output.pvBuffer;
  1093. if(Output.cbBuffer < sizeof(DWORD) * 4)
  1094. {
  1095. return SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
  1096. }
  1097. if(dwFlags & SCH_FLAG_READ_KEY)
  1098. {
  1099. pContext->ReadCounter = *(PDWORD)pbBuffer;
  1100. }
  1101. pbBuffer += sizeof(DWORD);
  1102. if(dwFlags & SCH_FLAG_WRITE_KEY)
  1103. {
  1104. pContext->WriteCounter = *(PDWORD)pbBuffer;
  1105. }
  1106. pbBuffer += sizeof(DWORD);
  1107. cbReadKey = *(PDWORD)pbBuffer;
  1108. pbBuffer += sizeof(DWORD);
  1109. cbWriteKey = *(PDWORD)pbBuffer;
  1110. pbBuffer += sizeof(DWORD);
  1111. if(Output.cbBuffer < sizeof(DWORD) * 4 + cbReadKey + cbWriteKey)
  1112. {
  1113. return SP_LOG_RESULT(STATUS_INVALID_PARAMETER);
  1114. }
  1115. pbReadKey = pbBuffer;
  1116. pbBuffer += cbReadKey;
  1117. pbWriteKey = pbBuffer;
  1118. pbBuffer += cbWriteKey;
  1119. SP_ASSERT(pbBuffer - (PBYTE)Output.pvBuffer == (INT)Output.cbBuffer);
  1120. //
  1121. // Place keys into context structure.
  1122. //
  1123. if(dwFlags & SCH_FLAG_READ_KEY)
  1124. {
  1125. if(cbReadKey)
  1126. {
  1127. if(!CryptImportKey(pContext->RipeZombie->hMasterProv,
  1128. pbReadKey,
  1129. cbReadKey,
  1130. 0,
  1131. CRYPT_EXPORTABLE,
  1132. &pContext->hReadKey))
  1133. {
  1134. SP_LOG_RESULT(GetLastError());
  1135. scRet = PCT_INT_INTERNAL_ERROR;
  1136. goto done;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. pContext->hReadKey = 0;
  1142. }
  1143. }
  1144. if(dwFlags & SCH_FLAG_WRITE_KEY)
  1145. {
  1146. if(cbWriteKey)
  1147. {
  1148. if(!CryptImportKey(pContext->RipeZombie->hMasterProv,
  1149. pbWriteKey,
  1150. cbWriteKey,
  1151. 0,
  1152. CRYPT_EXPORTABLE,
  1153. &pContext->hWriteKey))
  1154. {
  1155. SP_LOG_RESULT(GetLastError());
  1156. scRet = PCT_INT_INTERNAL_ERROR;
  1157. goto done;
  1158. }
  1159. }
  1160. else
  1161. {
  1162. pContext->hWriteKey = 0;
  1163. }
  1164. }
  1165. done:
  1166. SPExternalFree(Output.pvBuffer);
  1167. return scRet;
  1168. }
  1169. //+---------------------------------------------------------------------------
  1170. //
  1171. // Function: GetUserKeysCallback
  1172. //
  1173. // Synopsis: Find the user context that corresponds to the passed in LSA
  1174. // context, serialize the encryption keys, and return them in
  1175. // the output buffer.
  1176. //
  1177. // Arguments: [dwLsaContext] -- Pointer to LSA Schannel context.
  1178. // [dwFlags] -- SCH_FLAG_READ_KEY, SCH_FLAG_WRITE_KEY
  1179. // [pInput] -- Not used.
  1180. // [pOutput] -- (output) Serialized keys.
  1181. //
  1182. // History: 10-17-97 jbanes Created
  1183. //
  1184. // Notes: The structure of the output buffer is as follows:
  1185. //
  1186. // DWORD dwReadSequence;
  1187. // DWORD dwWriteSequence;
  1188. // DWORD cbReadKey;
  1189. // BYTE rgbReadKey[];
  1190. // DWORD cbWriteKey;
  1191. // BYTE rgbWriteKey[];
  1192. //
  1193. //----------------------------------------------------------------------------
  1194. SECURITY_STATUS
  1195. GetUserKeysCallback(
  1196. ULONG_PTR dwLsaContext,
  1197. ULONG_PTR dwFlags,
  1198. SecBuffer *pInput,
  1199. SecBuffer *pOutput)
  1200. {
  1201. DWORD cbReadKey = 0;
  1202. DWORD cbWriteKey = 0;
  1203. DWORD cbData;
  1204. PBYTE pbBuffer;
  1205. DWORD cbBuffer;
  1206. PSPContext pContext;
  1207. PSSL_USER_CONTEXT pUserContext;
  1208. if(!SchannelInit(TRUE))
  1209. {
  1210. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  1211. }
  1212. DebugLog((DEB_TRACE, "GetUserKeysCallback\n"));
  1213. //
  1214. // Find the user context.
  1215. //
  1216. if(pInput->pvBuffer != NULL &&
  1217. pInput->cbBuffer == sizeof(CRED_THUMBPRINT))
  1218. {
  1219. // Search for matching context thumbprint.
  1220. pUserContext = SslFindUserContextEx((PCRED_THUMBPRINT)pInput->pvBuffer);
  1221. if(pUserContext == NULL)
  1222. {
  1223. return SP_LOG_RESULT( SEC_E_INVALID_HANDLE );
  1224. }
  1225. }
  1226. else
  1227. {
  1228. // Search for matching lsa context
  1229. pUserContext = SslFindUserContext(dwLsaContext);
  1230. if(pUserContext == NULL)
  1231. {
  1232. return SP_LOG_RESULT( SEC_E_INVALID_HANDLE );
  1233. }
  1234. }
  1235. pContext = pUserContext->pContext;
  1236. if(pContext == NULL)
  1237. {
  1238. return SP_LOG_RESULT( SEC_E_INTERNAL_ERROR );
  1239. }
  1240. //
  1241. // Compute size of output buffer.
  1242. //
  1243. if(dwFlags & SCH_FLAG_READ_KEY)
  1244. {
  1245. if(pContext->pReadCipherInfo->aiCipher != CALG_NULLCIPHER)
  1246. {
  1247. if(!pContext->hReadKey)
  1248. {
  1249. return SP_LOG_RESULT( SEC_E_INVALID_HANDLE );
  1250. }
  1251. if(!CryptExportKey(pContext->hReadKey,
  1252. 0, OPAQUEKEYBLOB, 0,
  1253. NULL,
  1254. &cbReadKey))
  1255. {
  1256. SP_LOG_RESULT(GetLastError());
  1257. return SEC_E_INTERNAL_ERROR;
  1258. }
  1259. }
  1260. else
  1261. {
  1262. cbReadKey = 0;
  1263. }
  1264. }
  1265. if(dwFlags & SCH_FLAG_WRITE_KEY)
  1266. {
  1267. if(pContext->pWriteCipherInfo->aiCipher != CALG_NULLCIPHER)
  1268. {
  1269. if(!pContext->hWriteKey)
  1270. {
  1271. return SP_LOG_RESULT( SEC_E_INVALID_HANDLE );
  1272. }
  1273. if(!CryptExportKey(pContext->hWriteKey,
  1274. 0, OPAQUEKEYBLOB, 0,
  1275. NULL,
  1276. &cbWriteKey))
  1277. {
  1278. SP_LOG_RESULT(GetLastError());
  1279. return SEC_E_INTERNAL_ERROR;
  1280. }
  1281. }
  1282. else
  1283. {
  1284. cbWriteKey = 0;
  1285. }
  1286. }
  1287. cbBuffer = sizeof(DWORD) +
  1288. sizeof(DWORD) +
  1289. sizeof(DWORD) + cbReadKey +
  1290. sizeof(DWORD) + cbWriteKey;
  1291. // Allocate memory for output buffer.
  1292. pbBuffer = PvExtVirtualAlloc( cbBuffer);
  1293. if(pbBuffer == NULL)
  1294. {
  1295. return SP_LOG_RESULT( SEC_E_INSUFFICIENT_MEMORY );
  1296. }
  1297. pOutput->BufferType = SECBUFFER_DATA;
  1298. pOutput->cbBuffer = cbBuffer;
  1299. pOutput->pvBuffer = pbBuffer;
  1300. //
  1301. // Serialize keys.
  1302. //
  1303. *(PDWORD)pbBuffer = pContext->ReadCounter;
  1304. pbBuffer += sizeof(DWORD);
  1305. *(PDWORD)pbBuffer = pContext->WriteCounter;
  1306. pbBuffer += sizeof(DWORD);
  1307. *(PDWORD)pbBuffer = cbReadKey;
  1308. pbBuffer += sizeof(DWORD);
  1309. *(PDWORD)pbBuffer = cbWriteKey;
  1310. pbBuffer += sizeof(DWORD);
  1311. if(dwFlags & SCH_FLAG_READ_KEY)
  1312. {
  1313. if(pContext->pReadCipherInfo->aiCipher != CALG_NULLCIPHER)
  1314. {
  1315. cbData = cbReadKey;
  1316. if(!CryptExportKey(pContext->hReadKey,
  1317. 0, OPAQUEKEYBLOB, 0,
  1318. pbBuffer,
  1319. &cbData))
  1320. {
  1321. FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  1322. SP_LOG_RESULT(GetLastError());
  1323. return SEC_E_INTERNAL_ERROR;
  1324. }
  1325. if(!CryptDestroyKey(pContext->hReadKey))
  1326. {
  1327. SP_LOG_RESULT(GetLastError());
  1328. }
  1329. }
  1330. pContext->hReadKey = 0;
  1331. }
  1332. pbBuffer += cbReadKey;
  1333. if(dwFlags & SCH_FLAG_WRITE_KEY)
  1334. {
  1335. if(pContext->pWriteCipherInfo->aiCipher != CALG_NULLCIPHER)
  1336. {
  1337. cbData = cbWriteKey;
  1338. if(!CryptExportKey(pContext->hWriteKey,
  1339. 0, OPAQUEKEYBLOB, 0,
  1340. pbBuffer,
  1341. &cbData))
  1342. {
  1343. FreeExtVirtualAlloc(pOutput->pvBuffer, pOutput->cbBuffer);
  1344. SP_LOG_RESULT(GetLastError());
  1345. return SEC_E_INTERNAL_ERROR;
  1346. }
  1347. if(!CryptDestroyKey(pContext->hWriteKey))
  1348. {
  1349. SP_LOG_RESULT(GetLastError());
  1350. }
  1351. }
  1352. pContext->hWriteKey = 0;
  1353. }
  1354. pbBuffer += cbWriteKey;
  1355. return SEC_E_OK;
  1356. }
  1357. // Always called from callback routine (in the application process).
  1358. VOID *
  1359. PvExtVirtualAlloc(DWORD cb)
  1360. {
  1361. SECURITY_STATUS Status;
  1362. PVOID pv = NULL;
  1363. SIZE_T Size = cb;
  1364. Status = NtAllocateVirtualMemory(
  1365. GetCurrentProcess(),
  1366. &pv,
  1367. 0,
  1368. &Size,
  1369. MEM_COMMIT,
  1370. PAGE_READWRITE);
  1371. if(!NT_SUCCESS(Status))
  1372. {
  1373. pv = NULL;
  1374. }
  1375. DebugLog((DEB_TRACE, "SslCallbackVirtualAlloc: 0x%x bytes at 0x%x\n", cb, pv));
  1376. return(pv);
  1377. }
  1378. // Always called from callback routine (in the application process),
  1379. // typically when an error occurs and we're cleaning up.
  1380. SECURITY_STATUS
  1381. FreeExtVirtualAlloc(PVOID pv, SIZE_T cbMem)
  1382. {
  1383. cbMem = 0;
  1384. return(NtFreeVirtualMemory(GetCurrentProcess(),
  1385. &pv,
  1386. &cbMem,
  1387. MEM_RELEASE));
  1388. }
  1389. // Always called from the LSA process, when freeing memory allocated
  1390. // by a callback function.
  1391. SECURITY_STATUS
  1392. SPFreeUserAllocMemory(PVOID pv, SIZE_T cbMem)
  1393. {
  1394. SECPKG_CALL_INFO CallInfo;
  1395. if(LsaTable->GetCallInfo(&CallInfo))
  1396. {
  1397. SECURITY_STATUS Status;
  1398. HANDLE hProcess;
  1399. hProcess = OpenProcess(PROCESS_VM_OPERATION,
  1400. FALSE,
  1401. CallInfo.ProcessId);
  1402. if(hProcess == NULL)
  1403. {
  1404. return SP_LOG_RESULT(GetLastError());
  1405. }
  1406. cbMem = 0;
  1407. Status = NtFreeVirtualMemory(hProcess,
  1408. &pv,
  1409. &cbMem,
  1410. MEM_RELEASE);
  1411. if(!NT_SUCCESS(Status))
  1412. {
  1413. SP_LOG_RESULT(Status);
  1414. }
  1415. CloseHandle(hProcess);
  1416. }
  1417. DebugLog((DEB_TRACE, "SslCallbackVirtualFree: 0x%x bytes at 0x%x\n", cbMem, pv));
  1418. return SEC_E_OK;
  1419. }