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.

839 lines
26 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1996
  6. //
  7. // File: ctxtapi.cxx
  8. //
  9. // Contents: Context APIs for the NtLm security package
  10. // Main entry points into this dll:
  11. // SpDeleteContext
  12. // SpInitLsaModeContext
  13. // SpApplyControlToken
  14. // SpAcceptLsaModeContext
  15. //
  16. // History: ChandanS 26-Jul-1996 Stolen from kerberos\client2\ctxtapi.cxx
  17. // JClark 28-Jun-2000 Added WMI Trace Logging Support
  18. //
  19. //------------------------------------------------------------------------
  20. #define NTLM_CTXTAPI
  21. #include <global.h>
  22. #include "Trace.h"
  23. //+-------------------------------------------------------------------------
  24. //
  25. // Function: SpDeleteContext
  26. //
  27. // Synopsis: Deletes an NtLm context
  28. //
  29. // Effects:
  30. //
  31. // Arguments: ContextHandle - The context to delete
  32. //
  33. // Requires:
  34. //
  35. // Returns: STATUS_SUCCESS or STATUS_INVALID_HANDLE
  36. //
  37. // Notes:
  38. //
  39. //
  40. //--------------------------------------------------------------------------
  41. NTSTATUS NTAPI
  42. SpDeleteContext(
  43. IN ULONG_PTR ContextHandle
  44. )
  45. /*++
  46. Routine Description:
  47. Deletes the local data structures associated with the specified
  48. security context.
  49. This API terminates a context on the local machine.
  50. Arguments:
  51. ContextHandle - Handle to the context to delete
  52. Return Value:
  53. STATUS_SUCCESS - Call completed successfully
  54. SEC_E_NO_SPM -- Security Support Provider is not running
  55. SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid
  56. --*/
  57. {
  58. NTSTATUS Status = STATUS_SUCCESS;
  59. ULONG_PTR TempContextHandle = ContextHandle;
  60. SspPrint((SSP_API, "Entering SpDeleteContext for 0x%x\n", ContextHandle));
  61. Status = SsprDeleteSecurityContext(
  62. TempContextHandle );
  63. SspPrint((SSP_API, "Leaving SpDeleteContext for 0x%x\n", ContextHandle));
  64. return (SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
  65. }
  66. //+-------------------------------------------------------------------------
  67. //
  68. // Function: SpInitLsaModeContext
  69. //
  70. // Synopsis: NtLm implementation of InitializeSecurityContext
  71. // while in Lsa mode. If we return TRUE in *MappedContext,
  72. // secur32 will call SpInitUserModeContext with
  73. // the returned context handle and ContextData
  74. // as input. Fill in whatever info needed for
  75. // the user mode apis
  76. //
  77. // Effects:
  78. //
  79. // Arguments:
  80. //
  81. // Requires:
  82. //
  83. // Returns:
  84. //
  85. // Notes: This function can be called in various ways:
  86. // 1. Generic users of ntlm make the first call to
  87. // InitializeSecurityContext and we return a NEGOTIATE_MESSAGE
  88. // 2. The rdr makes the first call to InitializeSecurityContext
  89. // with no contextHandle but info is passed in through a
  90. // CHALLENGE_MESSAGE (& possibly an NTLM_CHALLENGE_MESSAGE),
  91. // we return an AUTHENTICATE_MESSAGE and an
  92. // NTLM_INITIALIZE_RESPONSE
  93. // 3. Generic users of NTLM make the second call to
  94. // InitializeSecurityContext, passing in a CHALLENGE_MESSAGE
  95. // and we return an AUTHENTICATE_MESSAGE
  96. //
  97. //--------------------------------------------------------------------------
  98. NTSTATUS NTAPI
  99. SpInitLsaModeContext(
  100. IN OPTIONAL ULONG_PTR CredentialHandle,
  101. IN OPTIONAL ULONG_PTR OldContextHandle,
  102. IN OPTIONAL PUNICODE_STRING TargetName,
  103. IN ULONG ContextReqFlags,
  104. IN ULONG TargetDataRep,
  105. IN PSecBufferDesc InputBuffers,
  106. OUT PULONG_PTR NewContextHandle,
  107. IN OUT PSecBufferDesc OutputBuffers,
  108. OUT PULONG ContextAttributes,
  109. OUT PTimeStamp ExpirationTime,
  110. OUT PBOOLEAN MappedContext,
  111. OUT PSecBuffer ContextData
  112. )
  113. {
  114. NTSTATUS Status = STATUS_SUCCESS;
  115. SecBuffer TempTokens[4];
  116. PSecBuffer FirstInputToken;
  117. PSecBuffer SecondInputToken;
  118. PSecBuffer FirstOutputToken;
  119. PSecBuffer SecondOutputToken;
  120. ULONG_PTR OriginalContextHandle = NULL;
  121. ULONG_PTR TempContextHandle = NULL;
  122. ULONG NegotiateFlags = 0;
  123. UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  124. //Tracing State
  125. NTLM_TRACE_INFO TraceInfo = {0};
  126. UINT32 TraceHint = 0;
  127. SspPrint((SSP_API, "Entering SpInitLsaModeContext for Old:0x%x, New:0x%x\n", OldContextHandle, *NewContextHandle));
  128. //Begin tracing an InitializeSecurityContext call for NTLM
  129. if (NtlmGlobalEventTraceFlag){
  130. //Header goo
  131. SET_TRACE_HEADER(TraceInfo,
  132. NtlmInitializeGuid,
  133. EVENT_TRACE_TYPE_START,
  134. WNODE_FLAG_TRACED_GUID|WNODE_FLAG_USE_MOF_PTR,
  135. 2);
  136. TraceHint = (OldContextHandle == 0)?
  137. TRACE_INIT_FIRST:
  138. TRACE_INIT_CHALLENGE;
  139. SET_TRACE_DATA(TraceInfo,
  140. TRACE_INITACC_STAGEHINT,
  141. TraceHint);
  142. SET_TRACE_DATA(TraceInfo,
  143. TRACE_INITACC_INCONTEXT,
  144. OldContextHandle);
  145. TraceEvent(NtlmGlobalTraceLoggerHandle,
  146. (PEVENT_TRACE_HEADER)&TraceInfo);
  147. }
  148. RtlZeroMemory(
  149. TempTokens,
  150. sizeof(TempTokens)
  151. );
  152. FirstInputToken = &TempTokens[0];
  153. SecondInputToken = &TempTokens[1];
  154. FirstOutputToken = &TempTokens[2];
  155. SecondOutputToken = &TempTokens[3];
  156. *MappedContext = FALSE;
  157. ASSERT(ContextData);
  158. ContextData->pvBuffer = NULL;
  159. ContextData->cbBuffer = 0;
  160. RtlZeroMemory(SessionKey,
  161. MSV1_0_USER_SESSION_KEY_LENGTH);
  162. UNREFERENCED_PARAMETER( TargetDataRep );
  163. //
  164. // Extract tokens from the SecBuffers
  165. //
  166. if ( !SspGetTokenBuffer( InputBuffers,
  167. 0, // get the first SECBUFFER_TOKEN
  168. &FirstInputToken,
  169. TRUE
  170. ) ) {
  171. Status = SEC_E_INVALID_TOKEN;
  172. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, SspGetTokenBuffer (FirstInputToken) returns %d\n", Status));
  173. goto Cleanup;
  174. }
  175. //
  176. // If we are using supplied credentials, get the second SECBUFFER_TOKEN
  177. //
  178. if (ContextReqFlags & ISC_REQ_USE_SUPPLIED_CREDS)
  179. {
  180. if ( !SspGetTokenBuffer( InputBuffers,
  181. 1, // get the second SECBUFFER_TOKEN
  182. &SecondInputToken,
  183. TRUE
  184. ) ) {
  185. Status = SEC_E_INVALID_TOKEN;
  186. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, SspGetTokenBuffer (SecondInputToken) returns %d\n", Status));
  187. goto Cleanup;
  188. }
  189. }
  190. if ( !SspGetTokenBuffer( OutputBuffers,
  191. 0, // get the first SECBUFFER_TOKEN
  192. &FirstOutputToken,
  193. FALSE
  194. ) ) {
  195. Status = SEC_E_INVALID_TOKEN;
  196. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, SspGetTokenBuffer (FirstOutputToken) returns %d\n", Status));
  197. goto Cleanup;
  198. }
  199. if ( !SspGetTokenBuffer( OutputBuffers,
  200. 1, // get the second SECBUFFER_TOKEN
  201. &SecondOutputToken,
  202. FALSE
  203. ) ) {
  204. Status = SEC_E_INVALID_TOKEN;
  205. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, SspGetTokenBuffer (SecondOutputToken) returns %d\n", Status));
  206. goto Cleanup;
  207. }
  208. //
  209. // Save the old context handle, in case someone changes it
  210. //
  211. TempContextHandle = OldContextHandle;
  212. OriginalContextHandle = OldContextHandle;
  213. //
  214. // If no previous context was passed
  215. // and if no legitimate input token existed, this is the first call
  216. //
  217. if ((OriginalContextHandle == 0 ) &&
  218. (FirstInputToken->cbBuffer == 0))
  219. {
  220. if ( !ARGUMENT_PRESENT( CredentialHandle ) ) {
  221. Status = STATUS_INVALID_HANDLE;
  222. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, No CredentialHandle\n"));
  223. goto Cleanup;
  224. }
  225. *NewContextHandle = 0;
  226. Status = SsprHandleFirstCall(
  227. CredentialHandle,
  228. NewContextHandle,
  229. ContextReqFlags,
  230. FirstInputToken->cbBuffer,
  231. FirstInputToken->pvBuffer,
  232. TargetName,
  233. &FirstOutputToken->cbBuffer,
  234. &FirstOutputToken->pvBuffer,
  235. ContextAttributes,
  236. ExpirationTime,
  237. SessionKey,
  238. &NegotiateFlags );
  239. TempContextHandle = *NewContextHandle;
  240. //
  241. // If context was passed in, continue where we left off.
  242. // Or if the redir's passing in stuff in the InputBuffers,
  243. // skip the first call and get on with the second
  244. //
  245. } else {
  246. *NewContextHandle = OldContextHandle;
  247. Status = SsprHandleChallengeMessage(
  248. CredentialHandle,
  249. &TempContextHandle,
  250. ContextReqFlags,
  251. FirstInputToken->cbBuffer,
  252. FirstInputToken->pvBuffer,
  253. SecondInputToken->cbBuffer,
  254. SecondInputToken->pvBuffer,
  255. TargetName,
  256. &FirstOutputToken->cbBuffer,
  257. &FirstOutputToken->pvBuffer,
  258. &SecondOutputToken->cbBuffer,
  259. &SecondOutputToken->pvBuffer,
  260. ContextAttributes,
  261. ExpirationTime,
  262. SessionKey,
  263. &NegotiateFlags
  264. );
  265. }
  266. //
  267. // If the original handle is zero, set it to be the TempContextHandle.
  268. // This is for the datagram case, where we map the context after the
  269. // first call to initialize.
  270. //
  271. if (OriginalContextHandle == 0) {
  272. OriginalContextHandle = TempContextHandle;
  273. *NewContextHandle = OriginalContextHandle;
  274. }
  275. //
  276. // Only map the context if this is the real authentication, not a re-auth
  277. // or if this was datagram.
  278. //
  279. if (((Status == SEC_I_CONTINUE_NEEDED) &&
  280. ((*ContextAttributes & ISC_RET_DATAGRAM) != 0)) ||
  281. ((Status == SEC_E_OK) &&
  282. ((*ContextAttributes & (SSP_RET_REAUTHENTICATION | ISC_RET_DATAGRAM)) == 0))) {
  283. NTSTATUS TempStatus;
  284. TempStatus = SspMapContext(
  285. &OriginalContextHandle,
  286. SessionKey,
  287. NegotiateFlags,
  288. NULL, // no token handle for clients
  289. NULL, // no password expiry for clients
  290. 0, // no userflags
  291. ContextData
  292. );
  293. if (!NT_SUCCESS(TempStatus)) {
  294. Status = TempStatus;
  295. SspPrint((SSP_CRITICAL, "SpInitLsaModeContext, SspMapContext returns %d\n", Status));
  296. goto Cleanup;
  297. }
  298. SspPrint((SSP_SESSION_KEYS, "Init sessionkey %lx %lx %lx %lx\n",
  299. ((DWORD*)SessionKey)[0],
  300. ((DWORD*)SessionKey)[1],
  301. ((DWORD*)SessionKey)[2],
  302. ((DWORD*)SessionKey)[3]
  303. ));
  304. //
  305. // Yes, do load msv1_0.dll in the client's process
  306. // and ContextData will contain info to be passed on
  307. // to the InitializeSecurityContext counterpart that
  308. // runs in the client's process
  309. *MappedContext = TRUE;
  310. }
  311. //
  312. // Make sure this bit isn't sent to the caller
  313. //
  314. *ContextAttributes &= ~SSP_RET_REAUTHENTICATION;
  315. Cleanup:
  316. // Send the output stuff
  317. // pvBuffer is reassigned in case ISC-REQ_ALLOCATE_MEMORY has ben defined
  318. // if (OutputBuffers != NULL && OutputBuffers->cBuffers > 0 && OutputBuffers->pBuffers != NULL)
  319. // {
  320. // OutputBuffers->pBuffers->cbBuffer = FirstOutputToken.cbBuffer;
  321. // OutputBuffers->pBuffers->pvBuffer = FirstOutputToken.pvBuffer;
  322. // }
  323. SspPrint((SSP_API, "Leaving SpInitLsaModeContext for Old:0x%x, New:0x%x\n", OldContextHandle, *NewContextHandle));
  324. //
  325. // Convert and save, will be (perhaps traced then) returned
  326. //
  327. Status = (SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
  328. //
  329. //Trace the end of this call
  330. //
  331. if (NtlmGlobalEventTraceFlag){
  332. //Header goo
  333. SET_TRACE_HEADER(TraceInfo,
  334. NtlmInitializeGuid,
  335. EVENT_TRACE_TYPE_END,
  336. WNODE_FLAG_TRACED_GUID|WNODE_FLAG_USE_MOF_PTR,
  337. 4);
  338. SET_TRACE_DATA(TraceInfo,
  339. TRACE_INITACC_STAGEHINT,
  340. TraceHint);
  341. SET_TRACE_DATA(TraceInfo,
  342. TRACE_INITACC_INCONTEXT,
  343. OldContextHandle);
  344. SET_TRACE_DATAPTR(TraceInfo,
  345. TRACE_INITACC_OUTCONTEXT,
  346. NewContextHandle);
  347. SET_TRACE_DATA(TraceInfo,
  348. TRACE_INITACC_STATUS,
  349. Status);
  350. TraceEvent(
  351. NtlmGlobalTraceLoggerHandle,
  352. (PEVENT_TRACE_HEADER)&TraceInfo
  353. );
  354. }
  355. return Status;
  356. }
  357. NTSTATUS NTAPI
  358. SpApplyControlToken(
  359. IN ULONG_PTR ContextHandle,
  360. IN PSecBufferDesc ControlToken
  361. )
  362. {
  363. SspPrint((SSP_API, "Entering SpApplyControlToken\n"));
  364. UNREFERENCED_PARAMETER(ContextHandle);
  365. UNREFERENCED_PARAMETER(ControlToken);
  366. SspPrint((SSP_API, "Leaving SpApplyControlToken\n"));
  367. return(SEC_E_UNSUPPORTED_FUNCTION);
  368. }
  369. //+-------------------------------------------------------------------------
  370. //
  371. // Function: SpAcceptLsaModeContext
  372. //
  373. // Synopsis: NtLm implementation of AcceptSecurityContext call.
  374. // This routine accepts an AP request message from a client
  375. // and verifies that it is a valid ticket. If mutual
  376. // authentication is desired an AP reply is generated to
  377. // send back to the client.
  378. //
  379. // Effects:
  380. //
  381. // Arguments:
  382. //
  383. // Requires:
  384. //
  385. // Returns:
  386. //
  387. // Notes:
  388. //
  389. //
  390. //--------------------------------------------------------------------------
  391. NTSTATUS NTAPI
  392. SpAcceptLsaModeContext(
  393. IN OPTIONAL ULONG_PTR CredentialHandle,
  394. IN OPTIONAL ULONG_PTR OldContextHandle,
  395. IN PSecBufferDesc InputBuffers,
  396. IN ULONG ContextReqFlags,
  397. IN ULONG TargetDataRep,
  398. OUT PULONG_PTR NewContextHandle,
  399. OUT PSecBufferDesc OutputBuffers,
  400. OUT PULONG ContextAttributes,
  401. OUT PTimeStamp ExpirationTime,
  402. OUT PBOOLEAN MappedContext,
  403. OUT PSecBuffer ContextData
  404. )
  405. /*++
  406. Routine Description:
  407. Allows a remotely initiated security context between the application
  408. and a remote peer to be established. To complete the establishment of
  409. context one or more reply tokens may be required from remote peer.
  410. This function is the server counterpart to the
  411. InitializeSecurityContext API. The ContextAttributes is a bit mask
  412. representing various context level functions viz. delegation, mutual
  413. authentication, confidentiality, replay detection and sequence
  414. detection. This API is used by the server side. When a request comes
  415. in, the server uses the ContextReqFlags parameter to specify what
  416. it requires of the session. In this fashion, a server can specify that
  417. clients must be capable of using a confidential or integrity checked
  418. session, and fail clients that can't meet that demand. Alternatively,
  419. a server can require nothing, and whatever the client can provide or
  420. requires is returned in the pfContextAttributes parameter. For a
  421. package that supports 3 leg mutual authentication, the calling sequence
  422. would be: Client provides a token, server calls Accept the first time,
  423. generating a reply token. The client uses this in a second call to
  424. InitializeSecurityContext, and generates a final token. This token is
  425. then used in the final call to Accept to complete the session. Another
  426. example would be the LAN Manager/NT authentication style. The client
  427. connects to negotiate a protocol. The server calls Accept to set up a
  428. context and generate a challenge to the client. The client calls
  429. InitializeSecurityContext and creates a response. The server then
  430. calls Accept the final time to allow the package to verify the response
  431. is appropriate for the challenge.
  432. Arguments:
  433. CredentialHandle - Handle to the credentials to be used to
  434. create the context.
  435. OldContextHandle - Handle to the partially formed context, if this is
  436. a second call (see above) or NULL if this is the first call.
  437. InputToken - Pointer to the input token. In the first call this
  438. token can either be NULL or may contain security package specific
  439. information.
  440. ContextReqFlags - Requirements of the context, package specific.
  441. #define ASC_REQ_DELEGATE 0x00000001
  442. #define ASC_REQ_MUTUAL_AUTH 0x00000002
  443. #define ASC_REQ_REPLAY_DETECT 0x00000004
  444. #define ASC_REQ_SEQUENCE_DETECT 0x00000008
  445. #define ASC_REQ_CONFIDENTIALITY 0x00000010
  446. #define ASC_REQ_ALLOCATE_MEMORY 0x00000100
  447. #define ASC_REQ_USE_DCE_STYLE 0x00000200
  448. TargetDataRep - Long indicating the data representation (byte ordering, etc)
  449. on the target. The constant SECURITY_NATIVE_DREP may be supplied
  450. by the transport indicating that the native format is in use.
  451. NewContextHandle - New context handle. If this is a second call, this
  452. can be the same as OldContextHandle.
  453. OutputToken - Buffer to receive the output token.
  454. ContextAttributes -Attributes of the context established.
  455. #define ASC_RET_DELEGATE 0x00000001
  456. #define ASC_RET_MUTUAL_AUTH 0x00000002
  457. #define ASC_RET_REPLAY_DETECT 0x00000004
  458. #define ASC_RET_SEQUENCE_DETECT 0x00000008
  459. #define ASC_RET_CONFIDENTIALITY 0x00000010
  460. #define ASC_RET_ALLOCATED_BUFFERS 0x00000100
  461. #define ASC_RET_USED_DCE_STYLE 0x00000200
  462. ExpirationTime - Expiration time of the context.
  463. Return Value:
  464. STATUS_SUCCESS - Message handled
  465. SEC_I_CONTINUE_NEEDED -- Caller should call again later
  466. SEC_E_NO_SPM -- Security Support Provider is not running
  467. SEC_E_INVALID_TOKEN -- Token improperly formatted
  468. SEC_E_INVALID_HANDLE -- Credential/Context Handle is invalid
  469. SEC_E_BUFFER_TOO_SMALL -- Buffer for output token isn't big enough
  470. SEC_E_LOGON_DENIED -- User is no allowed to logon to this server
  471. SEC_E_INSUFFICIENT_MEMORY -- Not enough memory
  472. --*/
  473. {
  474. NTSTATUS Status = STATUS_SUCCESS;
  475. SecBuffer TempTokens[3];
  476. PSecBuffer FirstInputToken;
  477. PSecBuffer SecondInputToken;
  478. PSecBuffer FirstOutputToken;
  479. ULONG NegotiateFlags = 0;
  480. UCHAR SessionKey[MSV1_0_USER_SESSION_KEY_LENGTH];
  481. HANDLE TokenHandle = NULL;
  482. NTSTATUS SubStatus = STATUS_SUCCESS;
  483. TimeStamp PasswordExpiry;
  484. ULONG UserFlags;
  485. //Tracing State
  486. NTLM_TRACE_INFO TraceInfo = {0};
  487. UINT32 TraceHint = 0;
  488. SspPrint((SSP_API, "Entering SpAcceptLsaModeContext for Old:0x%x, New:0x%x\n", OldContextHandle, *NewContextHandle));
  489. //Begin tracing an AcceptSecurityContext call for NTLM
  490. if (NtlmGlobalEventTraceFlag){
  491. //Header goo
  492. SET_TRACE_HEADER(TraceInfo,
  493. NtlmAcceptGuid,
  494. EVENT_TRACE_TYPE_START,
  495. WNODE_FLAG_TRACED_GUID|WNODE_FLAG_USE_MOF_PTR,
  496. 2);
  497. TraceHint = (OldContextHandle == 0)?
  498. TRACE_ACCEPT_NEGOTIATE:
  499. TRACE_ACCEPT_AUTHENTICATE;
  500. SET_TRACE_DATA(TraceInfo,
  501. TRACE_INITACC_STAGEHINT,
  502. TraceHint);
  503. SET_TRACE_DATA(TraceInfo,
  504. TRACE_INITACC_INCONTEXT,
  505. OldContextHandle);
  506. TraceEvent(NtlmGlobalTraceLoggerHandle,
  507. (PEVENT_TRACE_HEADER)&TraceInfo);
  508. }
  509. FirstInputToken = &TempTokens[0];
  510. SecondInputToken = &TempTokens[1];
  511. FirstOutputToken = &TempTokens[2];
  512. RtlZeroMemory(
  513. TempTokens,
  514. sizeof(TempTokens)
  515. );
  516. RtlZeroMemory(
  517. SessionKey,
  518. MSV1_0_USER_SESSION_KEY_LENGTH
  519. );
  520. *MappedContext = FALSE;
  521. //
  522. // Validate the arguments
  523. //
  524. UNREFERENCED_PARAMETER( TargetDataRep );
  525. if ( !SspGetTokenBuffer( InputBuffers,
  526. 0, // get the first SECBUFFER_TOKEN
  527. &FirstInputToken,
  528. TRUE ) ) {
  529. Status = SEC_E_INVALID_TOKEN;
  530. SspPrint((SSP_CRITICAL, "SpAcceptLsaModeContext, SspGetTokenBuffer (FirstInputToken) returns %d\n", Status));
  531. goto Cleanup;
  532. }
  533. if ( !SspGetTokenBuffer( InputBuffers,
  534. 1, // get the second SECBUFFER_TOKEN
  535. &SecondInputToken,
  536. TRUE ) ) {
  537. Status = SEC_E_INVALID_TOKEN;
  538. SspPrint((SSP_CRITICAL, "SpAcceptLsaModeContext, SspGetTokenBuffer (SecondInputToken) returns %d\n", Status));
  539. goto Cleanup;
  540. }
  541. if ( !SspGetTokenBuffer( OutputBuffers,
  542. 0, // get the first SECBUFFER_TOKEN
  543. &FirstOutputToken,
  544. FALSE ) ) {
  545. Status = SEC_E_INVALID_TOKEN;
  546. SspPrint((SSP_CRITICAL, "SpAcceptLsaModeContext, SspGetTokenBuffer (FirstOutputToken) returns %d\n", Status));
  547. goto Cleanup;
  548. }
  549. //
  550. // If no previous context was passed in this is the first call.
  551. //
  552. if ( (OldContextHandle == 0 ) &&
  553. (SecondInputToken->cbBuffer == 0)) {
  554. if ( !ARGUMENT_PRESENT( CredentialHandle ) ) {
  555. Status = SEC_E_INVALID_HANDLE;
  556. SspPrint((SSP_CRITICAL, "SpAcceptLsaModeContext, No CredentialHandle\n"));
  557. goto Cleanup;
  558. }
  559. Status = SsprHandleNegotiateMessage(
  560. CredentialHandle,
  561. NewContextHandle,
  562. ContextReqFlags,
  563. FirstInputToken->cbBuffer,
  564. FirstInputToken->pvBuffer,
  565. &FirstOutputToken->cbBuffer,
  566. &FirstOutputToken->pvBuffer,
  567. ContextAttributes,
  568. ExpirationTime );
  569. //
  570. // If context was passed in, continue where we left off.
  571. //
  572. } else {
  573. *NewContextHandle = OldContextHandle;
  574. Status = SsprHandleAuthenticateMessage(
  575. CredentialHandle,
  576. NewContextHandle,
  577. ContextReqFlags,
  578. FirstInputToken->cbBuffer,
  579. FirstInputToken->pvBuffer,
  580. SecondInputToken->cbBuffer,
  581. SecondInputToken->pvBuffer,
  582. &FirstOutputToken->cbBuffer,
  583. &FirstOutputToken->pvBuffer,
  584. ContextAttributes,
  585. ExpirationTime,
  586. SessionKey,
  587. &NegotiateFlags,
  588. &TokenHandle,
  589. &SubStatus,
  590. &PasswordExpiry,
  591. &UserFlags
  592. );
  593. //
  594. // for errors such as PASSWORD_EXPIRED, return the SubStatus, which
  595. // is more descriptive than the generic error code.
  596. //
  597. if( Status == STATUS_ACCOUNT_RESTRICTION )
  598. Status = SubStatus;
  599. }
  600. if ((Status == SEC_E_OK) &&
  601. !(*ContextAttributes & SSP_RET_REAUTHENTICATION)) {
  602. Status = SspMapContext(
  603. NewContextHandle,
  604. SessionKey,
  605. NegotiateFlags,
  606. TokenHandle,
  607. &PasswordExpiry,
  608. UserFlags,
  609. ContextData
  610. );
  611. if (!NT_SUCCESS(Status)) {
  612. SspPrint((SSP_CRITICAL, "SpAcceptLsaModeContext, SspMapContext returns %d\n", Status));
  613. goto Cleanup;
  614. }
  615. SspPrint((SSP_SESSION_KEYS, "Accept sessionkey %lx %lx %lx %lx\n",
  616. ((DWORD*)SessionKey)[0],
  617. ((DWORD*)SessionKey)[1],
  618. ((DWORD*)SessionKey)[2],
  619. ((DWORD*)SessionKey)[3]
  620. ));
  621. *MappedContext = TRUE;
  622. } else {
  623. //
  624. // Make sure this bit isn't sent to the caller
  625. //
  626. *ContextAttributes &= ~SSP_RET_REAUTHENTICATION;
  627. }
  628. Cleanup:
  629. if (TokenHandle != NULL) {
  630. NtClose(TokenHandle);
  631. }
  632. // TODO: this really necessary since we're in LSA mode???
  633. SetLastError(RtlNtStatusToDosError(SubStatus));
  634. SspPrint((SSP_API, "Leaving SpAcceptLsaModeContext for Old:0x%x, New:0x%x\n", OldContextHandle, *NewContextHandle));
  635. //Convert and save, will be (perhaps traced then) returned
  636. Status = (SspNtStatusToSecStatus(Status, SEC_E_INTERNAL_ERROR));
  637. //Trace the end of this call
  638. if (NtlmGlobalEventTraceFlag){
  639. //Header goo
  640. SET_TRACE_HEADER(TraceInfo,
  641. NtlmAcceptGuid,
  642. EVENT_TRACE_TYPE_END,
  643. WNODE_FLAG_TRACED_GUID|WNODE_FLAG_USE_MOF_PTR,
  644. 4);
  645. SET_TRACE_DATA(TraceInfo,
  646. TRACE_INITACC_STAGEHINT,
  647. TraceHint);
  648. SET_TRACE_DATA(TraceInfo,
  649. TRACE_INITACC_INCONTEXT,
  650. OldContextHandle);
  651. SET_TRACE_DATAPTR(TraceInfo,
  652. TRACE_INITACC_OUTCONTEXT,
  653. NewContextHandle);
  654. SET_TRACE_DATA(TraceInfo,
  655. TRACE_INITACC_STATUS,
  656. Status);
  657. TraceEvent(
  658. NtlmGlobalTraceLoggerHandle,
  659. (PEVENT_TRACE_HEADER)&TraceInfo
  660. );
  661. }
  662. // Converted to SecStatus before tracing
  663. return Status;
  664. }