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.

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