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.

1142 lines
45 KiB

  1. /* (C) 1997-1999 Microsoft Corp.
  2. *
  3. * file : Decode.c
  4. * author : Erik Mavrinac
  5. *
  6. * description: Decoding logic for MCS PDUs, for passing on to handlers
  7. * in ConPDU.c for connect PDUs and DomPDU.c and other files for domain
  8. * PDUs.
  9. */
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #include <mcsimpl.h>
  13. #include <at128.h>
  14. /*
  15. * Defines
  16. */
  17. // Leading PDU byte for connect PDUs.
  18. #define CONNECT_PDU 0x7F
  19. // Size of the X.224 RFC1006 header.
  20. #define RFC1006HeaderSize 4
  21. // Constant for an incompletely-received input data header.
  22. #define IncompleteHeader 0xFFFFFFFF
  23. // Sizes for fast-path headers.
  24. #define FastPathBaseHeaderSize 2
  25. /*
  26. * Prototypes for external functions for which we have no header.
  27. */
  28. void __stdcall SM_DecodeFastPathInput(void *, BYTE *, unsigned, unsigned,
  29. unsigned, unsigned);
  30. /*
  31. * Prototypes for locally-defined functions
  32. */
  33. BOOLEAN __fastcall RecognizeMCSFrame(PDomain, BYTE *, int, unsigned *);
  34. MCSError __fastcall DeliverShadowData(PDomain, BYTE *, unsigned, ChannelID);
  35. /*
  36. * Logs an error to the system event log and drops the connection.
  37. * ErrDetailCodes are from inc\LogErr.h.
  38. */
  39. // Defined maximum size for caller-provided data to be sent to system event
  40. // log. Max data size is 256, IcaLogError() includes a Unicode string
  41. // "WinStation" which takes up some of the space, as does the unsigned
  42. // subcode used here.
  43. #define MaxEventDataLen (234 - sizeof(unsigned))
  44. void APIENTRY MCSProtocolErrorEvent(
  45. PSDCONTEXT pContext,
  46. PPROTOCOLSTATUS pStat,
  47. unsigned ErrDetailCode,
  48. BYTE *pDetailData,
  49. unsigned DetailDataLen)
  50. {
  51. BYTE SpewBuf[256];
  52. WCHAR *StringParams;
  53. unsigned DataLen;
  54. NTSTATUS Status;
  55. UNICODE_STRING EventLogName;
  56. ICA_CHANNEL_COMMAND Command;
  57. // Increment the error counter.
  58. pStat->Input.Errors++;
  59. // Set the facility name based on the ErrDetailCode. More will need to be
  60. // added here as we get more facilties using this function.
  61. if (ErrDetailCode == Log_Null_Base)
  62. StringParams = L"NULL";
  63. else if (ErrDetailCode >= Log_X224_Base && ErrDetailCode < Log_MCS_Base)
  64. StringParams = L"X.224";
  65. else if (ErrDetailCode >= Log_MCS_Base && ErrDetailCode < Log_RDP_Base)
  66. StringParams = L"MCS";
  67. else if (ErrDetailCode >= Log_RDP_Base && ErrDetailCode < Log_RDP_ENC_Base)
  68. StringParams = L"WD";
  69. else if (ErrDetailCode >= Log_RDP_ENC_Base) // Add new facility here...
  70. StringParams = L"\"DATA ENCRYPTION\"";
  71. // ErrDetailCode is designated as the first unsigned in the extra buffer.
  72. *((unsigned *)SpewBuf) = ErrDetailCode;
  73. // Limit data according to max size.
  74. DataLen = (DetailDataLen < MaxEventDataLen ? DetailDataLen :
  75. MaxEventDataLen);
  76. if (pDetailData != NULL)
  77. memcpy(SpewBuf + sizeof(unsigned), pDetailData, DataLen);
  78. DataLen += sizeof(unsigned);
  79. IcaLogError(pContext, STATUS_RDP_PROTOCOL_ERROR, &StringParams, 1,
  80. SpewBuf, DataLen);
  81. // Signal that we need to drop the link.
  82. Command.Header.Command = ICA_COMMAND_BROKEN_CONNECTION;
  83. Command.BrokenConnection.Reason = Broken_Unexpected;
  84. Command.BrokenConnection.Source = BrokenSource_Server;
  85. Status = IcaChannelInput(pContext, Channel_Command, 0, NULL,
  86. (BYTE *)&Command, sizeof(Command));
  87. if (!NT_SUCCESS(Status))
  88. ErrOut(pContext, "MCSProtocolErrorEvent(): Could not send BROKEN_CONN "
  89. "upward");
  90. }
  91. /*
  92. * Utility function to send an X.224 connection response. Used by
  93. * DecodeWireData() and when a T120_START is sent indicating the
  94. * stack is up.
  95. */
  96. NTSTATUS SendX224Confirm(Domain *pDomain)
  97. {
  98. POUTBUF pOutBuf;
  99. NTSTATUS Status;
  100. pDomain->State = State_X224_Connected;
  101. // This PDU send is vital to the connection and must succeed.
  102. // Keep retrying the allocation until it succeeds.
  103. do {
  104. // Allow the call to wait for a buffer.
  105. Status = IcaBufferAlloc(pDomain->pContext, TRUE, FALSE,
  106. X224_ConnectionConPacketSize, NULL, &pOutBuf);
  107. if (Status != STATUS_SUCCESS) // NT_SUCCESS() does not fail STATUS_TIMEOUT
  108. ErrOut(pDomain->pContext,
  109. "Could not alloc X.224 connect-confirm OutBuf, retrying");
  110. } while (Status != STATUS_SUCCESS);
  111. // Use a bogus source port number for the confirm. This is
  112. // not used by either side.
  113. CreateX224ConnectionConfirmPacket(pOutBuf->pBuffer,
  114. pDomain->X224SourcePort, 0x1234);
  115. pOutBuf->ByteCount = X224_ConnectionConPacketSize;
  116. Status = SendOutBuf(pDomain, pOutBuf);
  117. if (!NT_SUCCESS(Status)) {
  118. ErrOut(pDomain->pContext,
  119. "Unable to send X.224 connection-confirm");
  120. return Status; // Intended receiver receives silence.
  121. }
  122. return STATUS_SUCCESS;
  123. }
  124. /*
  125. * Connect-request-specific bytes:
  126. * Byte Contents
  127. * ---- --------
  128. * 6 MSB of destination (answering) socket/port #,
  129. * should be 0
  130. * 7 LSB of destination socket/port #, should be 0
  131. * 8 MSB of source (calling) socket/port #
  132. * 9 LSB of source socket/port #
  133. * 10 Data class, should be 0x00 for X.224 class 0.
  134. *
  135. * Following are an optional TPDU size (incl. RFC1006 header size
  136. * of 4 bytes but not incl. X.224 3-byte data header)
  137. * negotiation block.
  138. * If this block is not present, an RFC1006 default is assumed
  139. * (65531, minus 3 bytes for the rest of the data packet
  140. * header)
  141. * Only present if LenInd is 2:
  142. * 11 TPDU type (only TPDU_SIZE (0xC0) supported)
  143. * 12 Info length (must be 0x01 for TPDU_SIZE)
  144. * 13 Encoded per X.224 sec 13.3.4(b), as power of 2 in
  145. * range 7..11 for TPDU size
  146. */
  147. NTSTATUS HandleX224ConnectReq(
  148. Domain *pDomain,
  149. BYTE *pBuffer,
  150. unsigned PacketLen)
  151. {
  152. POUTBUF pOutBuf;
  153. NTSTATUS Status;
  154. unsigned LenInd;
  155. if (pDomain->State != State_Unconnected) {
  156. ErrOut(pDomain->pContext,
  157. "X.224 ConnectionRequest received unexpectedly");
  158. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  159. Log_X224_ConnectReceivedAfterConnected,
  160. pBuffer, PacketLen);
  161. return STATUS_RDP_PROTOCOL_ERROR;
  162. }
  163. // Decode the length indicator in byte 4. Should be equal to the
  164. // remaining packet size after the RFC1006 header and LenInd byte.
  165. LenInd = pBuffer[4];
  166. if (LenInd != (PacketLen - RFC1006HeaderSize - 1)) {
  167. ErrOut(pDomain->pContext,
  168. "X.224 Connect LenInd does not match packet length");
  169. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  170. Log_X224_ConnectLenIndNotMatchingPacketLen,
  171. pBuffer, PacketLen);
  172. return STATUS_RDP_PROTOCOL_ERROR;
  173. }
  174. // Check for possible denial-of-service attack or malformed packet.
  175. if (PacketLen < 11 || LenInd < 6) {
  176. ErrOut(pDomain->pContext, "HandleX224ConnectReq(): Header length "
  177. "or LenInd encoded in X.224 header too short");
  178. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  179. Log_X224_ConnectHeaderLenNotRequiredSize,
  180. pBuffer, PacketLen);
  181. return STATUS_RDP_PROTOCOL_ERROR;
  182. }
  183. // Verify that dst port is set per standard.
  184. if (pBuffer[6] != 0x00 || pBuffer[7] != 0x00)
  185. WarnOut(pDomain->pContext, "HandleX224ConnectReq(): Dest port not "
  186. "0x0000");
  187. // Save src port.
  188. pDomain->X224SourcePort = (pBuffer[8] << 8) + pBuffer[9];
  189. // Must be class 0 connection per standard.
  190. if (pBuffer[10] != 0x00) {
  191. ErrOut(pDomain->pContext, "HandleX224ConnectReq(): Data class not "
  192. "0x00 (X.224 class 0)");
  193. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  194. Log_X224_ConnectNotClassZero,
  195. pBuffer, PacketLen);
  196. return STATUS_RDP_PROTOCOL_ERROR;
  197. }
  198. // Set the default RFC1006 data size.
  199. pDomain->MaxX224DataSize = X224_DefaultDataSize;
  200. // Check for optional parameters.
  201. if (LenInd == 6)
  202. goto FinishedDecoding;
  203. // TPDU_SIZE is 3 bytes.
  204. if (PacketLen < 14 || LenInd < 9) {
  205. ErrOut(pDomain->pContext, "HandleX224ConnectReq(): Header length(s) "
  206. "encoded in CR header too short for TPDU_SIZE");
  207. goto FinishedDecoding;
  208. }
  209. //MCS FUTURE: X.224 class 0 defined a couple more codes here;
  210. // should we handle them in the future?
  211. if (pBuffer[11] == TPDU_SIZE) {
  212. if (pBuffer[12] != 0x01) {
  213. ErrOut(pDomain->pContext, "HandleX224ConnectReq(): Illegal data "
  214. "size field in TPDU_SIZE block");
  215. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  216. Log_X224_ConnectTPDU_SIZELengthFieldIllegalValue,
  217. pBuffer, PacketLen);
  218. return STATUS_RDP_PROTOCOL_ERROR;
  219. }
  220. // Must conform to X.224 class 0 constraints of 7..11.
  221. if (pBuffer[13] < 7 || pBuffer[13] > 11) {
  222. ErrOut(pDomain->pContext, "HandleX224ConnectReq(): Illegal data "
  223. "size field in TPDU size block");
  224. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  225. Log_X224_ConnectTPDU_SIZENotLegalRange,
  226. pBuffer, PacketLen);
  227. return STATUS_RDP_PROTOCOL_ERROR;
  228. }
  229. // Size is power of 2 -- 128..2048, minus 3 bytes for X.224
  230. // Data TPDU header size.
  231. pDomain->MaxX224DataSize = (1 << pBuffer[13]) - 3;
  232. if (PacketLen > 14)
  233. WarnOut(pDomain->pContext, "HandleX224ConnectReq(): Frame size "
  234. "greater than TPDU data bytes (incl. TPDU-SIZE) for "
  235. "connection-request");
  236. }
  237. if (LenInd > 9)
  238. WarnOut(pDomain->pContext, "X224Recognize(): Extra optional "
  239. "fields present in TPDU, we are not handling!");
  240. FinishedDecoding:
  241. // If the virtual channels have already been bound, and the
  242. // stack has been given permission to send, send the
  243. // X.224 response to start the client data flow.
  244. if (pDomain->bChannelBound && pDomain->bCanSendData) {
  245. TraceOut(pDomain->pContext,
  246. "DecodeWireData(): Sending X.224 response");
  247. Status = SendX224Confirm(pDomain);
  248. // Ignore errors. Should only occur if the stack is
  249. // going down.
  250. }
  251. else {
  252. // Set up for later with indication that X.224 is waiting.
  253. pDomain->State = State_X224_Requesting;
  254. }
  255. return STATUS_SUCCESS;
  256. }
  257. /*
  258. * Disconnect-request-specific bytes:
  259. * Byte Contents
  260. * ---- --------
  261. * 6 MSB of destination socket/port #
  262. * 7 LSB of destination socket/port #
  263. * 8 MSB of source (sending) socket/port #
  264. * 9 LSB of source socket/port #
  265. * 10 Reason code:
  266. * 0 : not specified
  267. * 1 : congestion at sending machine
  268. * 2 : no session manager for data at sender
  269. * 3 : address unknown
  270. *
  271. * NOTE: We do not use any of these fields.
  272. */
  273. NTSTATUS HandleX224Disconnect(
  274. Domain *pDomain,
  275. BYTE *pBuffer,
  276. unsigned PacketLen)
  277. {
  278. unsigned LenInd;
  279. if (pDomain->State == State_Unconnected) {
  280. ErrOut(pDomain->pContext, "HandleX224Disconnect(): Disconnect "
  281. "received when not connected");
  282. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  283. Log_X224_DisconnectWithoutConnection,
  284. pBuffer, PacketLen);
  285. return STATUS_RDP_PROTOCOL_ERROR;
  286. }
  287. if (pDomain->State == State_MCS_Connected) {
  288. // Not a serious error since we just dropped X.224 below MCS
  289. // without first dropping MCS.
  290. WarnOut(pDomain->pContext, "X.224 Disconnect received, "
  291. "MCS was in connected state");
  292. SignalBrokenConnection(pDomain);
  293. }
  294. pDomain->State = State_Disconnected;
  295. pDomain->bEndConnectionPacketReceived = TRUE;
  296. // Decode the length indicator in byte 4. Should be equal to the
  297. // remaining packet size after the RFC1006 header and LenInd byte.
  298. LenInd = pBuffer[4];
  299. if (LenInd != (PacketLen - RFC1006HeaderSize - 1)) {
  300. ErrOut(pDomain->pContext,
  301. "X.224 Disconnect LenInd does not match packet length");
  302. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  303. Log_X224_DisconnectLenIndNotMatchingPacketLen,
  304. pBuffer, PacketLen);
  305. return STATUS_RDP_PROTOCOL_ERROR;
  306. }
  307. // Possible denial-of-service attack or malformed packet.
  308. if (PacketLen != 11 || LenInd != 6) {
  309. ErrOut(pDomain->pContext, "HandleX224Disconnect(): Overall header "
  310. "length or LenInd encoded in X.224 Disconnect wrong size");
  311. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  312. Log_X224_DisconnectHeaderLenNotRequiredSize,
  313. pBuffer, PacketLen);
  314. return STATUS_RDP_PROTOCOL_ERROR;
  315. }
  316. return STATUS_SUCCESS;
  317. }
  318. /*
  319. * Main entry point for data arriving from transport via IcaRawInput() path.
  320. * Decode data passed up from the transport. pBuffer is assumed not to be
  321. * usable beyond the return from this function, so that data copying is
  322. * done as necessary. It is possible for incomplete frames to be passed
  323. * in, so a packet reassembly buffer is maintained.
  324. * This function is called directly by ICADD with a pointer to the WD data
  325. * structure. By convention, we assume that the DomainHandle is first in
  326. * that struct so we can simply do a double-indirection to get to our data.
  327. * Assumes the presence of X.224 framing headers at the start of all
  328. * data.
  329. *
  330. * General X.224 header is laid out as follows, with specific TPDU bytes
  331. * following:
  332. * Byte Contents
  333. * ---- --------
  334. * 0 RFC1006 version number, must be 0x03.
  335. * 1 RFC1006 Reserved, must be 0x00.
  336. * 2 RFC1006 MSB of word-sized total-frame length (incl. whole X.224
  337. * header).
  338. * 3 RFC1006 LSB of word-sized total-frame length.
  339. * 4 Length Indicator, the size of the header bytes following.
  340. * 5 Packet type indicator. Only 4 most sig. bits are type code, but
  341. * X.224 class 0 specifies lower 4 bits to be 0 anyway.
  342. */
  343. NTSTATUS MCSIcaRawInput(
  344. void *pTSWd,
  345. PINBUF pInBuf,
  346. BYTE *pBuf,
  347. ULONG BytesLeft)
  348. {
  349. BYTE *pBuffer;
  350. Domain *pDomain;
  351. BOOLEAN bUsingReassemblyBuf, bMCSRecognizedFrame;
  352. unsigned NBytesConsumed_MCS, Diff, X224TPDUType, PacketLength;
  353. // We assume we will not use InBufs.
  354. ASSERT(pInBuf == NULL);
  355. ASSERT(pBuf != NULL);
  356. ASSERT(BytesLeft != 0);
  357. // We actually receive a pointer to WD instance data. The first element in
  358. // that data is a DomainHandle, i.e. a pointer to a Domain.
  359. pDomain = *((Domain **)pTSWd);
  360. // Increment protocol counters.
  361. pDomain->pStat->Input.WdBytes += BytesLeft;
  362. pDomain->pStat->Input.WdFrames++;
  363. #ifdef DUMP_RAW_INPUT
  364. DbgPrint("Received raw input, len=%d\n", BytesLeft);
  365. if (pDomain->Ptrs[0] == NULL)
  366. pDomain->Ptrs[0] = pDomain->FooBuf;
  367. memcpy(pDomain->Ptrs[pDomain->NumPtrs], pBuf, BytesLeft);
  368. pDomain->NumPtrs++;
  369. pDomain->Ptrs[pDomain->NumPtrs] = (BYTE *)pDomain->Ptrs[pDomain->NumPtrs - 1] +
  370. BytesLeft;
  371. #endif
  372. /*
  373. * Check for previous data in reassembly buffer. Prepare whole X.224
  374. * packet for decode loop.
  375. */
  376. if (pDomain->StackClass != Stack_Shadow) {
  377. if (pDomain->StoredDataLength == 0) {
  378. // We'll handle setup of this case just inside the decode loop,
  379. // triggered by this value being FALSE.
  380. bUsingReassemblyBuf = FALSE;
  381. }
  382. else {
  383. ASSERT(pDomain->pReassembleData != NULL);
  384. if (pDomain->PacketDataLength == IncompleteHeader) {
  385. ASSERT(pDomain->pReassembleData == pDomain->PacketBuf);
  386. // We did not have enough of a header last time to
  387. // determine the packet size. Try to reassemble enough of one
  388. // to get the size. We only need the first 4 bytes to get
  389. // the size from the X.224 RFC1006 header, or 2-3 bytes
  390. // for the fastpath header. We know the packet type based
  391. // on the first byte, and must have received at least
  392. // one byte in the last round.
  393. if ((BytesLeft + pDomain->StoredDataLength) <
  394. pDomain->PacketHeaderLength) {
  395. // Copy what little we got and return -- we still don't
  396. // have a header.
  397. memcpy(pDomain->pReassembleData +
  398. pDomain->StoredDataLength, pBuf, BytesLeft);
  399. pDomain->StoredDataLength += BytesLeft;
  400. return STATUS_SUCCESS;
  401. }
  402. if (pDomain->PacketHeaderLength < pDomain->StoredDataLength) {
  403. pBuffer = pDomain->pReassembleData;
  404. goto X224BadPktType;
  405. }
  406. memcpy(pDomain->pReassembleData +
  407. pDomain->StoredDataLength, pBuf,
  408. pDomain->PacketHeaderLength -
  409. pDomain->StoredDataLength);
  410. BytesLeft -= (pDomain->PacketHeaderLength -
  411. pDomain->StoredDataLength);
  412. pBuf += (pDomain->PacketHeaderLength -
  413. pDomain->StoredDataLength);
  414. pDomain->StoredDataLength = pDomain->PacketHeaderLength;
  415. // Get the size.
  416. if (pDomain->bCurrentPacketFastPath) {
  417. // Total packet length is in the second and, possibly,
  418. // third bytes.of the packet. Format is similar to
  419. // ASN.1 PER - high bit of first byte set means length is
  420. // contained in the low 7 bits of current byte as the
  421. // most significant bits, plus the 8 bits of the
  422. // next byte for a total size of 15 bits. Otherwise,
  423. // the packet size is contained within the low 7 bits
  424. // of the second byte only.
  425. if (!(pDomain->pReassembleData[1] & 0x80)) {
  426. pDomain->PacketDataLength =
  427. pDomain->pReassembleData[1];
  428. }
  429. else {
  430. // We need a third byte. We don't assemble it the
  431. // first time around to keep from corrupting the
  432. // stream if we received a 1-byte size with no
  433. // contents. Most often we will be receiving
  434. // a 1-byte size anyway, so this code is little
  435. // executed.
  436. pDomain->PacketHeaderLength = 3;
  437. if (BytesLeft) {
  438. pDomain->pReassembleData[2] = *pBuf;
  439. pDomain->PacketDataLength =
  440. (pDomain->pReassembleData[1] & 0x7F) << 8 |
  441. *pBuf;
  442. BytesLeft--;
  443. pBuf++;
  444. }
  445. else {
  446. // No data left, try again later.
  447. // IncompleteHeader is already in PacketDataLength.
  448. return STATUS_SUCCESS;
  449. }
  450. }
  451. }
  452. else {
  453. // X.224 packet, length is in third and fourth bytes.
  454. pDomain->PacketDataLength =
  455. (pDomain->pReassembleData[2] << 8) +
  456. pDomain->pReassembleData[3];
  457. }
  458. // Dynamically allocate a buffer if size is too big.
  459. if (pDomain->PacketDataLength > pDomain->ReceiveBufSize) {
  460. TraceOut1(pDomain->pContext, "MCSIcaRawInput(): "
  461. "Allocating large [%ld] X.224 reassembly buf (path1)!",
  462. pDomain->PacketDataLength);
  463. pDomain->pReassembleData = ExAllocatePoolWithTag(PagedPool,
  464. pDomain->PacketDataLength + INPUT_BUFFER_BIAS, MCS_POOL_TAG);
  465. if (pDomain->pReassembleData != NULL) {
  466. // Copy the assembled header.
  467. memcpy(pDomain->pReassembleData,
  468. pDomain->PacketBuf,
  469. pDomain->PacketHeaderLength);
  470. }
  471. else {
  472. // We are trying to parse the beginning of a net frame
  473. // and have run out of memory. Set to read from the
  474. // RFC1006 header if we are called again.
  475. ErrOut(pDomain->pContext, "MCSIcaRawInput(): "
  476. "Failed to alloc large X.224 reassembly buf");
  477. pDomain->pReassembleData = pDomain->PacketBuf;
  478. return STATUS_NO_MEMORY;
  479. }
  480. }
  481. }
  482. if ((pDomain->StoredDataLength + BytesLeft) <
  483. pDomain->PacketDataLength) {
  484. // We still don't have enough data. Copy what we have
  485. // and return.
  486. memcpy(pDomain->pReassembleData +
  487. pDomain->StoredDataLength, pBuf, BytesLeft);
  488. pDomain->StoredDataLength += BytesLeft;
  489. return STATUS_SUCCESS;
  490. }
  491. // We have at least enough data for this packet. Only copy
  492. // up to the end of this particular packet. We'll handle
  493. // any later data below.
  494. if (pDomain->StoredDataLength > pDomain->PacketDataLength) {
  495. // We received a bad packet. Get out of here.
  496. pBuffer = pDomain->pReassembleData;
  497. goto X224BadPktType;
  498. }
  499. Diff = pDomain->PacketDataLength - pDomain->StoredDataLength;
  500. memcpy(pDomain->pReassembleData +
  501. pDomain->StoredDataLength, pBuf, Diff);
  502. pBuf += Diff;
  503. BytesLeft -= Diff;
  504. pDomain->StoredDataLength = pDomain->PacketDataLength;
  505. // Set decode data.
  506. pBuffer = pDomain->pReassembleData;
  507. PacketLength = pDomain->PacketDataLength;
  508. // This will prevent us from doing the default input-buffer setup
  509. // below.
  510. bUsingReassemblyBuf = TRUE;
  511. }
  512. /*
  513. * Main decode loop.
  514. * Loops as long as there are complete X.224 packets to decode.
  515. */
  516. for (;;) {
  517. /*
  518. * Handle the general case of data being used directly from the
  519. * inbound data buffer.
  520. */
  521. if (!bUsingReassemblyBuf) {
  522. // We must have at least one byte. Determine the packet type.
  523. if ((pBuf[0] & TS_INPUT_FASTPATH_ACTION_MASK) ==
  524. TS_INPUT_FASTPATH_ACTION_FASTPATH) {
  525. // Fast-path packet (low 2 bits = 00). Set up the minimum
  526. // header length.
  527. pDomain->PacketHeaderLength = 2;
  528. pDomain->bCurrentPacketFastPath = TRUE;
  529. }
  530. else if ((pBuf[0] & TS_INPUT_FASTPATH_ACTION_MASK) ==
  531. TS_INPUT_FASTPATH_ACTION_X224) {
  532. // X.224. Use 4-byte fixed header length.
  533. pDomain->PacketHeaderLength = RFC1006HeaderSize;
  534. pDomain->bCurrentPacketFastPath = FALSE;
  535. }
  536. else {
  537. // Bad low bits of first byte.
  538. pBuffer = pBuf;
  539. goto X224BadPktType;
  540. }
  541. // Check we have enough for the minimum header.
  542. if (BytesLeft >= pDomain->PacketHeaderLength) {
  543. // Get the size.
  544. if (pDomain->bCurrentPacketFastPath) {
  545. // Total packet length is in the second and, possibly,
  546. // third bytes.of the packet. Format is similar to
  547. // ASN.1 PER - high bit of first byte set means length is
  548. // contained in the low 7 bits of current byte as the
  549. // most significant bits, plus the 8 bits of the
  550. // next byte for a total size of 15 bits. Otherwise,
  551. // the packet size is contained within the low 7 bits
  552. // of the second byte only.
  553. if (!(pBuf[1] & 0x80)) {
  554. PacketLength = pBuf[1];
  555. }
  556. else {
  557. // We need a third byte. We don't assemble it the
  558. // first time around to keep from corrupting the
  559. // stream if we received a 1-byte size with no
  560. // contents. Most often we will be receiving
  561. // a 1-byte size anyway, so this code is little
  562. // executed.
  563. pDomain->PacketHeaderLength = 3;
  564. if (BytesLeft >= 3) {
  565. PacketLength = (pBuf[1] & 0x7F) << 8 | pBuf[2];
  566. }
  567. else {
  568. // We don't have enough for the minimum size
  569. // header, store the little bit we do have.
  570. pDomain->pReassembleData = pDomain->PacketBuf;
  571. pDomain->StoredDataLength = BytesLeft;
  572. pDomain->PacketDataLength = IncompleteHeader;
  573. pDomain->pReassembleData[0] = *pBuf;
  574. pDomain->pReassembleData[1] = pBuf[1];
  575. break;
  576. }
  577. }
  578. }
  579. else {
  580. // Get the X.224 size from the third and fourth bytes.
  581. PacketLength = (pBuf[2] << 8) + pBuf[3];
  582. }
  583. }
  584. else {
  585. // We don't have enough for the minimum size header, store
  586. // the little bit we do have.
  587. pDomain->pReassembleData = pDomain->PacketBuf;
  588. pDomain->StoredDataLength = BytesLeft;
  589. pDomain->PacketDataLength = IncompleteHeader;
  590. memcpy(pDomain->pReassembleData, pBuf, BytesLeft);
  591. break;
  592. }
  593. // Make sure we have a whole packet.
  594. if (PacketLength <= BytesLeft) {
  595. // Set decode data.
  596. pBuffer = (BYTE *)pBuf;
  597. // Skip the bytes we're about to consume.
  598. pBuf += PacketLength;
  599. BytesLeft -= PacketLength;
  600. }
  601. else {
  602. // We don't have a whole packet, store what we do have
  603. // and return.
  604. pDomain->PacketDataLength = PacketLength;
  605. pDomain->StoredDataLength = BytesLeft;
  606. if (PacketLength <= pDomain->ReceiveBufSize) {
  607. pDomain->pReassembleData = pDomain->PacketBuf;
  608. }
  609. else {
  610. // Size is too big for the standard buffer, alloc one.
  611. TraceOut1(pDomain->pContext, "MCSIcaRawInput(): "
  612. "Allocating large [%ld] X.224 reassembly buf (path2)!",
  613. pDomain->PacketDataLength);
  614. pDomain->pReassembleData = ExAllocatePoolWithTag(
  615. PagedPool, pDomain->PacketDataLength + INPUT_BUFFER_BIAS,
  616. MCS_POOL_TAG);
  617. if (pDomain->pReassembleData == NULL) {
  618. // We failed to allocate, and we're in the middle of
  619. // an X.224 frame. Store no bytes, and return an
  620. // error to the transport.
  621. ErrOut(pDomain->pContext, "MCSIcaRawInput(): "
  622. "Failed to alloc large X.224 reassembly buf");
  623. pDomain->PacketDataLength = 0;
  624. return STATUS_NO_MEMORY;
  625. }
  626. }
  627. memcpy(pDomain->pReassembleData, pBuf, BytesLeft);
  628. break;
  629. }
  630. }
  631. /*
  632. * Time to decode. Different handling for fast-path vs. X.224.
  633. */
  634. if (pDomain->bCurrentPacketFastPath) {
  635. // Verify that the sent size covers at least the header.
  636. if (PacketLength > pDomain->PacketHeaderLength) {
  637. // Let SM decrypt if need be, and pass to IM.
  638. SM_DecodeFastPathInput(pDomain->pSMData,
  639. pBuffer + pDomain->PacketHeaderLength,
  640. PacketLength - pDomain->PacketHeaderLength,
  641. pBuffer[0] & TS_INPUT_FASTPATH_ENCRYPTED,
  642. (pBuffer[0] & TS_INPUT_FASTPATH_NUMEVENTS_MASK) >> 2,
  643. pBuffer[0] & TS_INPUT_FASTPATH_SECURE_CHECKSUM);
  644. goto PostDecode;
  645. }
  646. else {
  647. goto X224BadPktType;
  648. }
  649. }
  650. // X.224.
  651. //
  652. // Verify all TPKT data up through the TPDU type code. This code
  653. // is performance path, so segregate the error handling code outside
  654. // the main paths.
  655. if (pBuffer[0] == 0x03 && pBuffer[1] == 0x00 &&
  656. PacketLength > RFC1006HeaderSize) {
  657. // Decode the X.224 PDU type contained in the 6th byte.
  658. X224TPDUType = pBuffer[5];
  659. // Most oft-used case is data.
  660. // Further bytes in data:
  661. // Byte Contents
  662. // ---- --------
  663. // 6 EOT flag -- 0x80 if end of sequence, 0x00 if not
  664. // 7+ Start of user data bytes
  665. if (X224TPDUType == X224_Data) {
  666. if (pDomain->State != State_Unconnected &&
  667. pDomain->State != State_Disconnected &&
  668. PacketLength > X224_DataHeaderSize &&
  669. pBuffer[4] == 0x02 &&
  670. pBuffer[6] == X224_EOT) {
  671. bMCSRecognizedFrame = RecognizeMCSFrame(pDomain,
  672. pBuffer + X224_DataHeaderSize,
  673. PacketLength - X224_DataHeaderSize,
  674. &NBytesConsumed_MCS);
  675. if (bMCSRecognizedFrame &&
  676. (NBytesConsumed_MCS >=
  677. (PacketLength - X224_DataHeaderSize))) {
  678. // TraceOut2(pDomain->pContext, "MCS accepted %d "
  679. // "bytes (Domain %X)", NBytesConsumed_MCS,
  680. // pDomain);
  681. }
  682. else {
  683. goto MCSRecognizeErr;
  684. }
  685. }
  686. else {
  687. goto DataPktProtocolErr;
  688. }
  689. }
  690. else {
  691. // Control-type PDUs, not a perf path.
  692. switch (X224TPDUType) {
  693. case X224_ConnectionReq:
  694. // Noncritical path, throw to another function to handle.
  695. if (HandleX224ConnectReq(pDomain, pBuffer,
  696. PacketLength) != STATUS_SUCCESS)
  697. goto ReturnErr;
  698. break;
  699. case X224_Disconnect:
  700. // Noncritical path, throw to another function to handle.
  701. if (HandleX224Disconnect(pDomain, pBuffer,
  702. PacketLength) != STATUS_SUCCESS)
  703. goto ReturnErr;
  704. break;
  705. default:
  706. ErrOut1(pDomain->pContext,
  707. "Unsupported X.224 TPDU type %d received",
  708. X224TPDUType);
  709. goto X224BadPktType;
  710. }
  711. }
  712. }
  713. else {
  714. goto RFC1006ProtocolErr;
  715. }
  716. PostDecode:
  717. // Free dynamic reassembly buf if allocated.
  718. if (bUsingReassemblyBuf &&
  719. pDomain->pReassembleData != pDomain->PacketBuf &&
  720. NULL != pDomain->pReassembleData) {
  721. ExFreePool(pDomain->pReassembleData);
  722. pDomain->pReassembleData = NULL;
  723. }
  724. // Force next loop iteration to use the PDU input buffer.
  725. bUsingReassemblyBuf = FALSE;
  726. pDomain->StoredDataLength = 0;
  727. // If we consumed exactly what came in on the wire, we're done.
  728. if (BytesLeft == 0) {
  729. pDomain->StoredDataLength = 0;
  730. break;
  731. }
  732. }
  733. }
  734. // This is shadow stack, so deliver the data the the requested channel
  735. else {
  736. MCSError MCSErr;
  737. MCSErr = DeliverShadowData(pDomain, pBuf, BytesLeft,
  738. pDomain->shadowChannel);
  739. if (MCSErr == MCS_NO_ERROR)
  740. return STATUS_SUCCESS;
  741. else
  742. return STATUS_RDP_PROTOCOL_ERROR;
  743. }
  744. return STATUS_SUCCESS;
  745. /*
  746. * Protocol error handling code, segregated for performance.
  747. */
  748. X224BadPktType:
  749. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  750. Log_X224_UnknownPacketType,
  751. pBuffer, 7);
  752. goto ReturnErr;
  753. MCSRecognizeErr:
  754. if (!bMCSRecognizedFrame) {
  755. //pTSWd->hDomainKernel might be cleaned by WD_Close
  756. if (*((Domain **)pTSWd))
  757. {
  758. ErrOut(pDomain->pContext, "MCSIcaRawInput(): X.224 data "
  759. "packet contains an incomplete MCS PDU!");
  760. if (pDomain->bCanSendData) {
  761. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  762. Log_X224_DataIncompleteMCSPacketNotSupported,
  763. pBuffer, PacketLength);
  764. }
  765. }
  766. else
  767. goto MCSQuit;
  768. }
  769. if (NBytesConsumed_MCS <
  770. (PacketLength - X224_DataHeaderSize)) {
  771. ErrOut1(pDomain->pContext, "MCS did not consume %d bytes "
  772. "in X.224 data TPKT", (PacketLength -
  773. X224_DataHeaderSize - NBytesConsumed_MCS));
  774. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  775. Log_X224_DataMultipleMCSPDUsNotSupported,
  776. pBuffer, PacketLength);
  777. goto ReturnErr;
  778. // MCS FUTURE: Implement parsing more than 1 MCS PDU per
  779. // X.224 TPKT.
  780. }
  781. DataPktProtocolErr:
  782. if (*((Domain **)pTSWd) == NULL) {
  783. goto MCSQuit;
  784. }
  785. if (pDomain->State == State_Unconnected) {
  786. ErrOut(pDomain->pContext, "X.224 Data received before X.224 "
  787. "Connect.");
  788. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  789. Log_X224_ReceivedDataBeforeConnected,
  790. pBuffer, PacketLength);
  791. goto ReturnErr;
  792. }
  793. if (pDomain->State == State_Disconnected) {
  794. if (!pDomain->bEndConnectionPacketReceived) {
  795. TraceOut(pDomain->pContext,
  796. "X.224 Data received after X.224 Disconnect or "
  797. "DPum");
  798. goto ReturnErr;
  799. }
  800. else {
  801. TraceOut(pDomain->pContext, "X.224 Data received after "
  802. "local disconnect, ignoring");
  803. goto ReturnErr;
  804. }
  805. }
  806. // Possible denial-of-service attack, malformed or null packet.
  807. if (PacketLength <= X224_DataHeaderSize) {
  808. ErrOut(pDomain->pContext, "X224Recognize(): Data header len "
  809. "wrong or null packet");
  810. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  811. Log_X224_PacketLengthLessThanHeader,
  812. pBuffer, 4);
  813. goto ReturnErr;
  814. }
  815. // TPDU length indicator should be 2 bytes.
  816. if (pBuffer[4] != 0x02) {
  817. ErrOut(pDomain->pContext, "MCSIcaRawInput(): X.224 data "
  818. "packet contains length indicator not set to 2");
  819. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  820. Log_X224_DataLenIndNotRequiredSize,
  821. pBuffer, 5);
  822. goto ReturnErr;
  823. }
  824. // We don't handle fragmented X.224 packets.
  825. if (pBuffer[6] != X224_EOT) {
  826. ErrOut(pDomain->pContext, "MCSIcaRawInput(): X.224 data "
  827. "packet does not have EOT bit set, not supported");
  828. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  829. Log_X224_DataFalseEOTNotSupported,
  830. pBuffer, 7);
  831. goto ReturnErr;
  832. }
  833. RFC1006ProtocolErr:
  834. if (pBuffer[0] != 0x03 || pBuffer[1] != 0x00) {
  835. ErrOut1(pDomain->pContext, "X.224 RFC1006 version not correct, "
  836. "skipping %d bytes", PacketLength);
  837. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  838. Log_X224_RFC1006HeaderVersionNotCorrect,
  839. pBuffer, 2);
  840. goto ReturnErr;
  841. }
  842. // Null TPKTs.
  843. if (PacketLength <= RFC1006HeaderSize) {
  844. ErrOut(pDomain->pContext, "X224Recognize(): Header len "
  845. "given is <= 4 (RFC header only)");
  846. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  847. Log_X224_PacketLengthLessThanHeader,
  848. pBuffer, RFC1006HeaderSize);
  849. goto ReturnErr;
  850. }
  851. ReturnErr:
  852. // Void any held packet data. The stream is considered corrupted now.
  853. pDomain->StoredDataLength = 0;
  854. MCSQuit:
  855. return STATUS_RDP_PROTOCOL_ERROR;
  856. }
  857. /*
  858. * Decodes MCS data. Assumes that X.224 headers have already been interpreted
  859. * such that pBuffer points to the start of the MCS data. Returns FALSE if
  860. * the frame data was too short.
  861. */
  862. BOOLEAN __fastcall RecognizeMCSFrame(
  863. PDomain pDomain,
  864. BYTE *pBuffer,
  865. int BytesLeft,
  866. unsigned *pNBytesConsumed)
  867. {
  868. int Result, PDUType;
  869. unsigned NBytesConsumed;
  870. *pNBytesConsumed = 0;
  871. if (BytesLeft >= 1) {
  872. if (*pBuffer != CONNECT_PDU) {
  873. // Domain PDUs include Data PDUs and are a perf path.
  874. // This must be a domain PDU. Domain PDU enumeration code is
  875. // stored in the high 6 bits of the first byte.
  876. PDUType = *pBuffer >> 2;
  877. // Special-case the almost-always data case.
  878. if (PDUType == MCS_SEND_DATA_REQUEST_ENUM) {
  879. return HandleAllSendDataPDUs(pDomain, pBuffer, BytesLeft,
  880. pNBytesConsumed);
  881. }
  882. else if (PDUType <= MaxDomainPDU) {
  883. // Domain PDUs are in the range 0..42, so simply index
  884. // into table and call handler. Note that we cannot skip
  885. // any bytes when passing to handler, since the last 2
  886. // bits of the initial byte can be used as information
  887. // by ASN.1 PER encoding.
  888. if (DomainPDUTable[PDUType].HandlePDUFunc != NULL)
  889. return DomainPDUTable[PDUType].HandlePDUFunc(pDomain,
  890. pBuffer, BytesLeft, pNBytesConsumed);
  891. else
  892. goto DomainPDURangeErr;
  893. }
  894. else {
  895. goto DomainPDURangeErr;
  896. }
  897. }
  898. else {
  899. // Not a performance path, PDUs on this path are control PDUs
  900. // used at the beginning of a connection sequence.
  901. // The first byte on a connect PDU is 0x7F, so that the actual
  902. // PDU code is in the second byte.
  903. if (BytesLeft < 2)
  904. return FALSE;
  905. PDUType = pBuffer[1];
  906. if (PDUType >= MinConnectPDU && PDUType <= MaxConnectPDU) {
  907. // Connect PDUs are in the range 101..104, so normalize to zero
  908. // and call from table. Note that we can skip 1st byte because
  909. // it has been completely claimed. 2nd byte is needed to unpack
  910. // the PDU size.
  911. PDUType = pBuffer[1] - MinConnectPDU;
  912. if (ConnectPDUTable[PDUType].HandlePDUFunc != NULL) {
  913. if (ConnectPDUTable[PDUType].HandlePDUFunc(pDomain,
  914. pBuffer + 1, BytesLeft - 1, pNBytesConsumed)) {
  915. (*pNBytesConsumed)++; // Add in the CONNECT_PDU byte.
  916. return TRUE;
  917. }
  918. else {
  919. return FALSE;
  920. }
  921. }
  922. else {
  923. goto ConnectPDURangeErr;
  924. }
  925. }
  926. else {
  927. goto ConnectPDURangeErr;
  928. }
  929. }
  930. return TRUE;
  931. }
  932. else {
  933. return FALSE;
  934. }
  935. /*
  936. * Protocol error handling code.
  937. */
  938. DomainPDURangeErr:
  939. if (PDUType > MaxDomainPDU) {
  940. ErrOut1(pDomain->pContext, "RecognizeMCSFrame(): Received bad "
  941. "domain PDU number %d", PDUType);
  942. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  943. Log_MCS_BadDomainPDUType,
  944. pBuffer, BytesLeft);
  945. goto ReturnErr;
  946. }
  947. ConnectPDURangeErr:
  948. if (PDUType < MinConnectPDU || PDUType > MaxConnectPDU) {
  949. ErrOut1(pDomain->pContext, "RecognizeMCSFrame(): Received bad "
  950. "connect PDU number %d", PDUType);
  951. MCSProtocolErrorEvent(pDomain->pContext, pDomain->pStat,
  952. Log_MCS_BadConnectPDUType,
  953. pBuffer, BytesLeft);
  954. goto ReturnErr;
  955. }
  956. ReturnErr:
  957. // Skip everything we received.
  958. *pNBytesConsumed = BytesLeft;
  959. return TRUE;
  960. }
  961. /*
  962. * Called by MCSICARawInput during shadow sessions to deliver shadow data to
  963. * any registered user attachements.
  964. */
  965. MCSError __fastcall DeliverShadowData(
  966. PDomain pDomain,
  967. BYTE *Frame,
  968. unsigned DataLength,
  969. ChannelID shadowChannel)
  970. {
  971. MCSChannel *pMCSChannel;
  972. unsigned CurUserID;
  973. UserAttachment *pUA;
  974. TraceOut(pDomain->pContext, "MCSDeliverShadowData(): entry");
  975. // Find channel in channel list.
  976. if (!SListGetByKey(&pDomain->ChannelList, shadowChannel, &pMCSChannel)) {
  977. // Ignore sends on missing channels. This means that no one
  978. // has joined the channel. Give a warning only.
  979. WarnOut1(pDomain->pContext, "Shadow ChannelID %d PDU does not exist",
  980. shadowChannel);
  981. return MCS_NO_SUCH_CHANNEL;
  982. }
  983. // Send indication to all local attachments.
  984. SListResetIteration(&pMCSChannel->UserList);
  985. while (SListIterate(&pMCSChannel->UserList, (UINT_PTR *)&CurUserID, &pUA))
  986. if (pUA->bLocal)
  987. (pUA->SDCallback)(
  988. Frame, // pData
  989. DataLength,
  990. pUA->UserDefined, // UserDefined
  991. pUA, // hUser
  992. FALSE, // bUniform
  993. pMCSChannel, // hChannel
  994. MCS_TOP_PRIORITY,
  995. 1004, // SenderID
  996. SEGMENTATION_BEGIN | SEGMENTATION_END); // Segmentation
  997. return MCS_NO_ERROR;
  998. }