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.

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