2011-07-03 01:10:10 +04:00
|
|
|
/**
|
2012-10-09 07:02:04 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-07-03 01:10:10 +04:00
|
|
|
* X.224 Transport Protocol Data Units (TPDUs)
|
|
|
|
*
|
|
|
|
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2012-08-15 01:09:01 +04:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-07-03 21:49:06 +04:00
|
|
|
#include <stdio.h>
|
2013-07-20 02:24:56 +04:00
|
|
|
#include <winpr/print.h>
|
2011-07-03 21:49:06 +04:00
|
|
|
|
2014-09-12 16:36:29 +04:00
|
|
|
#include <freerdp/log.h>
|
2014-08-07 18:51:24 +04:00
|
|
|
|
2011-07-03 01:10:10 +04:00
|
|
|
#include "tpdu.h"
|
|
|
|
|
2014-09-12 16:36:29 +04:00
|
|
|
#define TAG FREERDP_TAG("core")
|
|
|
|
|
2011-07-03 01:10:10 +04:00
|
|
|
/**
|
|
|
|
* TPDUs are defined in:
|
|
|
|
*
|
|
|
|
* http://www.itu.int/rec/T-REC-X.224-199511-I/
|
2019-11-06 17:24:51 +03:00
|
|
|
* X.224: Information technology - Open Systems Interconnection - Protocol for providing the
|
|
|
|
* connection-mode transport service
|
2011-07-03 01:10:10 +04:00
|
|
|
*
|
|
|
|
* RDP uses only TPDUs of class 0, the "simple class" defined in section 8 of X.224
|
|
|
|
*
|
|
|
|
* TPDU Header
|
|
|
|
* ____________________ byte
|
|
|
|
* | |
|
|
|
|
* | LI | 1
|
|
|
|
* |____________________|
|
|
|
|
* | |
|
|
|
|
* | Code | 2
|
|
|
|
* |____________________|
|
|
|
|
* | |
|
|
|
|
* | | 3
|
|
|
|
* |_______DST-REF______|
|
|
|
|
* | |
|
|
|
|
* | | 4
|
|
|
|
* |____________________|
|
|
|
|
* | |
|
|
|
|
* | | 5
|
|
|
|
* |_______SRC-REF______|
|
|
|
|
* | |
|
|
|
|
* | | 6
|
|
|
|
* |____________________|
|
|
|
|
* | |
|
|
|
|
* | Class | 7
|
|
|
|
* |____________________|
|
|
|
|
* | ... |
|
|
|
|
*/
|
|
|
|
|
2019-11-20 13:30:14 +03:00
|
|
|
static void tpdu_write_header(wStream* s, UINT16 length, BYTE code);
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Read TPDU header.
|
|
|
|
* @param s stream
|
|
|
|
* @param code variable pointer to receive TPDU code
|
|
|
|
* @return TPDU length indicator (LI)
|
|
|
|
*/
|
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li, UINT16 tpktlength)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
2013-07-20 02:24:56 +04:00
|
|
|
if (Stream_GetRemainingLength(s) < 3)
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-07-03 01:10:10 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Read_UINT8(s, *li); /* LI */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT8(s, *code); /* Code */
|
2011-07-03 21:49:06 +04:00
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
if (*li + 4 > tpktlength)
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "tpdu length %" PRIu16 " > tpkt header length %" PRIu16, li, tpktlength);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-07-04 03:27:02 +04:00
|
|
|
if (*code == X224_TPDU_DATA)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
|
|
|
/* EOT (1 byte) */
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(s, 1);
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
2011-07-09 23:28:59 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* DST-REF (2 bytes) */
|
|
|
|
/* SRC-REF (2 bytes) */
|
|
|
|
/* Class 0 (1 byte) */
|
2013-05-09 01:48:30 +04:00
|
|
|
return Stream_SafeSeek(s, 5);
|
2011-07-09 23:28:59 +04:00
|
|
|
}
|
2013-07-20 02:24:56 +04:00
|
|
|
|
2013-01-12 17:49:01 +04:00
|
|
|
return TRUE;
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Write TDPU header.
|
|
|
|
* @param s stream
|
|
|
|
* @param length length
|
|
|
|
* @param code TPDU code
|
|
|
|
*/
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
void tpdu_write_header(wStream* s, UINT16 length, BYTE code)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT8(s, length); /* LI */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT8(s, code); /* code */
|
2011-07-03 01:10:10 +04:00
|
|
|
|
|
|
|
if (code == X224_TPDU_DATA)
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT8(s, 0x80); /* EOT */
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT16(s, 0); /* DST-REF */
|
|
|
|
Stream_Write_UINT16(s, 0); /* SRC-REF */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT8(s, 0); /* Class 0 */
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-18 19:15:28 +04:00
|
|
|
/**
|
|
|
|
* Read Connection Request TPDU
|
|
|
|
* @param s stream
|
|
|
|
* @return length indicator (LI)
|
|
|
|
*/
|
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
BOOL tpdu_read_connection_request(wStream* s, BYTE* li, UINT16 tpktlength)
|
2011-08-18 19:15:28 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE code;
|
2011-08-18 19:15:28 +04:00
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
if (!tpdu_read_header(s, &code, li, tpktlength))
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-08-18 19:15:28 +04:00
|
|
|
|
|
|
|
if (code != X224_TPDU_CONNECTION_REQUEST)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "Error: expected X224_TPDU_CONNECTION_REQUEST");
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-08-18 19:15:28 +04:00
|
|
|
}
|
|
|
|
|
2013-01-12 17:49:01 +04:00
|
|
|
return TRUE;
|
2011-08-18 19:15:28 +04:00
|
|
|
}
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Write Connection Request TPDU.
|
|
|
|
* @param s stream
|
|
|
|
* @param length TPDU length
|
|
|
|
*/
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
void tpdu_write_connection_request(wStream* s, UINT16 length)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
2011-07-03 20:42:35 +04:00
|
|
|
tpdu_write_header(s, length, X224_TPDU_CONNECTION_REQUEST);
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Read Connection Confirm TPDU.
|
|
|
|
* @param s stream
|
|
|
|
* @return length indicator (LI)
|
|
|
|
*/
|
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li, UINT16 tpktlength)
|
2011-07-03 21:49:06 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE code;
|
2017-12-11 12:25:21 +03:00
|
|
|
size_t position;
|
|
|
|
size_t bytes_read = 0;
|
2014-07-22 21:14:43 +04:00
|
|
|
|
|
|
|
/* save the position to determine the number of bytes read */
|
|
|
|
position = Stream_GetPosition(s);
|
2011-07-03 21:49:06 +04:00
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
if (!tpdu_read_header(s, &code, li, tpktlength))
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-07-03 21:49:06 +04:00
|
|
|
|
|
|
|
if (code != X224_TPDU_CONNECTION_CONFIRM)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "Error: expected X224_TPDU_CONNECTION_CONFIRM");
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-07-03 21:49:06 +04:00
|
|
|
}
|
2014-07-22 21:14:43 +04:00
|
|
|
/*
|
|
|
|
* To ensure that there are enough bytes remaining for processing
|
|
|
|
* check against the length indicator (li). Already read bytes need
|
|
|
|
* to be taken into account.
|
|
|
|
* The -1 is because li was read but isn't included in the TPDU size.
|
|
|
|
* For reference see ITU-T Rec. X.224 - 13.2.1
|
|
|
|
*/
|
|
|
|
bytes_read = (Stream_GetPosition(s) - position) - 1;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
return (Stream_GetRemainingLength(s) >= (size_t)(*li - bytes_read));
|
2011-07-03 21:49:06 +04:00
|
|
|
}
|
|
|
|
|
2011-08-18 19:15:28 +04:00
|
|
|
/**
|
|
|
|
* Write Connection Confirm TPDU.
|
|
|
|
* @param s stream
|
|
|
|
* @param length TPDU length
|
|
|
|
*/
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
void tpdu_write_connection_confirm(wStream* s, UINT16 length)
|
2011-08-18 19:15:28 +04:00
|
|
|
{
|
|
|
|
tpdu_write_header(s, length, X224_TPDU_CONNECTION_CONFIRM);
|
|
|
|
}
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Write Disconnect Request TPDU.
|
|
|
|
* @param s stream
|
|
|
|
* @param length TPDU length
|
|
|
|
*/
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
void tpdu_write_disconnect_request(wStream* s, UINT16 length)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
2011-07-03 20:42:35 +04:00
|
|
|
tpdu_write_header(s, length, X224_TPDU_DISCONNECT_REQUEST);
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
|
|
|
|
2011-07-05 05:35:32 +04:00
|
|
|
/**
|
|
|
|
* Write Data TPDU.
|
|
|
|
* @param s stream
|
|
|
|
*/
|
|
|
|
|
2013-03-21 23:19:33 +04:00
|
|
|
void tpdu_write_data(wStream* s)
|
2011-07-03 01:10:10 +04:00
|
|
|
{
|
2011-07-08 08:37:25 +04:00
|
|
|
tpdu_write_header(s, 2, X224_TPDU_DATA);
|
2011-07-03 01:10:10 +04:00
|
|
|
}
|
2011-07-09 23:28:59 +04:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Read Data TPDU.
|
|
|
|
* @param s stream
|
|
|
|
*/
|
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
BOOL tpdu_read_data(wStream* s, UINT16* LI, UINT16 tpktlength)
|
2011-07-09 23:28:59 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE code;
|
2013-01-12 17:49:01 +04:00
|
|
|
BYTE li;
|
2011-07-09 23:28:59 +04:00
|
|
|
|
2020-02-20 10:22:19 +03:00
|
|
|
if (!tpdu_read_header(s, &code, &li, tpktlength))
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2011-07-09 23:28:59 +04:00
|
|
|
|
|
|
|
if (code != X224_TPDU_DATA)
|
2013-01-12 17:49:01 +04:00
|
|
|
return FALSE;
|
2013-07-20 02:24:56 +04:00
|
|
|
|
2013-01-12 17:49:01 +04:00
|
|
|
*LI = li;
|
2013-07-20 02:24:56 +04:00
|
|
|
|
2013-01-12 17:49:01 +04:00
|
|
|
return TRUE;
|
2011-07-09 23:28:59 +04:00
|
|
|
}
|