/** * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport. * * If possible a complete PDU is read, in case of non blocking transport this might not succeed. * Except in case of an error the passed stream will point to the last byte read (correct * position). When the pdu read is completed the stream is sealed and the pointer set to 0 * * @param[in] transport rdpTransport * @param[in] s wStream * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of * bytes of the *complete* pdu read */ int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; int position; int pduLength; BYTE* header; position = 0; pduLength = 0; if (!transport) return -1; if (!s) return -1; position = Stream_GetPosition(s); /* Make sure there is enough space for the longest header within the stream */ if (!Stream_EnsureCapacity(s, 4)) return -1; /* Make sure at least two bytes are read for further processing */ if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1) { /* No data available at the moment */ return status; } /* update position value for further checks */ position = Stream_GetPosition(s); header = Stream_Buffer(s); if (transport->NlaMode) { /* * In case NlaMode is set TSRequest package(s) are expected * 0x30 = DER encoded data with these bits set: * bit 6 P/C constructed * bit 5 tag number - sequence */ if (header[0] == 0x30) { /* TSRequest (NLA) */ if (header[1] & 0x80) { if ((header[1] & ~(0x80)) == 1) { /* check for header bytes already was readed in previous calls */ if (position < 3 && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1) return status; pduLength = header[2]; pduLength += 3; } else if ((header[1] & ~(0x80)) == 2) { /* check for header bytes already was readed in previous calls */ if (position < 4 && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1) return status; pduLength = (header[2] << 8) | header[3]; pduLength += 4; } else { WLog_ERR(TAG, "Error reading TSRequest!"); return -1; } } else { pduLength = header[1]; pduLength += 2; } } } else { if (header[0] == 0x03) { /* TPKT header */ /* check for header bytes already was readed in previous calls */ if (position < 4 && (status = transport_read_layer_bytes(transport, s, 4 - position)) != 1) return status; pduLength = (header[2] << 8) | header[3]; /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */ if (pduLength < 7 || pduLength > 0xFFFF) { WLog_ERR(TAG, "tpkt - invalid pduLength: %d", pduLength); return -1; } } else { /* Fast-Path Header */ if (header[1] & 0x80) { /* check for header bytes already was readed in previous calls */ if (position < 3 && (status = transport_read_layer_bytes(transport, s, 3 - position)) != 1) return status; pduLength = ((header[1] & 0x7F) << 8) | header[2]; } else pduLength = header[1]; /* * fast-path has 7 bits for length so the maximum size, including headers is 0x8000 * The theoretical minimum fast-path PDU consists only of two header bytes plus one * byte for data (e.g. fast-path input synchronize pdu) */ if (pduLength < 3 || pduLength > 0x8000) { WLog_ERR(TAG, "fast path - invalid pduLength: %d", pduLength); return -1; } } } if (!Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength)) return -1; status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; if (Stream_GetPosition(s) >= pduLength) WLog_Packet(WLog_Get(TAG), WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND); Stream_SealLength(s); Stream_SetPosition(s, 0); return Stream_Length(s); }
/** * @brief Try to read a complete PDU (NLA, fast-path or tpkt) from the underlying transport. * * If possible a complete PDU is read, in case of non blocking transport this might not succeed. * Except in case of an error the passed stream will point to the last byte read (correct * position). When the pdu read is completed the stream is sealed and the pointer set to 0 * * @param[in] transport rdpTransport * @param[in] s wStream * @return < 0 on error; 0 if not enough data is available (non blocking mode); > 0 number of * bytes of the *complete* pdu read */ int transport_read_pdu(rdpTransport* transport, wStream* s) { int status; int position; int pduLength; BYTE *header; position = 0; pduLength = 0; if (!transport) return -1; if (!s) return -1; position = Stream_GetPosition(s); /* Make sure there is enough space for the longest header within the stream */ Stream_EnsureCapacity(s, 4); /* Make sure at least two bytes are read for futher processing */ if (position < 2 && (status = transport_read_layer_bytes(transport, s, 2 - position)) != 1) { /* No data available at the moment */ return status; } header = Stream_Buffer(s); if (transport->NlaMode) { /* * In case NlaMode is set TSRequest package(s) are expected * 0x30 = DER encoded data with these bits set: * bit 6 P/C constructed * bit 5 tag number - sequence */ if (header[0] == 0x30) { /* TSRequest (NLA) */ if (header[1] & 0x80) { if ((header[1] & ~(0x80)) == 1) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = header[2]; pduLength += 3; } else if ((header[1] & ~(0x80)) == 2) { if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; pduLength += 4; } else { fprintf(stderr, "Error reading TSRequest!\n"); return -1; } } else { pduLength = header[1]; pduLength += 2; } } } else { if (header[0] == 0x03) { /* TPKT header */ if ((status = transport_read_layer_bytes(transport, s, 2)) != 1) return status; pduLength = (header[2] << 8) | header[3]; /* min and max values according to ITU-T Rec. T.123 (01/2007) section 8 */ if (pduLength < 7 || pduLength > 0xFFFF) { fprintf(stderr, "%s: tpkt - invalid pduLength: %d\n", __FUNCTION__, pduLength); return -1; } } else { /* Fast-Path Header */ if (header[1] & 0x80) { if ((status = transport_read_layer_bytes(transport, s, 1)) != 1) return status; pduLength = ((header[1] & 0x7F) << 8) | header[2]; } else pduLength = header[1]; /* * fast-path has 7 bits for length so the maximum size, including headers is 0x8000 * The theoretical minimum fast-path PDU consists only of two header bytes plus one * byte for data (e.g. fast-path input synchronize pdu) */ if (pduLength < 3 || pduLength > 0x8000) { fprintf(stderr, "%s: fast path - invalid pduLength: %d\n", __FUNCTION__, pduLength); return -1; } } } Stream_EnsureCapacity(s, Stream_GetPosition(s) + pduLength); status = transport_read_layer_bytes(transport, s, pduLength - Stream_GetPosition(s)); if (status != 1) return status; #ifdef WITH_DEBUG_TRANSPORT /* dump when whole PDU is read */ if (Stream_GetPosition(s) >= pduLength) { fprintf(stderr, "Local < Remote\n"); winpr_HexDump(Stream_Buffer(s), pduLength); } #endif if (Stream_GetPosition(s) >= pduLength) WLog_Packet(transport->log, WLOG_TRACE, Stream_Buffer(s), pduLength, WLOG_PACKET_INBOUND); Stream_SealLength(s); Stream_SetPosition(s, 0); return Stream_Length(s); }