FreeRDP
Loading...
Searching...
No Matches
tpdu.c
1
20#include <freerdp/config.h>
21
22#include <stdio.h>
23#include <winpr/print.h>
24
25#include <freerdp/log.h>
26
27#include "tpdu.h"
28
29#define TAG FREERDP_TAG("core")
30
66static BOOL tpdu_write_header(wStream* s, UINT16 length, BYTE code);
67
75BOOL tpdu_read_header(wStream* s, BYTE* code, BYTE* li, UINT16 tpktlength)
76{
77 if (!Stream_CheckAndLogRequiredLength(TAG, s, 3))
78 return FALSE;
79
80 Stream_Read_UINT8(s, *li); /* LI */
81 Stream_Read_UINT8(s, *code); /* Code */
82
83 if (*li + 4 > tpktlength)
84 {
85 WLog_ERR(TAG, "tpdu length %" PRIu8 " > tpkt header length %" PRIu16, *li, tpktlength);
86 return FALSE;
87 }
88
89 if (*code == X224_TPDU_DATA)
90 {
91 /* EOT (1 byte) */
92 Stream_Seek(s, 1);
93 }
94 else
95 {
96 /* DST-REF (2 bytes) */
97 /* SRC-REF (2 bytes) */
98 /* Class 0 (1 byte) */
99 if (!Stream_SafeSeek(s, 5))
100 {
101 WLog_WARN(TAG, "tpdu invalid data, got %" PRIuz ", require at least 5 more",
102 Stream_GetRemainingLength(s));
103 return FALSE;
104 }
105 }
106
107 return TRUE;
108}
109
117BOOL tpdu_write_header(wStream* s, UINT16 length, BYTE code)
118{
119 if (length > UINT8_MAX)
120 {
121 WLog_WARN(TAG, "tpdu invalid length, got %" PRIu16 ", maximum supported is %d", length,
122 UINT8_MAX);
123 return FALSE;
124 }
125 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 3))
126 return FALSE;
127
128 WINPR_ASSERT(length <= UINT8_MAX);
129 Stream_Write_UINT8(s, (UINT8)length); /* LI */
130 Stream_Write_UINT8(s, code); /* code */
131
132 if (code == X224_TPDU_DATA)
133 {
134 Stream_Write_UINT8(s, 0x80); /* EOT */
135 }
136 else
137 {
138 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 5))
139 return FALSE;
140 Stream_Write_UINT16(s, 0); /* DST-REF */
141 Stream_Write_UINT16(s, 0); /* SRC-REF */
142 Stream_Write_UINT8(s, 0); /* Class 0 */
143 }
144 return TRUE;
145}
146
153BOOL tpdu_read_connection_request(wStream* s, BYTE* li, UINT16 tpktlength)
154{
155 BYTE code = 0;
156
157 if (!tpdu_read_header(s, &code, li, tpktlength))
158 return FALSE;
159
160 if (code != X224_TPDU_CONNECTION_REQUEST)
161 {
162 WLog_ERR(TAG, "Error: expected X224_TPDU_CONNECTION_REQUEST");
163 return FALSE;
164 }
165
166 return TRUE;
167}
168
175BOOL tpdu_write_connection_request(wStream* s, UINT16 length)
176{
177 return tpdu_write_header(s, length, X224_TPDU_CONNECTION_REQUEST);
178}
179
186BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li, UINT16 tpktlength)
187{
188 BYTE code = 0;
189 size_t position = 0;
190 size_t bytes_read = 0;
191
192 /* save the position to determine the number of bytes read */
193 position = Stream_GetPosition(s);
194
195 if (!tpdu_read_header(s, &code, li, tpktlength))
196 return FALSE;
197
198 if (code != X224_TPDU_CONNECTION_CONFIRM)
199 {
200 WLog_ERR(TAG, "Error: expected X224_TPDU_CONNECTION_CONFIRM");
201 return FALSE;
202 }
203 /*
204 * To ensure that there are enough bytes remaining for processing
205 * check against the length indicator (li). Already read bytes need
206 * to be taken into account.
207 * The -1 is because li was read but isn't included in the TPDU size.
208 * For reference see ITU-T Rec. X.224 - 13.2.1
209 */
210 bytes_read = (Stream_GetPosition(s) - position) - 1;
211
212 return Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(*li - bytes_read));
213}
214
221BOOL tpdu_write_connection_confirm(wStream* s, UINT16 length)
222{
223 return tpdu_write_header(s, length, X224_TPDU_CONNECTION_CONFIRM);
224}
225
232BOOL tpdu_write_disconnect_request(wStream* s, UINT16 length)
233{
234 return tpdu_write_header(s, length, X224_TPDU_DISCONNECT_REQUEST);
235}
236
242BOOL tpdu_write_data(wStream* s)
243{
244 return tpdu_write_header(s, 2, X224_TPDU_DATA);
245}
246
252BOOL tpdu_read_data(wStream* s, UINT16* LI, UINT16 tpktlength)
253{
254 BYTE code = 0;
255 BYTE li = 0;
256
257 if (!tpdu_read_header(s, &code, &li, tpktlength))
258 return FALSE;
259
260 if (code != X224_TPDU_DATA)
261 {
262 const BYTE dCode = X224_TPDU_DATA;
263 WLog_ERR(TAG, "tpdu got code 0x%02" PRIx8 " expected X224_TPDU_DATA [0x%02" PRIx8 "]", code,
264 dCode);
265 return FALSE;
266 }
267
268 *LI = li;
269
270 return TRUE;
271}
272
273const char* tpdu_type_to_string(int type)
274{
275 switch (type)
276 {
277 case X224_TPDU_CONNECTION_REQUEST:
278 return "X224_TPDU_CONNECTION_REQUEST";
279 case X224_TPDU_CONNECTION_CONFIRM:
280 return "X224_TPDU_CONNECTION_CONFIRM";
281 case X224_TPDU_DISCONNECT_REQUEST:
282 return "X224_TPDU_DISCONNECT_REQUEST";
283 case X224_TPDU_DATA:
284 return "X224_TPDU_DATA";
285 case X224_TPDU_ERROR:
286 return "X224_TPDU_ERROR";
287 default:
288 return "X224_TPDU_UNKNOWN";
289 }
290}