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.

849 lines
29 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. exsessup.c
  5. Abstract:
  6. This module implements the routines for setting up a session using the
  7. the securitt negotiation mechanism ( post NT40 ).
  8. Author:
  9. Balan Sethu Raman [SethuR] 7-March-1995
  10. Revision History:
  11. Notes:
  12. The extended session setup is used in the new security negotiation scheme
  13. which involves multiple round trips to the server before the user can be
  14. successfully authenticated and a session established.
  15. In the modified scheme the negotiate returns a BLOB which is passed to the
  16. client side security package to initiate the session setup procedure. The
  17. BLOB returned by the server contains an encoding of the security packages
  18. supported by the server.
  19. The client side security package when presented with this BLOB chooses a
  20. security package and encodes the client credentials in the form of a
  21. BLOB which is shipped to the server using the EXTENDED_SESSION_SETUP_ANDX
  22. SMB.
  23. The server has one of three responses to an EXTENDED_SESSION_SETUP_ANDX
  24. SMB presented by the client.
  25. 1) The server has enough information to establish the session.
  26. 2) The server cannot proceed with the session setup because of an
  27. error in the information presented by the client or otherwise.
  28. 3) The security package on the server needs an additional round trip
  29. before the session setup can be established. This is especially
  30. true of new security packages which support mutual authentication
  31. between the client and server.
  32. In the first two cases no further round trips are required. The action taken
  33. on the client side depends upon whether the server returned a BLOB. If the
  34. server returned a BLOB it must be presented to the client side security
  35. package to complete the session setup procedure.
  36. In the case of (3) the BLOB returned by the server must be presented to the
  37. client and the BLOB generated by the security package must be shipped back
  38. to the server.
  39. In the SMBCE_EXTENDED_SESSION_SETUP_EXCHANGE the following parameters support
  40. the protocol outlined above. A buffer with maximum server buffer size is allocated,
  41. locked and a MDL created as part of the exchange initialization. This buffer is
  42. used to hold the server response BLOB. Notice that this avoids redundant copying
  43. and handles all the known cases.
  44. --*/
  45. #include "precomp.h"
  46. #pragma hdrstop
  47. #include "exsessup.h"
  48. #ifdef ALLOC_PRAGMA
  49. #pragma alloc_text(PAGE, SmbCeInitializeExtendedSessionSetupExchange)
  50. #pragma alloc_text(PAGE, SmbCeDiscardExtendedSessionSetupExchange)
  51. #pragma alloc_text(PAGE, SmbExtSecuritySessionSetupExchangeStart)
  52. #pragma alloc_text(PAGE, SmbExtSecuritySessionSetupExchangeSendCompletionHandler)
  53. #endif
  54. // this string is used to test whether the server really supports security signature.
  55. // if the server returns back the deferent string on SMB header security signature of the
  56. // extended session setup response from the client sends out on the request, the server
  57. // does support security signature.
  58. CHAR InitialSecuritySignature[] = {"BSRSPYL "};
  59. extern BOOLEAN MRxSmbSecuritySignaturesEnabled;
  60. //
  61. // The Bug check file id for this module
  62. //
  63. #define BugCheckFileId (RDBSS_BUG_CHECK_SMB_NETROOT)
  64. //
  65. // The local debug trace level
  66. //
  67. #define Dbg (DEBUG_TRACE_DISPATCH)
  68. //
  69. // Forward declarations ...
  70. //
  71. NTSTATUS
  72. SmbCeInitializeExtendedSessionSetupExchange(
  73. PSMB_EXCHANGE* pExchangePtr,
  74. PMRX_V_NET_ROOT pVNetRoot)
  75. /*++
  76. Routine Description:
  77. This routine initializes an instance of a session setup exchange.
  78. Arguments:
  79. pExchange - the exchange instance
  80. pVNetRoot - the MRX_V_NET_ROOT instance associated with the exchange.
  81. Return Value:
  82. NTSTATUS - The return status for the operation
  83. --*/
  84. {
  85. NTSTATUS Status;
  86. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange;
  87. PAGED_CODE();
  88. ASSERT((pExchangePtr == NULL) ||
  89. ((*pExchangePtr)->Type == EXTENDED_SESSION_SETUP_EXCHANGE));
  90. Status = SmbCeInitializeExchange(
  91. pExchangePtr,
  92. NULL,
  93. pVNetRoot,
  94. EXTENDED_SESSION_SETUP_EXCHANGE,
  95. &ExtendedSessionSetupExchangeDispatch);
  96. if (Status == STATUS_SUCCESS) {
  97. PSMBCEDB_SERVER_ENTRY pServerEntry;
  98. pServerEntry = SmbCeGetExchangeServerEntry(*pExchangePtr);
  99. pExtSessionSetupExchange = (PSMB_EXTENDED_SESSION_SETUP_EXCHANGE)
  100. (*pExchangePtr);
  101. pExtSessionSetupExchange->SmbCeFlags |= SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION;
  102. // Allocate the buffer to hold the server response.
  103. pExtSessionSetupExchange->BufferLength =
  104. pServerEntry->Server.MaximumBufferSize;
  105. pExtSessionSetupExchange->pActualBuffer = RxAllocatePoolWithTag(
  106. PagedPool,
  107. (pExtSessionSetupExchange->BufferLength + TRANSPORT_HEADER_SIZE),
  108. MRXSMB_KERBEROS_POOLTAG);
  109. pExtSessionSetupExchange->pServerResponseBlob = NULL;
  110. pExtSessionSetupExchange->ServerResponseBlobLength = 0;
  111. pExtSessionSetupExchange->Reparse = TRUE;
  112. if (pExtSessionSetupExchange->pActualBuffer != NULL) {
  113. (PCHAR) pExtSessionSetupExchange->pBuffer =
  114. (PCHAR) pExtSessionSetupExchange->pActualBuffer + TRANSPORT_HEADER_SIZE;
  115. RxAllocateHeaderMdl(
  116. pExtSessionSetupExchange->pBuffer,
  117. pExtSessionSetupExchange->BufferLength,
  118. pExtSessionSetupExchange->pBufferAsMdl
  119. );
  120. if (pExtSessionSetupExchange->pBufferAsMdl != NULL) {
  121. RxProbeAndLockHeaderPages(
  122. pExtSessionSetupExchange->pBufferAsMdl,
  123. KernelMode,
  124. IoModifyAccess,
  125. Status);
  126. } else {
  127. Status = STATUS_INSUFFICIENT_RESOURCES;
  128. }
  129. } else {
  130. Status = STATUS_INSUFFICIENT_RESOURCES;
  131. }
  132. if (Status != STATUS_SUCCESS) {
  133. if (pExtSessionSetupExchange->pBufferAsMdl != NULL) {
  134. IoFreeMdl(pExtSessionSetupExchange->pBufferAsMdl);
  135. }
  136. if (pExtSessionSetupExchange->pActualBuffer != NULL) {
  137. RxFreePool(pExtSessionSetupExchange->pActualBuffer);
  138. }
  139. SmbCePrepareExchangeForReuse(*pExchangePtr);
  140. }
  141. }
  142. return Status;
  143. }
  144. VOID
  145. SmbCeDiscardExtendedSessionSetupExchange(
  146. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange)
  147. /*++
  148. Routine Description:
  149. This routine discards an instance of a session setup exchange.
  150. Arguments:
  151. pExchange - the exchange instance
  152. --*/
  153. {
  154. PAGED_CODE();
  155. if (pExtSessionSetupExchange->pBufferAsMdl != NULL) {
  156. RxUnlockHeaderPages(pExtSessionSetupExchange->pBufferAsMdl);
  157. IoFreeMdl(pExtSessionSetupExchange->pBufferAsMdl);
  158. }
  159. if (pExtSessionSetupExchange->pActualBuffer != NULL) {
  160. RxFreePool(pExtSessionSetupExchange->pActualBuffer);
  161. }
  162. if (pExtSessionSetupExchange->pServerResponseBlob != NULL) {
  163. RxFreePool(pExtSessionSetupExchange->pServerResponseBlob);
  164. }
  165. // Normally discrading the exchange results in the session state being
  166. // updated. In order to avoid race conditions between those exchanges
  167. // which are awaiting this construction and the updating of the session
  168. // state it is done locally. COnsequently the exchange state needs to be
  169. // updated so the the discard routine does not attempt it again.
  170. pExtSessionSetupExchange->SmbCeFlags &= ~SMBCE_EXCHANGE_SESSION_CONSTRUCTOR;
  171. SmbCeDiscardExchange(
  172. (PSMB_EXCHANGE)pExtSessionSetupExchange);
  173. }
  174. NTSTATUS
  175. SmbExtSecuritySessionSetupExchangeStart(
  176. PSMB_EXCHANGE pExchange)
  177. /*++
  178. Routine Description:
  179. This is the start routine for net root construction exchanges. This initiates the
  180. construction of the appropriate SMB's if required.
  181. Arguments:
  182. pExchange - the exchange instance
  183. Return Value:
  184. RXSTATUS - The return status for the operation
  185. --*/
  186. {
  187. NTSTATUS Status;
  188. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange;
  189. PSMB_HEADER pSmbHeader;
  190. PREQ_NT_EXTENDED_SESSION_SETUP_ANDX pSessionSetupRequest;
  191. PGENERIC_ANDX pGenericAndX;
  192. PSMBCEDB_SERVER_ENTRY pServerEntry;
  193. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  194. ULONG SmbBufferUnconsumed;
  195. USHORT Flags2 = 0;
  196. PAGED_CODE();
  197. pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  198. pSessionEntry = SmbCeGetExchangeSessionEntry(pExchange);
  199. pExtSessionSetupExchange = (PSMB_EXTENDED_SESSION_SETUP_EXCHANGE)pExchange;
  200. if (!pExtSessionSetupExchange->FirstSessionSetup) {
  201. if (pSessionEntry->Header.State == SMBCEDB_ACTIVE) {
  202. return STATUS_SUCCESS;
  203. } else {
  204. return STATUS_USER_SESSION_DELETED;
  205. }
  206. }
  207. ASSERT((pExtSessionSetupExchange->Type == EXTENDED_SESSION_SETUP_EXCHANGE) &&
  208. (pExtSessionSetupExchange->pBuffer != NULL) &&
  209. (pExtSessionSetupExchange->pBufferAsMdl != NULL));
  210. SmbCeLog(("ExtSecSessSetup - %lx %lx\n",
  211. pExtSessionSetupExchange->pServerResponseBlob, pSessionEntry));
  212. SmbLog(LOG,
  213. SmbExtSecuritySessionSetupExchangeStart,
  214. LOGPTR(pExtSessionSetupExchange->pServerResponseBlob)
  215. LOGPTR(pSessionEntry));
  216. pSmbHeader = (PSMB_HEADER)(pExtSessionSetupExchange->pBuffer);
  217. // Fill in the buffer header
  218. pSessionSetupRequest = (PREQ_NT_EXTENDED_SESSION_SETUP_ANDX)(pSmbHeader + 1);
  219. pGenericAndX = (PGENERIC_ANDX)pSessionSetupRequest;
  220. SmbBufferUnconsumed = pExtSessionSetupExchange->BufferLength - sizeof(SMB_HEADER);
  221. Flags2 |= (SMB_FLAGS2_UNICODE |
  222. SMB_FLAGS2_KNOWS_EAS |
  223. SMB_FLAGS2_KNOWS_LONG_NAMES |
  224. SMB_FLAGS2_NT_STATUS |
  225. SMB_FLAGS2_EXTENDED_SECURITY);
  226. *((PULONG)&pSmbHeader->Protocol) = SMB_HEADER_PROTOCOL;
  227. pSmbHeader->Flags = (SMB_FLAGS_CASE_INSENSITIVE | SMB_FLAGS_CANONICALIZED_PATHS);
  228. pSmbHeader->Flags2 = Flags2;
  229. pSmbHeader->Pid = MRXSMB_PROCESS_ID;
  230. pSmbHeader->Uid = pSessionEntry->Session.UserId;
  231. pSmbHeader->Tid = 0;
  232. pSmbHeader->ErrorClass = 0;
  233. pSmbHeader->Reserved = 0;
  234. pSmbHeader->Command = SMB_COM_SESSION_SETUP_ANDX;
  235. SmbPutUshort(&pSmbHeader->Error,0);
  236. if (MRxSmbSecuritySignaturesEnabled) {
  237. pSmbHeader->Flags2 |= SMB_FLAGS2_SMB_SECURITY_SIGNATURE;
  238. }
  239. // Build the session setup and x.
  240. Status = SMBCE_SERVER_DIALECT_DISPATCH(
  241. &pServerEntry->Server,
  242. BuildSessionSetup,
  243. (pExchange,
  244. pGenericAndX,
  245. &SmbBufferUnconsumed));
  246. if (Status == STATUS_SUCCESS) {
  247. // Update the buffer for the construction of the following SMB.
  248. SmbPutUshort(
  249. &pSessionSetupRequest->AndXOffset,
  250. (USHORT)(pExtSessionSetupExchange->BufferLength - SmbBufferUnconsumed));
  251. pSessionSetupRequest->AndXCommand = SMB_COM_NO_ANDX_COMMAND;
  252. pSessionSetupRequest->AndXReserved = 0;
  253. if (pServerEntry->SecuritySignaturesEnabled &&
  254. !pServerEntry->SecuritySignaturesActive) {
  255. RtlCopyMemory(pSmbHeader->SecuritySignature,InitialSecuritySignature,SMB_SECURITY_SIGNATURE_LENGTH);
  256. }
  257. }
  258. if (Status == STATUS_SUCCESS) {
  259. Status = SmbCeTranceive(
  260. pExchange,
  261. (RXCE_SEND_PARTIAL | RXCE_SEND_SYNCHRONOUS),
  262. pExtSessionSetupExchange->pBufferAsMdl,
  263. (pExtSessionSetupExchange->BufferLength -
  264. SmbBufferUnconsumed));
  265. RxDbgTrace( 0, Dbg, ("Net Root SmbCeTranceive returned %lx\n",Status));
  266. }
  267. return Status;
  268. }
  269. NTSTATUS
  270. ParseExtSecuritySessionSetupResponse(
  271. IN PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange,
  272. IN ULONG BytesIndicated,
  273. IN ULONG BytesAvailable,
  274. IN PSMB_HEADER pSmbHeader)
  275. /*++
  276. Routine Description:
  277. This is the routine used to parse the extended session setup response from
  278. the server.
  279. Arguments:
  280. pExtSessionSetupExchange -- the exchange instance
  281. BytesIndicated -- the number of bytes indicated
  282. BytesAvailable -- the total number of bytes sent by the server
  283. pSmbHeader -- the SMB header ( beginning of the response)
  284. Return Value:
  285. NTSTATUS - The return status for the operation
  286. --*/
  287. {
  288. NTSTATUS Status;
  289. ULONG ResponseLength;
  290. PRESP_NT_EXTENDED_SESSION_SETUP_ANDX pSessionSetupResponse;
  291. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  292. if (BytesIndicated < sizeof(SMB_HEADER) + 1) {
  293. // Abort the exchange. No further processing can be done.
  294. return STATUS_INVALID_NETWORK_RESPONSE;
  295. }
  296. pSessionEntry = SmbCeGetExchangeSessionEntry(pExtSessionSetupExchange);
  297. pSessionSetupResponse = (PRESP_NT_EXTENDED_SESSION_SETUP_ANDX)(pSmbHeader + 1);
  298. if ((pSessionSetupResponse->WordCount != 4) &&
  299. (pSessionSetupResponse->WordCount != 0)) {
  300. return STATUS_INVALID_NETWORK_RESPONSE;
  301. }
  302. // Parse the header and extract the status. The status has special significance
  303. // for further processing. If the server returns a BLOB and
  304. // STATUS_MORE_PROCESSING_REQUIRED additional round trips are required.
  305. pExtSessionSetupExchange->Status = GetSmbResponseNtStatus(pSmbHeader,(PSMB_EXCHANGE)pExtSessionSetupExchange);
  306. // Mask the errors returned by the security packagte on the server
  307. if (pExtSessionSetupExchange->Status == STATUS_INVALID_HANDLE) {
  308. pExtSessionSetupExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  309. }
  310. //if no blob came back.....just get out
  311. if (pSessionSetupResponse->WordCount == 0) {
  312. pExtSessionSetupExchange->ServerResponseBlobLength = 0;
  313. return STATUS_SUCCESS;
  314. }
  315. // Squirrel away the UID on the first response. This UID needs to be used in
  316. // subsequent trips to complete the session establishment as it identifies
  317. // the session to the server.
  318. pSessionEntry->Session.UserId = pSmbHeader->Uid;
  319. if (FlagOn(SmbGetUshort(&pSessionSetupResponse->Action), SMB_SETUP_GUEST)) {
  320. pSessionEntry->Session.Flags |= SMBCE_SESSION_FLAGS_GUEST_SESSION;
  321. }
  322. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseExtSecuritySessionSetupResponse BytesIndicated %ld\n",BytesIndicated));
  323. RxDbgTrace( 0, (DEBUG_TRACE_ALWAYS), ("ParseExtSecuritySessionSetupResponse BytesAvailable %ld\n",BytesAvailable));
  324. // The bytes indicated should be atleast cover the SMB_HEADER and the
  325. // session setup response ( fixed portion )
  326. ResponseLength = sizeof(SMB_HEADER) +
  327. FIELD_OFFSET(
  328. RESP_NT_EXTENDED_SESSION_SETUP_ANDX,
  329. Buffer);
  330. if (BytesIndicated > ResponseLength) {
  331. // Compute the extended session setup response length.
  332. pExtSessionSetupExchange->ResponseLength =
  333. ResponseLength +
  334. SmbGetUshort(
  335. &pSessionSetupResponse->ByteCount);
  336. RxDbgTrace(0,Dbg,("Kerberos session setup response length %ld\n",pExtSessionSetupExchange->ResponseLength));
  337. if (pExtSessionSetupExchange->ResponseLength > pExtSessionSetupExchange->BufferLength) {
  338. return STATUS_BUFFER_OVERFLOW;
  339. }
  340. if (BytesIndicated < pExtSessionSetupExchange->ResponseLength) {
  341. // Set up the response for copying the data.
  342. Status = pExtSessionSetupExchange->Reparse
  343. ? STATUS_MORE_PROCESSING_REQUIRED
  344. : STATUS_INVALID_NETWORK_RESPONSE;
  345. pExtSessionSetupExchange->Status = Status;
  346. } else {
  347. // set up the offsets in the response.
  348. pExtSessionSetupExchange->ServerResponseBlobOffset =
  349. sizeof(SMB_HEADER) +
  350. FIELD_OFFSET(
  351. RESP_NT_EXTENDED_SESSION_SETUP_ANDX,
  352. Buffer);
  353. pExtSessionSetupExchange->ServerResponseBlobLength =
  354. pSessionSetupResponse->SecurityBlobLength;
  355. // Copy the response onto the buffer associated with the exchange.
  356. RtlCopyMemory(
  357. pExtSessionSetupExchange->pBuffer,
  358. pSmbHeader,
  359. pExtSessionSetupExchange->ResponseLength);
  360. Status = STATUS_SUCCESS;
  361. }
  362. } else {
  363. // Abort the exchange. No further processing can be done.
  364. Status = STATUS_INVALID_NETWORK_RESPONSE;
  365. pExtSessionSetupExchange->Status = Status;
  366. }
  367. return Status;
  368. }
  369. NTSTATUS
  370. SmbExtSecuritySessionSetupExchangeReceive(
  371. IN struct _SMB_EXCHANGE *pExchange, // The exchange instance
  372. IN ULONG BytesIndicated,
  373. IN ULONG BytesAvailable,
  374. OUT ULONG *pBytesTaken,
  375. IN PSMB_HEADER pSmbHeader,
  376. OUT PMDL *pDataBufferPointer,
  377. OUT PULONG pDataSize,
  378. IN ULONG ReceiveFlags)
  379. /*++
  380. Routine Description:
  381. This is the recieve indication handling routine for net root construction exchanges
  382. Arguments:
  383. pExchange - the exchange instance
  384. BytesIndicated - the number of bytes indicated
  385. Bytes Available - the number of bytes available
  386. pBytesTaken - the number of bytes consumed
  387. pSmbHeader - the byte buffer
  388. pDataBufferPointer - the buffer into which the remaining data is to be copied.
  389. pDataSize - the buffer size.
  390. Return Value:
  391. RXSTATUS - The return status for the operation
  392. Notes:
  393. This routine is called at DPC level.
  394. --*/
  395. {
  396. NTSTATUS Status;
  397. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange;
  398. PSMBCEDB_SERVER_ENTRY pServerEntry = SmbCeGetExchangeServerEntry(pExchange);
  399. ULONG SessionSetupResponseLength = 0;
  400. pExtSessionSetupExchange = (PSMB_EXTENDED_SESSION_SETUP_EXCHANGE)pExchange;
  401. if (pServerEntry->SecuritySignaturesEnabled &&
  402. !pServerEntry->SecuritySignaturesActive &&
  403. RtlCompareMemory(pSmbHeader->SecuritySignature,
  404. InitialSecuritySignature,
  405. SMB_SECURITY_SIGNATURE_LENGTH) != SMB_SECURITY_SIGNATURE_LENGTH) {
  406. pExtSessionSetupExchange->pResumptionContext->SecuritySignatureReturned = TRUE;
  407. }
  408. // Parse the response.
  409. Status = ParseExtSecuritySessionSetupResponse(
  410. pExtSessionSetupExchange,
  411. BytesIndicated,
  412. BytesAvailable,
  413. pSmbHeader);
  414. if (Status != STATUS_MORE_PROCESSING_REQUIRED) {
  415. *pBytesTaken = BytesAvailable;
  416. Status = STATUS_SUCCESS;
  417. } else {
  418. *pBytesTaken = 0;
  419. *pDataBufferPointer = pExtSessionSetupExchange->pBufferAsMdl;
  420. *pDataSize = pExtSessionSetupExchange->ResponseLength;
  421. }
  422. return Status;
  423. }
  424. NTSTATUS
  425. SmbExtSecuritySessionSetupExchangeSendCompletionHandler(
  426. IN PSMB_EXCHANGE pExchange, // The exchange instance
  427. IN PMDL pXmitBuffer,
  428. IN NTSTATUS SendCompletionStatus)
  429. /*++
  430. Routine Description:
  431. This is the send call back indication handling routine for net root construction exchanges
  432. Arguments:
  433. pExchange - the exchange instance
  434. Return Value:
  435. RXSTATUS - The return status for the operation
  436. --*/
  437. {
  438. return STATUS_SUCCESS;
  439. }
  440. NTSTATUS
  441. SmbExtSecuritySessionSetupExchangeCopyDataHandler(
  442. IN PSMB_EXCHANGE pExchange, // The exchange instance
  443. IN PMDL pCopyDataBuffer,
  444. IN ULONG DataSize)
  445. /*++
  446. Routine Description:
  447. This is the copy data handling routine for net root construction exchanges
  448. Arguments:
  449. pExchange - the exchange instance
  450. Return Value:
  451. RXSTATUS - The return status for the operation
  452. --*/
  453. {
  454. NTSTATUS Status;
  455. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange;
  456. PSMB_HEADER pSmbHeader;
  457. pExtSessionSetupExchange = (PSMB_EXTENDED_SESSION_SETUP_EXCHANGE)pExchange;
  458. pSmbHeader = (PSMB_HEADER)(pExtSessionSetupExchange->pBuffer);
  459. Status = ParseExtSecuritySessionSetupResponse(
  460. pExtSessionSetupExchange,
  461. DataSize,
  462. DataSize,
  463. pSmbHeader);
  464. // At this time the parse routine cannot return STATUS_MORE_PROCESSING_REQUIRED
  465. // as the entire response has been consumed.
  466. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  467. DbgPrint("Mapping Incomplete Server Response to Invalid Response\n");
  468. SmbLogError(Status,
  469. LOG,
  470. SmbExtSecuritySessionSetupExchangeCopyDataHandler,
  471. LOGPTR(pExtSessionSetupExchange));
  472. pExtSessionSetupExchange->Status = STATUS_INVALID_NETWORK_RESPONSE;
  473. }
  474. return STATUS_SUCCESS;
  475. }
  476. NTSTATUS
  477. SmbExtSecuritySessionSetupExchangeFinalize(
  478. PSMB_EXCHANGE pExchange,
  479. BOOLEAN *pPostFinalize)
  480. /*++
  481. Routine Description:
  482. This routine finalkzes the construct net root exchange. It resumes the RDBSS by invoking
  483. the call back and discards the exchange
  484. Arguments:
  485. pExchange - the exchange instance
  486. CurrentIrql - the current interrupt request level
  487. pPostFinalize - a pointer to a BOOLEAN if the request should be posted
  488. Return Value:
  489. RXSTATUS - The return status for the operation
  490. --*/
  491. {
  492. NTSTATUS Status;
  493. PSMB_EXTENDED_SESSION_SETUP_EXCHANGE pExtSessionSetupExchange;
  494. PSMBCE_RESUMPTION_CONTEXT pResumptionContext;
  495. pExtSessionSetupExchange = (PSMB_EXTENDED_SESSION_SETUP_EXCHANGE)pExchange;
  496. if (!pExtSessionSetupExchange->RequestPosted) {
  497. pExtSessionSetupExchange->RequestPosted = TRUE;
  498. *pPostFinalize = TRUE;
  499. return STATUS_SUCCESS;
  500. } else {
  501. // reset the flag since the exchange will be reused
  502. pExtSessionSetupExchange->RequestPosted = FALSE;
  503. *pPostFinalize = FALSE;
  504. }
  505. // Determine if further processing is required. If not finalize the
  506. // session entry.
  507. RxDbgTrace(0,Dbg,
  508. ("SmbExtSecuritySessionSetupExchangeFinalize: pESSExchange->Status = %lx\n",pExtSessionSetupExchange->Status));
  509. // If the server returned STATUS_MORE_PROCESSING_REQUIRED and a BLOB was present
  510. // another trip to the server is required and we start all over again.
  511. if ((Status = pExtSessionSetupExchange->Status) != STATUS_MORE_PROCESSING_REQUIRED) {
  512. // The server returned an error other than STATUS_MORE_PROCESSING_REQUIRED
  513. // The session establishment can be completed based on whether the server
  514. // returned a BLOB. If a BLOB was returned it needs to be passed to the
  515. // local security package. This will enable the local security package to
  516. // either complete the session establishment successfully or to extract
  517. // extended error information from the BLOB. This can in turn be used to
  518. // propogate more meaningful errors to the client.
  519. if (Status == STATUS_SUCCESS &&
  520. pExtSessionSetupExchange->ServerResponseBlobLength != 0) {
  521. PVOID pServerResponseBlob;
  522. // If we are not going back to the server an additional copy of the
  523. // server response BLOB is not required.
  524. pServerResponseBlob =
  525. ((PBYTE)pExtSessionSetupExchange->pBuffer +
  526. pExtSessionSetupExchange->ServerResponseBlobOffset);
  527. Status = ValidateServerExtendedSessionSetupResponse(
  528. pExtSessionSetupExchange,
  529. pServerResponseBlob,
  530. pExtSessionSetupExchange->ServerResponseBlobLength);
  531. }
  532. } else {
  533. // Make a copy of the server response blob so that the new session setup SMB
  534. // can be constructed
  535. if (pExtSessionSetupExchange->ServerResponseBlobLength != 0) {
  536. if (pExtSessionSetupExchange->pServerResponseBlob != NULL) {
  537. RxFreePool(pExtSessionSetupExchange->pServerResponseBlob);
  538. }
  539. pExtSessionSetupExchange->pServerResponseBlob =
  540. RxAllocatePoolWithTag(
  541. PagedPool,
  542. pExtSessionSetupExchange->ServerResponseBlobLength,
  543. MRXSMB_KERBEROS_POOLTAG);
  544. if (pExtSessionSetupExchange->pServerResponseBlob != NULL) {
  545. RtlCopyMemory(
  546. pExtSessionSetupExchange->pServerResponseBlob,
  547. ((PBYTE)pExtSessionSetupExchange->pBuffer +
  548. pExtSessionSetupExchange->ServerResponseBlobOffset),
  549. pExtSessionSetupExchange->ServerResponseBlobLength);
  550. } else {
  551. Status = STATUS_INSUFFICIENT_RESOURCES;
  552. }
  553. }
  554. }
  555. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  556. PMRX_V_NET_ROOT pVNetRoot;
  557. USHORT SmbCeFlags;
  558. PRX_CONTEXT RxContext;
  559. pVNetRoot = pExtSessionSetupExchange->SmbCeContext.pVNetRoot;
  560. RxContext = pExtSessionSetupExchange->RxContext;
  561. // This is required so that the session state is not effected as the exchange
  562. // is prepared for reuse. This will enable us to avoid redundant initialization
  563. // as well as to carry over the state from one trip to another easily.
  564. ClearFlag(
  565. pExtSessionSetupExchange->SmbCeFlags,
  566. SMBCE_EXCHANGE_SESSION_CONSTRUCTOR);
  567. SmbCePrepareExchangeForReuse((PSMB_EXCHANGE)pExtSessionSetupExchange);
  568. // Note: By invoking SmbCeInitializeExchange as opposed to
  569. // SmbCeInitializeExtendedSessionSetupExchange only the connection engine
  570. // portion of the exchange is initialized. This will enable us to carry
  571. // over the state ( the server response BLOB ) from one trip to another
  572. // easily.
  573. Status = SmbCeInitializeExchange(
  574. (PSMB_EXCHANGE *)&pExtSessionSetupExchange,
  575. NULL,
  576. pVNetRoot,
  577. EXTENDED_SESSION_SETUP_EXCHANGE,
  578. &ExtendedSessionSetupExchangeDispatch);
  579. if (Status == STATUS_SUCCESS) {
  580. pExtSessionSetupExchange->SmbCeFlags |= SMBCE_EXCHANGE_TIMED_RECEIVE_OPERATION;
  581. pExtSessionSetupExchange->RxContext = RxContext;
  582. // Avoid duplicate counting during Exchange Initialization.
  583. SmbCeDecrementActiveExchangeCount();
  584. // Set the session echange state to SMBCE_EXCHANGE_SESSION_INITIALIZED
  585. // so that the connection engine does not queue up the request the normal
  586. // way. This will force the connection engine to initiate immediately.
  587. pExtSessionSetupExchange->SmbCeState = SMBCE_EXCHANGE_SESSION_INITIALIZED;
  588. Status = SmbCeInitiateExchange((PSMB_EXCHANGE)pExtSessionSetupExchange);
  589. }
  590. }
  591. if (Status != STATUS_PENDING) {
  592. PSMBCEDB_SERVER_ENTRY pServerEntry;
  593. PSMBCEDB_SESSION_ENTRY pSessionEntry;
  594. SMBCEDB_OBJECT_STATE SessionState;
  595. RxDbgTrace(0,Dbg,("Kerberos Exchange Session Final Status(%lx)\n",Status));
  596. pServerEntry = SmbCeGetExchangeServerEntry(pExtSessionSetupExchange);
  597. pSessionEntry = SmbCeGetExchangeSessionEntry(pExtSessionSetupExchange);
  598. pResumptionContext = pExtSessionSetupExchange->pResumptionContext;
  599. // Tear down the exchange instance ...
  600. SmbCeDiscardExtendedSessionSetupExchange(pExtSessionSetupExchange);
  601. if (pResumptionContext != NULL) {
  602. pResumptionContext->Status = Status;
  603. SmbCeResume(pResumptionContext);
  604. }
  605. }
  606. return STATUS_SUCCESS;
  607. }
  608. SMB_EXCHANGE_DISPATCH_VECTOR
  609. ExtendedSessionSetupExchangeDispatch =
  610. {
  611. SmbExtSecuritySessionSetupExchangeStart,
  612. SmbExtSecuritySessionSetupExchangeReceive,
  613. SmbExtSecuritySessionSetupExchangeCopyDataHandler,
  614. NULL,
  615. SmbExtSecuritySessionSetupExchangeFinalize,
  616. NULL
  617. };
  618.