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.

1558 lines
43 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: usermode.c
  7. //
  8. // Contents: User mode functions
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 10-08-96 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "sslp.h"
  18. #include <ssl2msg.h>
  19. #include <ssl3msg.h>
  20. #include <pct1msg.h>
  21. #include <mapper.h>
  22. // Counter for exported handles
  23. ULONG_PTR ExportedContext = 0;
  24. SECURITY_STATUS
  25. UpdateContextUsrToLsa(IN LSA_SEC_HANDLE hContextHandle);
  26. SECPKG_USER_FUNCTION_TABLE SslTable[ 2 ] =
  27. {
  28. {
  29. SpInstanceInit,
  30. SpInitUserModeContext,
  31. SpMakeSignature,
  32. SpVerifySignature,
  33. SpSealMessage,
  34. SpUnsealMessage,
  35. SpGetContextToken,
  36. SpUserQueryContextAttributes,
  37. SpCompleteAuthToken,
  38. SpDeleteUserModeContext,
  39. SpFormatCredentials,
  40. SpMarshallSupplementalCreds,
  41. SpExportSecurityContext,
  42. SpImportSecurityContext
  43. },
  44. {
  45. SpInstanceInit,
  46. SpInitUserModeContext,
  47. SpMakeSignature,
  48. SpVerifySignature,
  49. SpSealMessage,
  50. SpUnsealMessage,
  51. SpGetContextToken,
  52. SpUserQueryContextAttributes,
  53. SpCompleteAuthToken,
  54. SpDeleteUserModeContext,
  55. SpFormatCredentials,
  56. SpMarshallSupplementalCreds,
  57. SpExportSecurityContext,
  58. SpImportSecurityContext
  59. }
  60. };
  61. NTSTATUS
  62. SEC_ENTRY
  63. SpUserModeInitialize(
  64. IN ULONG LsaVersion,
  65. OUT PULONG PackageVersion,
  66. OUT PSECPKG_USER_FUNCTION_TABLE * UserFunctionTable,
  67. OUT PULONG pcTables)
  68. {
  69. if (LsaVersion != SECPKG_INTERFACE_VERSION)
  70. {
  71. DebugLog((DEB_ERROR,"Invalid LSA version: %d\n", LsaVersion));
  72. return(STATUS_INVALID_PARAMETER);
  73. }
  74. *PackageVersion = SECPKG_INTERFACE_VERSION ;
  75. *UserFunctionTable = &SslTable[0] ;
  76. *pcTables = 2;
  77. SslInitContextManager();
  78. return( STATUS_SUCCESS );
  79. }
  80. NTSTATUS NTAPI
  81. SpInstanceInit(
  82. IN ULONG Version,
  83. IN PSECPKG_DLL_FUNCTIONS DllFunctionTable,
  84. OUT PVOID * UserFunctionTable
  85. )
  86. {
  87. NTSTATUS Status;
  88. DWORD i;
  89. // Register callback functions.
  90. for(i = 0; i < g_cSchannelCallbacks; i++)
  91. {
  92. Status = DllFunctionTable->RegisterCallback(
  93. g_SchannelCallbacks[i].dwTag,
  94. g_SchannelCallbacks[i].pFunction);
  95. if(Status != STATUS_SUCCESS)
  96. {
  97. return Status;
  98. }
  99. }
  100. return(STATUS_SUCCESS);
  101. }
  102. //+-------------------------------------------------------------------------
  103. //
  104. // Function: SpDeleteUserModeContext
  105. //
  106. // Synopsis: Deletes a user mode context by unlinking it and then
  107. // dereferencing it.
  108. //
  109. // Effects:
  110. //
  111. // Arguments: ContextHandle - Lsa context handle of the context to delete
  112. //
  113. // Requires:
  114. //
  115. // Returns: STATUS_SUCCESS on success, STATUS_INVALID_HANDLE if the
  116. // context can't be located
  117. //
  118. // Notes:
  119. //
  120. //
  121. //--------------------------------------------------------------------------
  122. NTSTATUS NTAPI
  123. SpDeleteUserModeContext(
  124. IN LSA_SEC_HANDLE ContextHandle
  125. )
  126. {
  127. SslDeleteUserContext( ContextHandle );
  128. return( SEC_E_OK );
  129. }
  130. //+-------------------------------------------------------------------------
  131. //
  132. // Function: SpInitUserModeContext
  133. //
  134. // Synopsis: Creates a user-mode context from a packed LSA mode context
  135. //
  136. // Effects:
  137. //
  138. // Arguments: ContextHandle - Lsa mode context handle for the context
  139. // PackedContext - A marshalled buffer containing the LSA
  140. // mode context.
  141. //
  142. // Requires:
  143. //
  144. // Returns: STATUS_SUCCESS or STATUS_INSUFFICIENT_RESOURCES
  145. //
  146. // Notes:
  147. //
  148. //
  149. //--------------------------------------------------------------------------
  150. NTSTATUS NTAPI
  151. SpInitUserModeContext(
  152. IN LSA_SEC_HANDLE ContextHandle,
  153. IN PSecBuffer PackedContext
  154. )
  155. {
  156. SECURITY_STATUS scRet ;
  157. if(!SchannelInit(TRUE))
  158. {
  159. return SP_LOG_RESULT(SEC_E_INTERNAL_ERROR);
  160. }
  161. scRet = SslAddUserContext( ContextHandle, NULL, PackedContext, FALSE );
  162. if ( NT_SUCCESS( scRet ) )
  163. {
  164. if(g_pFreeContextBuffer)
  165. {
  166. g_pFreeContextBuffer( PackedContext->pvBuffer );
  167. }
  168. }
  169. return( scRet );
  170. }
  171. //+-------------------------------------------------------------------------
  172. //
  173. // Function: SpMakeSignature
  174. //
  175. // Synopsis: Signs a message buffer by calculatinga checksum over all
  176. // the non-read only data buffers and encrypting the checksum
  177. // along with a nonce.
  178. //
  179. // Effects:
  180. //
  181. // Arguments: ContextHandle - Handle of the context to use to sign the
  182. // message.
  183. // QualityOfProtection - Unused flags.
  184. // MessageBuffers - Contains an array of buffers to sign and
  185. // to store the signature.
  186. // MessageSequenceNumber - Sequence number for this message,
  187. // only used in datagram cases.
  188. //
  189. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  190. // was not configured for message integrity.
  191. // STATUS_INVALID_PARAMETER - the signature buffer could not
  192. // be found.
  193. // STATUS_BUFFER_TOO_SMALL - the signature buffer is too small
  194. // to hold the signature
  195. //
  196. // Returns:
  197. //
  198. // Notes:
  199. //
  200. //
  201. //--------------------------------------------------------------------------
  202. NTSTATUS NTAPI
  203. SpMakeSignature(
  204. IN LSA_SEC_HANDLE ContextHandle,
  205. IN ULONG QualityOfProtection,
  206. IN PSecBufferDesc MessageBuffers,
  207. IN ULONG MessageSequenceNumber
  208. )
  209. {
  210. return( SEC_E_UNSUPPORTED_FUNCTION );
  211. }
  212. //+-------------------------------------------------------------------------
  213. //
  214. // Function: SpVerifySignature
  215. //
  216. // Synopsis: Verifies a signed message buffer by calculating a checksum over all
  217. // the non-read only data buffers and encrypting the checksum
  218. // along with a nonce.
  219. //
  220. // Effects:
  221. //
  222. // Arguments: ContextHandle - Handle of the context to use to sign the
  223. // message.
  224. // MessageBuffers - Contains an array of signed buffers and
  225. // a signature buffer.
  226. // MessageSequenceNumber - Sequence number for this message,
  227. // only used in datagram cases.
  228. // QualityOfProtection - Unused flags.
  229. //
  230. // Requires: STATUS_INVALID_HANDLE - the context could not be found or
  231. // was not configured for message integrity.
  232. // STATUS_INVALID_PARAMETER - the signature buffer could not
  233. // be found or was too small.
  234. //
  235. // Returns:
  236. //
  237. // Notes:
  238. //
  239. //
  240. //--------------------------------------------------------------------------
  241. NTSTATUS NTAPI
  242. SpVerifySignature(
  243. IN LSA_SEC_HANDLE ContextHandle,
  244. IN PSecBufferDesc MessageBuffers,
  245. IN ULONG MessageSequenceNumber,
  246. OUT PULONG QualityOfProtection
  247. )
  248. {
  249. return( SEC_E_UNSUPPORTED_FUNCTION );
  250. }
  251. NTSTATUS NTAPI
  252. SpSealMessage(
  253. IN LSA_SEC_HANDLE ContextHandle,
  254. IN ULONG QualityOfProtection,
  255. IN PSecBufferDesc pMessage,
  256. IN ULONG MessageSequenceNumber
  257. )
  258. {
  259. PSSL_USER_CONTEXT Context ;
  260. PSPContext pContext;
  261. PSecBuffer pHdrBuffer;
  262. PSecBuffer pDataBuffer;
  263. PSecBuffer pTlrBuffer;
  264. PSecBuffer pTokenBuffer;
  265. SP_STATUS pctRet = PCT_ERR_OK;
  266. SPBuffer CommOut;
  267. SPBuffer AppIn;
  268. DWORD cbBuffer;
  269. BOOL fAlloced = FALSE;
  270. BOOL fConnectionMode = FALSE;
  271. int i;
  272. SP_BEGIN("SpSealMessage");
  273. Context = SslFindUserContext( ContextHandle );
  274. if ( !Context )
  275. {
  276. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  277. }
  278. pContext = Context->pContext;
  279. if(pContext == NULL)
  280. {
  281. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  282. }
  283. if(!(pContext->State & SP_STATE_CONNECTED) || !pContext->Encrypt)
  284. {
  285. SP_RETURN( SP_LOG_RESULT(SEC_E_CONTEXT_EXPIRED) );
  286. }
  287. //
  288. // Find the buffer with the data:
  289. //
  290. pHdrBuffer = NULL;
  291. pDataBuffer = NULL;
  292. pTlrBuffer = NULL;
  293. pTokenBuffer = NULL;
  294. /* Gibraltar passes in the following,
  295. * a TOKEN buffer (or SECBUFFER_STREAM_HEADER)
  296. * a DATA buffer
  297. * a TOKEN buffer (or SECBUFFER_STREAM_TRAILER)
  298. * or we can get a connection mode as in
  299. * DATA buffer
  300. * Token buffer
  301. */
  302. if(0 == (pContext->Flags & CONTEXT_FLAG_CONNECTION_MODE))
  303. {
  304. // Stream Mode
  305. // The output buffer should be a concatenation of
  306. // the header buffer, Data buffer, and Trailer buffers.
  307. for (i = 0 ; i < (int)pMessage->cBuffers ; i++ )
  308. {
  309. switch(pMessage->pBuffers[i].BufferType)
  310. {
  311. case SECBUFFER_STREAM_HEADER:
  312. pHdrBuffer = &pMessage->pBuffers[i];
  313. break;
  314. case SECBUFFER_DATA :
  315. pDataBuffer = &pMessage->pBuffers[i];
  316. if(pHdrBuffer == NULL) pHdrBuffer = pDataBuffer;
  317. break;
  318. case SECBUFFER_STREAM_TRAILER:
  319. pTlrBuffer = &pMessage->pBuffers[i];
  320. break;
  321. case SECBUFFER_TOKEN:
  322. if(pHdrBuffer == NULL)
  323. {
  324. pHdrBuffer = &pMessage->pBuffers[i];
  325. }
  326. else if(pTlrBuffer == NULL)
  327. {
  328. pTlrBuffer = &pMessage->pBuffers[i];
  329. }
  330. break;
  331. default:
  332. break;
  333. }
  334. }
  335. if (!pHdrBuffer || !pDataBuffer )
  336. {
  337. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  338. }
  339. #if DBG
  340. DebugLog((DEB_TRACE, "Header (uninitialized): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  341. pHdrBuffer->cbBuffer,
  342. pHdrBuffer->pvBuffer));
  343. DebugLog((DEB_TRACE, "Data (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  344. pDataBuffer->cbBuffer,
  345. pDataBuffer->pvBuffer));
  346. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  347. if(pTlrBuffer)
  348. {
  349. DebugLog((DEB_TRACE, "Trailer (uninitialized): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  350. pTlrBuffer->cbBuffer,
  351. pTlrBuffer->pvBuffer));
  352. }
  353. #endif
  354. // Now, figure out if all of the buffers are contiguous, if not, then we
  355. // have to allocate a buffer
  356. fAlloced = FALSE;
  357. if((PUCHAR)pDataBuffer->pvBuffer !=
  358. ((PUCHAR)pHdrBuffer->pvBuffer + pHdrBuffer->cbBuffer))
  359. {
  360. fAlloced = TRUE;
  361. }
  362. if(pTlrBuffer)
  363. {
  364. if((PUCHAR)pTlrBuffer->pvBuffer !=
  365. ((PUCHAR)pDataBuffer->pvBuffer + pDataBuffer->cbBuffer))
  366. {
  367. fAlloced = TRUE;
  368. }
  369. }
  370. if(!fAlloced)
  371. {
  372. // All of our buffers are contiguous, so we do
  373. // not need to allocate a contiguous buffer.
  374. pTokenBuffer = pHdrBuffer;
  375. AppIn.pvBuffer = pDataBuffer->pvBuffer;
  376. AppIn.cbData = pDataBuffer->cbBuffer;
  377. AppIn.cbBuffer = pDataBuffer->cbBuffer;
  378. CommOut.pvBuffer = pHdrBuffer->pvBuffer;
  379. CommOut.cbData = 0;
  380. CommOut.cbBuffer = pHdrBuffer->cbBuffer + pDataBuffer->cbBuffer;
  381. if(pTlrBuffer)
  382. {
  383. CommOut.cbBuffer += pTlrBuffer->cbBuffer;
  384. AppIn.cbBuffer += pTlrBuffer->cbBuffer;
  385. }
  386. }
  387. else
  388. {
  389. // Our buffers are not contiguous, so we must allocate a contiguous
  390. // buffer to do our work in.
  391. // Calculate the size of the buffer
  392. CommOut.cbBuffer = pHdrBuffer->cbBuffer + pDataBuffer->cbBuffer;
  393. if(pTlrBuffer)
  394. {
  395. CommOut.cbBuffer += pTlrBuffer->cbBuffer;
  396. }
  397. // Allocate the buffer
  398. CommOut.pvBuffer = SPExternalAlloc(CommOut.cbBuffer);
  399. if(CommOut.pvBuffer == NULL)
  400. {
  401. SP_RETURN( SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY) );
  402. }
  403. // Copy data to encrypt to the buffer
  404. CommOut.cbData = 0;
  405. AppIn.pvBuffer = (PBYTE)CommOut.pvBuffer + pHdrBuffer->cbBuffer;
  406. AppIn.cbBuffer = CommOut.cbBuffer - pHdrBuffer->cbBuffer;
  407. AppIn.cbData = pDataBuffer->cbBuffer;
  408. CopyMemory((PBYTE)AppIn.pvBuffer, (PBYTE)pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  409. }
  410. pctRet = pContext->Encrypt(pContext,
  411. &AppIn,
  412. &CommOut);
  413. if(pctRet == PCT_ERR_OK)
  414. {
  415. // Set the various buffer sizes.
  416. cbBuffer = CommOut.cbData;
  417. // The first few bytes always go in the header buffer.
  418. pHdrBuffer->cbBuffer = min(cbBuffer, pHdrBuffer->cbBuffer);
  419. cbBuffer -= pHdrBuffer->cbBuffer;
  420. if(pTlrBuffer)
  421. {
  422. // The output data buffer is the same size as the input data buffer.
  423. pDataBuffer->cbBuffer = min(cbBuffer, pDataBuffer->cbBuffer);
  424. cbBuffer -= pDataBuffer->cbBuffer;
  425. // The trailer buffer gets the data that's left over.
  426. pTlrBuffer->cbBuffer = min(cbBuffer, pTlrBuffer->cbBuffer);
  427. cbBuffer -= pTlrBuffer->cbBuffer;
  428. }
  429. else
  430. {
  431. pDataBuffer->cbBuffer = min(cbBuffer, pDataBuffer->cbBuffer);
  432. cbBuffer -= pDataBuffer->cbBuffer;
  433. }
  434. if(fAlloced)
  435. {
  436. // If we allocated the buffer, then we must copy
  437. CopyMemory(pHdrBuffer->pvBuffer,
  438. CommOut.pvBuffer,
  439. pHdrBuffer->cbBuffer);
  440. CopyMemory(pDataBuffer->pvBuffer,
  441. (PUCHAR)CommOut.pvBuffer + pHdrBuffer->cbBuffer,
  442. pDataBuffer->cbBuffer);
  443. if(pTlrBuffer)
  444. {
  445. CopyMemory(pTlrBuffer->pvBuffer,
  446. (PUCHAR)CommOut.pvBuffer + pHdrBuffer->cbBuffer + pDataBuffer->cbBuffer,
  447. pTlrBuffer->cbBuffer);
  448. }
  449. }
  450. #if DBG
  451. DebugLog((DEB_TRACE, "Header (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  452. pHdrBuffer->cbBuffer,
  453. pHdrBuffer->pvBuffer));
  454. DBG_HEX_STRING(DEB_BUFFERS, pHdrBuffer->pvBuffer, pHdrBuffer->cbBuffer);
  455. DebugLog((DEB_TRACE, "Data (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  456. pDataBuffer->cbBuffer,
  457. pDataBuffer->pvBuffer));
  458. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  459. if(pTlrBuffer)
  460. {
  461. DebugLog((DEB_TRACE, "Trailer (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  462. pTlrBuffer->cbBuffer,
  463. pTlrBuffer->pvBuffer));
  464. DBG_HEX_STRING(DEB_BUFFERS, pTlrBuffer->pvBuffer, pTlrBuffer->cbBuffer);
  465. }
  466. #endif
  467. }
  468. }
  469. else
  470. {
  471. // We're doing connection mode, so unpack buffers as a
  472. // Data and then Token buffer
  473. fConnectionMode = TRUE;
  474. for (i = 0 ; i < (int)pMessage->cBuffers ; i++ )
  475. {
  476. switch(pMessage->pBuffers[i].BufferType)
  477. {
  478. case SECBUFFER_DATA :
  479. pDataBuffer = &pMessage->pBuffers[i];
  480. break;
  481. case SECBUFFER_TOKEN:
  482. if(pTokenBuffer == NULL)
  483. {
  484. pTokenBuffer = &pMessage->pBuffers[i];
  485. }
  486. break;
  487. default:
  488. break;
  489. }
  490. }
  491. if((pTokenBuffer == NULL) || (pDataBuffer == NULL))
  492. {
  493. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  494. }
  495. if((pDataBuffer->pvBuffer == NULL) || (pTokenBuffer->pvBuffer == NULL))
  496. {
  497. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  498. }
  499. #if DBG
  500. DebugLog((DEB_TRACE, "Data (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  501. pDataBuffer->cbBuffer,
  502. pDataBuffer->pvBuffer));
  503. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  504. DebugLog((DEB_TRACE, "Token (uninitialized): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  505. pTokenBuffer->cbBuffer,
  506. pTokenBuffer->pvBuffer));
  507. #endif
  508. // Connection Mode
  509. // The output should get written to a concatenation of the
  510. // data buffer and the token buffer. If no token buffer is
  511. // given, then we should allocate one.
  512. if((PUCHAR)pTokenBuffer->pvBuffer ==
  513. ((PUCHAR)pDataBuffer->pvBuffer + pDataBuffer->cbBuffer))
  514. {
  515. // If the buffers are contiguous, we can optimize!
  516. CommOut.pvBuffer = pDataBuffer->pvBuffer;
  517. CommOut.cbData = 0;
  518. CommOut.cbBuffer = pDataBuffer->cbBuffer + pTokenBuffer->cbBuffer;
  519. }
  520. else
  521. {
  522. // We have to realloc the buffer
  523. fAlloced = TRUE;
  524. CommOut.pvBuffer = SPExternalAlloc(pDataBuffer->cbBuffer + pTokenBuffer->cbBuffer);
  525. if(CommOut.pvBuffer == NULL)
  526. {
  527. SP_RETURN( SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY) );
  528. }
  529. CommOut.cbBuffer = pDataBuffer->cbBuffer + pTokenBuffer->cbBuffer;
  530. CommOut.cbData = 0;
  531. }
  532. // The data buffer always goes to AppIn
  533. AppIn.pvBuffer = pDataBuffer->pvBuffer;
  534. AppIn.cbData = pDataBuffer->cbBuffer;
  535. AppIn.cbBuffer = pDataBuffer->cbBuffer;
  536. pctRet = pContext->Encrypt(pContext,
  537. &AppIn,
  538. &CommOut);
  539. if(pctRet == PCT_ERR_OK)
  540. {
  541. // Set the various buffer sizes.
  542. cbBuffer = CommOut.cbData;
  543. // The first few bytes always go into the data buffer.
  544. pDataBuffer->cbBuffer = min(cbBuffer, pDataBuffer->cbBuffer);
  545. cbBuffer -= pDataBuffer->cbBuffer;
  546. // The remaining bytes go into the token buffer.
  547. pTokenBuffer->cbBuffer = min(cbBuffer, pTokenBuffer->cbBuffer);
  548. if(fAlloced)
  549. {
  550. // We encrypted into our temporary buffer, so we must
  551. // copy.
  552. CopyMemory(pDataBuffer->pvBuffer,
  553. CommOut.pvBuffer,
  554. pDataBuffer->cbBuffer);
  555. CopyMemory(pTokenBuffer->pvBuffer,
  556. (PUCHAR)CommOut.pvBuffer + pDataBuffer->cbBuffer,
  557. pTokenBuffer->cbBuffer);
  558. }
  559. }
  560. #if DBG
  561. DebugLog((DEB_TRACE, "Data (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  562. pDataBuffer->cbBuffer,
  563. pDataBuffer->pvBuffer));
  564. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  565. DebugLog((DEB_TRACE, "Token (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  566. pTokenBuffer->cbBuffer,
  567. pTokenBuffer->pvBuffer));
  568. DBG_HEX_STRING(DEB_BUFFERS, pTokenBuffer->pvBuffer, pTokenBuffer->cbBuffer);
  569. #endif
  570. }
  571. if(fAlloced)
  572. {
  573. SPExternalFree(CommOut.pvBuffer);
  574. }
  575. SP_RETURN( PctTranslateError(pctRet) );
  576. }
  577. NTSTATUS NTAPI
  578. SpUnsealMessage(
  579. IN LSA_SEC_HANDLE ContextHandle,
  580. IN PSecBufferDesc pMessage,
  581. IN ULONG MessageSequenceNumber,
  582. OUT PULONG QualityOfProtection
  583. )
  584. {
  585. // Output Buffer Types
  586. PSSL_USER_CONTEXT Context ;
  587. PSecBuffer pHdrBuffer;
  588. PSecBuffer pDataBuffer;
  589. PSecBuffer pTokenBuffer;
  590. PSecBuffer pTlrBuffer;
  591. PSecBuffer pExtraBuffer;
  592. SP_STATUS pctRet = PCT_ERR_OK;
  593. SPBuffer CommIn;
  594. SPBuffer AppOut;
  595. PSPContext pContext;
  596. DWORD cbHeaderSize;
  597. BOOL fAlloced = FALSE;
  598. SECURITY_STATUS scRet;
  599. int i;
  600. SP_BEGIN("SpUnsealMessage");
  601. Context = SslFindUserContext( ContextHandle );
  602. if ( !Context )
  603. {
  604. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  605. }
  606. pContext = Context->pContext;
  607. if(pContext == NULL)
  608. {
  609. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  610. }
  611. if(!(pContext->State & SP_STATE_CONNECTED))
  612. {
  613. SP_RETURN( SP_LOG_RESULT(SEC_E_CONTEXT_EXPIRED) );
  614. }
  615. //
  616. // Set up output buffers:
  617. //
  618. pHdrBuffer = NULL;
  619. pDataBuffer = NULL;
  620. pTokenBuffer = NULL;
  621. pTlrBuffer = NULL;
  622. pExtraBuffer = NULL;
  623. // On input, the buffers can either be
  624. // DataBuffer
  625. // TokenBuffer
  626. //
  627. // or
  628. //
  629. // Data Buffer
  630. // Empty
  631. // Empty
  632. // Empty
  633. //
  634. // on Output, the buffers are
  635. // DataBuffer
  636. // TokenBuffer
  637. //
  638. // or
  639. // HdrBuffer
  640. // DataBuffer
  641. // Tlrbuffer
  642. // Extrabuffer or Empty
  643. if(0 == (pContext->Flags & CONTEXT_FLAG_CONNECTION_MODE))
  644. {
  645. // Stream Mode
  646. // The output buffer should be a concatenation of
  647. // the header buffer, Data buffer, and Trailer buffers.
  648. for (i = 0 ; i < (int)pMessage->cBuffers ; i++ )
  649. {
  650. switch(pMessage->pBuffers[i].BufferType)
  651. {
  652. case SECBUFFER_DATA:
  653. // The message data buffer on input will be the hdr buffer on
  654. // output.
  655. pHdrBuffer = &pMessage->pBuffers[i];
  656. break;
  657. case SECBUFFER_EMPTY:
  658. if(pDataBuffer == NULL)
  659. {
  660. pDataBuffer = &pMessage->pBuffers[i];
  661. }
  662. else if (pTlrBuffer == NULL)
  663. {
  664. pTlrBuffer = &pMessage->pBuffers[i];
  665. }
  666. else if (pExtraBuffer == NULL)
  667. {
  668. pExtraBuffer = &pMessage->pBuffers[i];
  669. }
  670. break;
  671. default:
  672. break;
  673. }
  674. }
  675. if(!pHdrBuffer || !pDataBuffer || !pTlrBuffer || !pExtraBuffer)
  676. {
  677. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  678. }
  679. if(pHdrBuffer->pvBuffer == NULL)
  680. {
  681. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  682. }
  683. #if DBG
  684. DebugLog((DEB_TRACE, "Data (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  685. pHdrBuffer->cbBuffer,
  686. pHdrBuffer->pvBuffer));
  687. DBG_HEX_STRING(DEB_BUFFERS, pHdrBuffer->pvBuffer, pHdrBuffer->cbBuffer);
  688. #endif
  689. CommIn.pvBuffer = pHdrBuffer->pvBuffer;
  690. CommIn.cbData = pHdrBuffer->cbBuffer;
  691. CommIn.cbBuffer = pHdrBuffer->cbBuffer;
  692. pctRet = pContext->GetHeaderSize(pContext, &CommIn, &cbHeaderSize);
  693. if(pctRet == PCT_ERR_OK)
  694. {
  695. AppOut.pvBuffer = (PUCHAR)CommIn.pvBuffer + cbHeaderSize;
  696. AppOut.cbData = 0;
  697. AppOut.cbBuffer = CommIn.cbData-cbHeaderSize;
  698. pctRet = pContext->DecryptHandler(pContext,
  699. &CommIn,
  700. &AppOut);
  701. }
  702. if((pctRet == PCT_ERR_OK) ||
  703. (pctRet == PCT_INT_RENEGOTIATE))
  704. {
  705. if(CommIn.cbData < pHdrBuffer->cbBuffer)
  706. {
  707. pExtraBuffer->BufferType = SECBUFFER_EXTRA;
  708. pExtraBuffer->cbBuffer = pHdrBuffer->cbBuffer-CommIn.cbData;
  709. pExtraBuffer->pvBuffer = (PUCHAR)pHdrBuffer->pvBuffer+CommIn.cbData;
  710. }
  711. else
  712. {
  713. pExtraBuffer = NULL;
  714. }
  715. pHdrBuffer->BufferType = SECBUFFER_STREAM_HEADER;
  716. pHdrBuffer->cbBuffer = cbHeaderSize;
  717. pDataBuffer->BufferType = SECBUFFER_DATA;
  718. pDataBuffer->pvBuffer = AppOut.pvBuffer;
  719. pDataBuffer->cbBuffer = AppOut.cbData;
  720. pTlrBuffer->BufferType = SECBUFFER_STREAM_TRAILER;
  721. pTlrBuffer->pvBuffer = (PUCHAR)pDataBuffer->pvBuffer + AppOut.cbData;
  722. pTlrBuffer->cbBuffer = CommIn.cbBuffer-(AppOut.cbData+cbHeaderSize);
  723. #if DBG
  724. DebugLog((DEB_TRACE, "Header (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  725. pHdrBuffer->cbBuffer,
  726. pHdrBuffer->pvBuffer));
  727. DBG_HEX_STRING(DEB_BUFFERS, pHdrBuffer->pvBuffer, pHdrBuffer->cbBuffer);
  728. DebugLog((DEB_TRACE, "Data (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  729. pDataBuffer->cbBuffer,
  730. pDataBuffer->pvBuffer));
  731. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  732. DebugLog((DEB_TRACE, "Trailer (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  733. pTlrBuffer->cbBuffer,
  734. pTlrBuffer->pvBuffer));
  735. DBG_HEX_STRING(DEB_BUFFERS, pTlrBuffer->pvBuffer, pTlrBuffer->cbBuffer);
  736. if(pExtraBuffer)
  737. {
  738. DebugLog((DEB_TRACE, "Extra (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  739. pExtraBuffer->cbBuffer,
  740. pExtraBuffer->pvBuffer));
  741. DBG_HEX_STRING(DEB_BUFFERS, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
  742. }
  743. #endif
  744. if(pctRet == PCT_INT_RENEGOTIATE)
  745. {
  746. // Wow. Need to notify the lsa mode portion of the context that
  747. // the caller is about to call AcceptSecurityContext again, and
  748. // not to panic. So, we cruft up a magic "token" that we
  749. // pass along in ApplyControlToken:
  750. scRet = UpdateContextUsrToLsa(ContextHandle);
  751. if(FAILED(scRet))
  752. {
  753. SP_RETURN( SP_LOG_RESULT(scRet) );
  754. }
  755. }
  756. }
  757. else if(pctRet == PCT_INT_INCOMPLETE_MSG)
  758. {
  759. pDataBuffer->BufferType = SECBUFFER_MISSING;
  760. pDataBuffer->cbBuffer = CommIn.cbData - pHdrBuffer->cbBuffer;
  761. /* This is a hack to work with old code that was designed to work with
  762. * the old SSL. */
  763. pHdrBuffer->BufferType = SECBUFFER_MISSING;
  764. pHdrBuffer->cbBuffer = CommIn.cbData - pHdrBuffer->cbBuffer;
  765. }
  766. }
  767. else
  768. {
  769. // Connection Mode
  770. for (i = 0 ; i < (int)pMessage->cBuffers ; i++ )
  771. {
  772. switch(pMessage->pBuffers[i].BufferType)
  773. {
  774. case SECBUFFER_DATA :
  775. pDataBuffer = &pMessage->pBuffers[i];
  776. break;
  777. case SECBUFFER_TOKEN:
  778. if(pTokenBuffer == NULL)
  779. {
  780. pTokenBuffer = &pMessage->pBuffers[i];
  781. }
  782. break;
  783. default:
  784. break;
  785. }
  786. }
  787. if((pTokenBuffer == NULL) || (pDataBuffer == NULL))
  788. {
  789. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  790. }
  791. if((pDataBuffer->pvBuffer == NULL) || (pTokenBuffer->pvBuffer == NULL))
  792. {
  793. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_TOKEN) );
  794. }
  795. #if DBG
  796. DebugLog((DEB_TRACE, "Data (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  797. pDataBuffer->cbBuffer,
  798. pDataBuffer->pvBuffer));
  799. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  800. DebugLog((DEB_TRACE, "Token (ciphertext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  801. pTokenBuffer->cbBuffer,
  802. pTokenBuffer->pvBuffer));
  803. DBG_HEX_STRING(DEB_BUFFERS, pTokenBuffer->pvBuffer, pTokenBuffer->cbBuffer);
  804. #endif
  805. // The Data and Token buffers are concatenated together to
  806. // form a single input buffer.
  807. if((PUCHAR)pDataBuffer->pvBuffer + pDataBuffer->cbBuffer ==
  808. (PUCHAR)pTokenBuffer->pvBuffer)
  809. {
  810. // Speed Opt, If the buffers really are just one big buffer
  811. // then we can party on them directly.
  812. CommIn.pvBuffer = pDataBuffer->pvBuffer;
  813. CommIn.cbData = pDataBuffer->cbBuffer + pTokenBuffer->cbBuffer;
  814. CommIn.cbBuffer = CommIn.cbData;
  815. }
  816. else
  817. {
  818. // We have to allocate a uniform input buffer
  819. CommIn.cbData = pDataBuffer->cbBuffer + pTokenBuffer->cbBuffer;
  820. CommIn.pvBuffer = SPExternalAlloc(CommIn.cbData);
  821. if(CommIn.pvBuffer == NULL)
  822. {
  823. SP_RETURN( SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY) );
  824. }
  825. CommIn.cbBuffer = CommIn.cbData;
  826. CopyMemory(CommIn.pvBuffer, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  827. CopyMemory((PUCHAR)CommIn.pvBuffer + pDataBuffer->cbBuffer,
  828. pTokenBuffer->pvBuffer,
  829. pTokenBuffer->cbBuffer);
  830. fAlloced = TRUE;
  831. }
  832. AppOut.pvBuffer = pDataBuffer->pvBuffer;
  833. AppOut.cbData = 0;
  834. AppOut.cbBuffer = pDataBuffer->cbBuffer;
  835. pctRet = pContext->DecryptHandler(pContext,
  836. &CommIn,
  837. &AppOut);
  838. if((pctRet == PCT_ERR_OK) ||
  839. (pctRet == PCT_INT_RENEGOTIATE))
  840. {
  841. pDataBuffer->cbBuffer = AppOut.cbData;
  842. pTokenBuffer->cbBuffer = CommIn.cbData - AppOut.cbData;
  843. }
  844. if(fAlloced)
  845. {
  846. SPExternalFree(CommIn.pvBuffer);
  847. }
  848. #if DBG
  849. DebugLog((DEB_TRACE, "Data (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  850. pDataBuffer->cbBuffer,
  851. pDataBuffer->pvBuffer));
  852. DBG_HEX_STRING(DEB_BUFFERS, pDataBuffer->pvBuffer, pDataBuffer->cbBuffer);
  853. DebugLog((DEB_TRACE, "Token (plaintext): cbBuffer:0x%x, pvBuffer:0x%8.8x\n",
  854. pTokenBuffer->cbBuffer,
  855. pTokenBuffer->pvBuffer));
  856. DBG_HEX_STRING(DEB_BUFFERS, pTokenBuffer->pvBuffer, pTokenBuffer->cbBuffer);
  857. #endif
  858. }
  859. DebugOut(( DEB_TRACE, "Unseal returns %x \n", PctTranslateError( pctRet ) ));
  860. SP_RETURN( PctTranslateError(pctRet) );
  861. }
  862. //+-------------------------------------------------------------------------
  863. //
  864. // Function: SpGetContextToken
  865. //
  866. // Synopsis: returns a pointer to the token for a server-side context
  867. //
  868. // Effects:
  869. //
  870. // Arguments:
  871. //
  872. // Requires:
  873. //
  874. // Returns:
  875. //
  876. // Notes:
  877. //
  878. //
  879. //--------------------------------------------------------------------------
  880. NTSTATUS NTAPI
  881. SpGetContextToken(
  882. IN LSA_SEC_HANDLE ContextHandle,
  883. OUT PHANDLE ImpersonationToken
  884. )
  885. {
  886. PSSL_USER_CONTEXT Context;
  887. PSPContext pContext;
  888. PSessCacheItem pZombie;
  889. SECURITY_STATUS Status;
  890. Context = SslFindUserContext( ContextHandle );
  891. if ( !Context )
  892. {
  893. return( SEC_E_INVALID_HANDLE );
  894. }
  895. pContext = Context->pContext;
  896. if(pContext == NULL)
  897. {
  898. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  899. }
  900. pZombie = pContext->RipeZombie;
  901. if(pZombie == NULL ||
  902. pZombie->hLocator == 0)
  903. {
  904. if(pZombie->LocatorStatus)
  905. {
  906. return(SP_LOG_RESULT(pZombie->LocatorStatus));
  907. }
  908. else
  909. {
  910. return(SP_LOG_RESULT(SEC_E_NO_IMPERSONATION));
  911. }
  912. }
  913. if(pZombie->phMapper == NULL)
  914. {
  915. *ImpersonationToken = (HANDLE)pZombie->hLocator;
  916. }
  917. else
  918. {
  919. // Call the application mapper to get a token.
  920. Status = pZombie->phMapper->m_vtable->GetAccessToken(
  921. pZombie->phMapper->m_Reserved1,
  922. pZombie->hLocator,
  923. ImpersonationToken);
  924. if(!NT_SUCCESS(Status))
  925. {
  926. return SP_LOG_RESULT(Status);
  927. }
  928. }
  929. return( SEC_E_OK );
  930. }
  931. //+-------------------------------------------------------------------------
  932. //
  933. // Function: SpCompleteAuthToken
  934. //
  935. // Synopsis: Completes a context (in Kerberos case, does nothing)
  936. //
  937. // Effects:
  938. //
  939. // Arguments:
  940. //
  941. // Requires:
  942. //
  943. // Returns:
  944. //
  945. // Notes:
  946. //
  947. //
  948. //--------------------------------------------------------------------------
  949. NTSTATUS
  950. NTAPI
  951. SpCompleteAuthToken(
  952. IN LSA_SEC_HANDLE ContextHandle,
  953. IN PSecBufferDesc InputBuffer
  954. )
  955. {
  956. return(STATUS_SUCCESS);
  957. }
  958. NTSTATUS NTAPI
  959. SpFormatCredentials(
  960. IN PSecBuffer Credentials,
  961. OUT PSecBuffer FormattedCredentials
  962. )
  963. {
  964. return(STATUS_NOT_SUPPORTED);
  965. }
  966. NTSTATUS NTAPI
  967. SpMarshallSupplementalCreds(
  968. IN ULONG CredentialSize,
  969. IN PUCHAR Credentials,
  970. OUT PULONG MarshalledCredSize,
  971. OUT PVOID * MarshalledCreds
  972. )
  973. {
  974. return(STATUS_NOT_SUPPORTED);
  975. }
  976. //+---------------------------------------------------------------------------
  977. //
  978. // Function: UpdateContextUsrToLsa
  979. //
  980. // Synopsis: UnsealMessage has just received a redo request, so push the
  981. // read key over to the LSA process.
  982. //
  983. // Arguments: [hLsaContext] -- Handle to LSA schannel context.
  984. //
  985. // History: 10-20-97 jbanes Added CAPI integration.
  986. //
  987. // Notes: The format of the buffer sent to ApplyControlToken is:
  988. //
  989. // DWORD dwOperation; // SCHANNEL_RENEGOTIATE
  990. // DWORD dwNewState;
  991. // DWORD dwReadSequence;
  992. // DWORD cbReadKey;
  993. // BYTE rgbReadKey[];
  994. //
  995. //----------------------------------------------------------------------------
  996. SECURITY_STATUS
  997. UpdateContextUsrToLsa(
  998. IN LSA_SEC_HANDLE hLsaContext)
  999. {
  1000. PSSL_USER_CONTEXT pUserContext;
  1001. PSPContext pContext;
  1002. CtxtHandle hMyContext;
  1003. SecBuffer RedoNotify;
  1004. SecBufferDesc RedoDesc;
  1005. SECURITY_STATUS scRet;
  1006. PBYTE pbBuffer;
  1007. DWORD cbBuffer;
  1008. pUserContext = SslFindUserContext( hLsaContext );
  1009. if ( !pUserContext )
  1010. {
  1011. return SEC_E_INVALID_HANDLE;
  1012. }
  1013. pContext = pUserContext->pContext;
  1014. if(pContext == NULL)
  1015. {
  1016. SP_RETURN( SP_LOG_RESULT(SEC_E_INVALID_HANDLE) );
  1017. }
  1018. hMyContext.dwLower = (DWORD_PTR) GetCurrentThread() ;
  1019. hMyContext.dwUpper = hLsaContext ;
  1020. //
  1021. // Compute size of output buffer.
  1022. //
  1023. cbBuffer = sizeof(DWORD) * 2;
  1024. //
  1025. // Allocate memory for output buffer.
  1026. //
  1027. pbBuffer = SPExternalAlloc( cbBuffer);
  1028. if(pbBuffer == NULL)
  1029. {
  1030. return SEC_E_INSUFFICIENT_MEMORY;
  1031. }
  1032. RedoNotify.BufferType = SECBUFFER_TOKEN;
  1033. RedoNotify.cbBuffer = cbBuffer;
  1034. RedoNotify.pvBuffer = pbBuffer;
  1035. RedoDesc.ulVersion = SECBUFFER_VERSION ;
  1036. RedoDesc.pBuffers = &RedoNotify ;
  1037. RedoDesc.cBuffers = 1 ;
  1038. //
  1039. // Build output buffer.
  1040. //
  1041. *(PDWORD)pbBuffer = SCHANNEL_RENEGOTIATE;
  1042. pbBuffer += sizeof(DWORD);
  1043. *(PDWORD)pbBuffer = pContext->State;
  1044. pbBuffer += sizeof(DWORD);
  1045. //
  1046. // Call ApplyControlToken
  1047. //
  1048. DebugOut(( DEB_TRACE, "Sending state change to LSA since we're renegotiating\n" ));
  1049. scRet = ApplyControlToken( &hMyContext, &RedoDesc );
  1050. LocalFree(RedoNotify.pvBuffer);
  1051. return scRet;
  1052. }
  1053. BOOL
  1054. SslEmptyCacheA(LPSTR pszTargetName,
  1055. DWORD dwFlags)
  1056. {
  1057. ANSI_STRING String;
  1058. UNICODE_STRING UnicodeString;
  1059. NTSTATUS Status;
  1060. BOOL fSuccess;
  1061. UnicodeString.Length = 0;
  1062. UnicodeString.MaximumLength = 0;
  1063. UnicodeString.Buffer = NULL;
  1064. // Convert target name to unicode.
  1065. if(pszTargetName)
  1066. {
  1067. RtlInitAnsiString(&String, pszTargetName);
  1068. Status = RtlAnsiStringToUnicodeString(&UnicodeString,
  1069. &String,
  1070. TRUE);
  1071. if(!NT_SUCCESS(Status))
  1072. {
  1073. SetLastError(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  1074. return FALSE;
  1075. }
  1076. }
  1077. // Call unicode version of function.
  1078. fSuccess = SslEmptyCacheW(UnicodeString.Buffer, dwFlags);
  1079. if(UnicodeString.Buffer)
  1080. {
  1081. RtlFreeUnicodeString(&UnicodeString);
  1082. }
  1083. return fSuccess;
  1084. }
  1085. BOOL
  1086. SslEmptyCacheW(LPWSTR pszTargetName,
  1087. DWORD dwFlags)
  1088. {
  1089. HANDLE LsaHandle = 0;
  1090. DWORD PackageNumber;
  1091. LSA_STRING PackageName;
  1092. PSSL_PURGE_SESSION_CACHE_REQUEST pRequest = NULL;
  1093. DWORD cbTargetName;
  1094. DWORD cbRequest;
  1095. NTSTATUS Status;
  1096. NTSTATUS SubStatus;
  1097. Status = LsaConnectUntrusted(&LsaHandle);
  1098. if(FAILED(Status))
  1099. {
  1100. SP_LOG_RESULT(Status);
  1101. goto cleanup;
  1102. }
  1103. RtlInitAnsiString(&PackageName, SCHANNEL_NAME_A);
  1104. Status = LsaLookupAuthenticationPackage(
  1105. LsaHandle,
  1106. &PackageName,
  1107. &PackageNumber);
  1108. if(FAILED(Status))
  1109. {
  1110. SP_LOG_RESULT(Status);
  1111. goto cleanup;
  1112. }
  1113. cbRequest = sizeof(SSL_PURGE_SESSION_CACHE_REQUEST);
  1114. if(pszTargetName == NULL)
  1115. {
  1116. pRequest = SPExternalAlloc(cbRequest);
  1117. if(pRequest == NULL)
  1118. {
  1119. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1120. goto cleanup;
  1121. }
  1122. }
  1123. else
  1124. {
  1125. cbTargetName = (wcslen(pszTargetName) + 1) * sizeof(WCHAR);
  1126. cbRequest += cbTargetName;
  1127. pRequest = SPExternalAlloc(cbRequest);
  1128. if(pRequest == NULL)
  1129. {
  1130. Status = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  1131. goto cleanup;
  1132. }
  1133. memcpy(pRequest + 1, pszTargetName, cbTargetName);
  1134. pRequest->ServerName.Buffer = (LPWSTR)(pRequest + 1);
  1135. pRequest->ServerName.Length = (WORD)(wcslen(pszTargetName) * sizeof(WCHAR));
  1136. pRequest->ServerName.MaximumLength = (WORD)cbTargetName;
  1137. }
  1138. pRequest->MessageType = SSL_PURGE_CACHE_MESSAGE;
  1139. pRequest->Flags = SSL_PURGE_CLIENT_ENTRIES | SSL_PURGE_SERVER_ENTRIES;
  1140. Status = LsaCallAuthenticationPackage(
  1141. LsaHandle,
  1142. PackageNumber,
  1143. pRequest,
  1144. cbRequest,
  1145. NULL,
  1146. NULL,
  1147. &SubStatus);
  1148. if(FAILED(Status))
  1149. {
  1150. SP_LOG_RESULT(Status);
  1151. goto cleanup;
  1152. }
  1153. if(FAILED(SubStatus))
  1154. {
  1155. Status = SP_LOG_RESULT(SubStatus);
  1156. }
  1157. cleanup:
  1158. if(LsaHandle)
  1159. {
  1160. CloseHandle(LsaHandle);
  1161. }
  1162. if(pRequest)
  1163. {
  1164. SPExternalFree(pRequest);
  1165. }
  1166. if(FAILED(Status))
  1167. {
  1168. SetLastError(Status);
  1169. return FALSE;
  1170. }
  1171. return TRUE;
  1172. }
  1173. //+-------------------------------------------------------------------------
  1174. //
  1175. // Function: SpExportSecurityContext
  1176. //
  1177. // Synopsis: Exports a security context to another process
  1178. //
  1179. // Effects: Allocates memory for output
  1180. //
  1181. // Arguments: ContextHandle - handle to context to export
  1182. // Flags - Flags concerning duplication. Allowable flags:
  1183. // SECPKG_CONTEXT_EXPORT_DELETE_OLD - causes old context
  1184. // to be deleted.
  1185. // PackedContext - Receives serialized context to be freed with
  1186. // FreeContextBuffer
  1187. // TokenHandle - Optionally receives handle to context's token.
  1188. //
  1189. // Requires:
  1190. //
  1191. // Returns:
  1192. //
  1193. // Notes:
  1194. //
  1195. //
  1196. //--------------------------------------------------------------------------
  1197. NTSTATUS
  1198. NTAPI
  1199. SpExportSecurityContext(
  1200. LSA_SEC_HANDLE ContextHandle, // (in) context to export
  1201. ULONG fFlags, // (in) option flags
  1202. PSecBuffer pPackedContext, // (out) marshalled context
  1203. PHANDLE pToken // (out, optional) token handle for impersonation
  1204. )
  1205. {
  1206. PSSL_USER_CONTEXT Context;
  1207. PSPContext pContext;
  1208. NTSTATUS Status;
  1209. SP_STATUS pctRet;
  1210. DebugLog((DEB_TRACE, "SpExportSecurityContext\n"));
  1211. if (ARGUMENT_PRESENT(pToken))
  1212. {
  1213. *pToken = NULL;
  1214. }
  1215. pPackedContext->pvBuffer = NULL;
  1216. pPackedContext->cbBuffer = 0;
  1217. pPackedContext->BufferType = 0;
  1218. //
  1219. // Get handle to schannel context structure.
  1220. //
  1221. Context = SslFindUserContext( ContextHandle );
  1222. if ( !Context )
  1223. {
  1224. Status = SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
  1225. goto cleanup;
  1226. }
  1227. pContext = Context->pContext;
  1228. if(pContext == NULL)
  1229. {
  1230. Status = SP_LOG_RESULT(SEC_E_INVALID_HANDLE);
  1231. goto cleanup;
  1232. }
  1233. if(!(pContext->State & SP_STATE_CONNECTED))
  1234. {
  1235. Status = SP_LOG_RESULT(SEC_E_CONTEXT_EXPIRED);
  1236. goto cleanup;
  1237. }
  1238. //
  1239. // Build packed context structure.
  1240. //
  1241. pctRet = SPContextSerialize(pContext,
  1242. NULL,
  1243. (PBYTE *)&pPackedContext->pvBuffer,
  1244. &pPackedContext->cbBuffer,
  1245. FALSE);
  1246. if(pctRet != PCT_ERR_OK)
  1247. {
  1248. Status = SP_LOG_RESULT(SEC_E_ENCRYPT_FAILURE);
  1249. goto cleanup;
  1250. }
  1251. //
  1252. // Now either duplicate the token or copy it.
  1253. //
  1254. if (ARGUMENT_PRESENT(pToken) && (pContext->RipeZombie->hLocator))
  1255. {
  1256. if ((fFlags & SECPKG_CONTEXT_EXPORT_DELETE_OLD) != 0)
  1257. {
  1258. *pToken = (HANDLE)pContext->RipeZombie->hLocator;
  1259. pContext->RipeZombie->hLocator = 0;
  1260. }
  1261. else
  1262. {
  1263. Status = NtDuplicateObject(
  1264. NtCurrentProcess(),
  1265. (HANDLE)pContext->RipeZombie->hLocator,
  1266. NULL,
  1267. pToken,
  1268. 0, // no new access
  1269. 0, // no handle attributes
  1270. DUPLICATE_SAME_ACCESS
  1271. );
  1272. if (!NT_SUCCESS(Status))
  1273. {
  1274. goto cleanup;
  1275. }
  1276. }
  1277. }
  1278. Status = STATUS_SUCCESS;
  1279. cleanup:
  1280. DebugLog((DEB_TRACE, "SpExportSecurityContext returned 0x%x\n", Status));
  1281. return(Status);
  1282. }
  1283. NTSTATUS
  1284. NTAPI
  1285. SpImportSecurityContext(
  1286. PSecBuffer pPackedContext, // (in) marshalled context
  1287. HANDLE Token, // (in, optional) handle to token for context
  1288. PLSA_SEC_HANDLE ContextHandle // (out) new context handle
  1289. )
  1290. {
  1291. PSSL_USER_CONTEXT Context = NULL;
  1292. LSA_SEC_HANDLE LsaHandle;
  1293. NTSTATUS Status;
  1294. // Dummy up an lsa handle by incrementing a global variable. This
  1295. // will ensure that each imported context has a unique handle.
  1296. // Skip over values that could be interpreted as an aligned pointer,
  1297. // so that they won't get mixed up with real lsa handles.
  1298. LsaHandle = InterlockedIncrement((PLONG)&ExportedContext);
  1299. while(LsaHandle % MAX_NATURAL_ALIGNMENT == 0)
  1300. {
  1301. LsaHandle = InterlockedIncrement((PLONG)&ExportedContext);
  1302. }
  1303. Status = SslAddUserContext(LsaHandle, Token, pPackedContext, TRUE);
  1304. if(!NT_SUCCESS(Status))
  1305. {
  1306. return Status;
  1307. }
  1308. *ContextHandle = LsaHandle;
  1309. return(Status);
  1310. }