1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Auto-Detect PDUs
4  *
5  * Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <winpr/crypto.h>
25 
26 #include "autodetect.h"
27 
28 #define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001
29 #define RDP_RTT_REQUEST_TYPE_CONNECTTIME 0x1001
30 
31 #define RDP_RTT_RESPONSE_TYPE 0x0000
32 
33 #define RDP_BW_START_REQUEST_TYPE_CONTINUOUS 0x0014
34 #define RDP_BW_START_REQUEST_TYPE_TUNNEL 0x0114
35 #define RDP_BW_START_REQUEST_TYPE_CONNECTTIME 0x1014
36 #define RDP_BW_PAYLOAD_REQUEST_TYPE 0x0002
37 #define RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME 0x002B
38 #define RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS 0x0429
39 #define RDP_BW_STOP_REQUEST_TYPE_TUNNEL 0x0629
40 
41 #define RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME 0x0003
42 #define RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS 0x000B
43 
44 #define RDP_NETCHAR_SYNC_RESPONSE_TYPE 0x0018
45 
46 #define RDP_NETCHAR_RESULTS_0x0840 0x0840U
47 #define RDP_NETCHAR_RESULTS_0x0880 0x0880U
48 #define RDP_NETCHAR_RESULTS_0x08C0 0x08C0U
49 
50 typedef struct
51 {
52 	UINT8 headerLength;
53 	UINT8 headerTypeId;
54 	UINT16 sequenceNumber;
55 	UINT16 requestType;
56 } AUTODETECT_REQ_PDU;
57 
58 typedef struct
59 {
60 	UINT8 headerLength;
61 	UINT8 headerTypeId;
62 	UINT16 sequenceNumber;
63 	UINT16 responseType;
64 } AUTODETECT_RSP_PDU;
65 
autodetect_request_type_to_string(UINT32 requestType)66 static const char* autodetect_request_type_to_string(UINT32 requestType)
67 {
68 	switch (requestType)
69 	{
70 		case RDP_RTT_RESPONSE_TYPE:
71 			return "RDP_RTT_RESPONSE_TYPE";
72 		case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
73 			return "RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME";
74 		case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
75 			return "RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS";
76 		case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
77 			return "RDP_RTT_REQUEST_TYPE_CONTINUOUS";
78 		case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
79 			return "RDP_RTT_REQUEST_TYPE_CONNECTTIME";
80 		case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
81 			return "RDP_BW_START_REQUEST_TYPE_CONTINUOUS";
82 		case RDP_BW_START_REQUEST_TYPE_TUNNEL:
83 			return "RDP_BW_START_REQUEST_TYPE_TUNNEL";
84 		case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
85 			return "RDP_BW_START_REQUEST_TYPE_CONNECTTIME";
86 		case RDP_BW_PAYLOAD_REQUEST_TYPE:
87 			return "RDP_BW_PAYLOAD_REQUEST_TYPE";
88 		case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
89 			return "RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME";
90 		case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
91 			return "RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS";
92 		case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
93 			return "RDP_BW_STOP_REQUEST_TYPE_TUNNEL";
94 		case RDP_NETCHAR_RESULTS_0x0840:
95 			return "RDP_NETCHAR_RESULTS_0x0840";
96 		case RDP_NETCHAR_RESULTS_0x0880:
97 			return "RDP_NETCHAR_RESULTS_0x0880";
98 		case RDP_NETCHAR_RESULTS_0x08C0:
99 			return "RDP_NETCHAR_RESULTS_0x08C0";
100 		default:
101 			return "UNKNOWN";
102 	}
103 }
104 
autodetect_send_rtt_measure_request(rdpContext * context,UINT16 sequenceNumber,UINT16 requestType)105 static BOOL autodetect_send_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber,
106                                                 UINT16 requestType)
107 {
108 	wStream* s;
109 	s = rdp_message_channel_pdu_init(context->rdp);
110 
111 	if (!s)
112 		return FALSE;
113 
114 	WLog_VRB(AUTODETECT_TAG, "sending RTT Measure Request PDU");
115 	Stream_Write_UINT8(s, 0x06);                       /* headerLength (1 byte) */
116 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
117 	Stream_Write_UINT16(s, sequenceNumber);            /* sequenceNumber (2 bytes) */
118 	Stream_Write_UINT16(s, requestType);               /* requestType (2 bytes) */
119 	context->rdp->autodetect->rttMeasureStartTime = GetTickCount64();
120 	return rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
121 }
122 
autodetect_send_continuous_rtt_measure_request(rdpContext * context,UINT16 sequenceNumber)123 static BOOL autodetect_send_continuous_rtt_measure_request(rdpContext* context,
124                                                            UINT16 sequenceNumber)
125 {
126 	return autodetect_send_rtt_measure_request(context, sequenceNumber,
127 	                                           RDP_RTT_REQUEST_TYPE_CONTINUOUS);
128 }
129 
autodetect_send_connecttime_rtt_measure_request(rdpContext * context,UINT16 sequenceNumber)130 BOOL autodetect_send_connecttime_rtt_measure_request(rdpContext* context, UINT16 sequenceNumber)
131 {
132 	return autodetect_send_rtt_measure_request(context, sequenceNumber,
133 	                                           RDP_RTT_REQUEST_TYPE_CONNECTTIME);
134 }
135 
autodetect_send_rtt_measure_response(rdpRdp * rdp,UINT16 sequenceNumber)136 static BOOL autodetect_send_rtt_measure_response(rdpRdp* rdp, UINT16 sequenceNumber)
137 {
138 	wStream* s;
139 	/* Send the response PDU to the server */
140 	s = rdp_message_channel_pdu_init(rdp);
141 
142 	if (!s)
143 		return FALSE;
144 
145 	WLog_VRB(AUTODETECT_TAG, "sending RTT Measure Response PDU");
146 	Stream_Write_UINT8(s, 0x06);                        /* headerLength (1 byte) */
147 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
148 	Stream_Write_UINT16(s, sequenceNumber);             /* sequenceNumber (2 bytes) */
149 	Stream_Write_UINT16(s, RDP_RTT_RESPONSE_TYPE);      /* responseType (1 byte) */
150 	return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
151 }
152 
autodetect_send_bandwidth_measure_start(rdpContext * context,UINT16 sequenceNumber,UINT16 requestType)153 static BOOL autodetect_send_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber,
154                                                     UINT16 requestType)
155 {
156 	wStream* s;
157 	s = rdp_message_channel_pdu_init(context->rdp);
158 
159 	if (!s)
160 		return FALSE;
161 
162 	WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Start PDU");
163 	Stream_Write_UINT8(s, 0x06);                       /* headerLength (1 byte) */
164 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
165 	Stream_Write_UINT16(s, sequenceNumber);            /* sequenceNumber (2 bytes) */
166 	Stream_Write_UINT16(s, requestType);               /* requestType (2 bytes) */
167 	return rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
168 }
169 
autodetect_send_continuous_bandwidth_measure_start(rdpContext * context,UINT16 sequenceNumber)170 static BOOL autodetect_send_continuous_bandwidth_measure_start(rdpContext* context,
171                                                                UINT16 sequenceNumber)
172 {
173 	return autodetect_send_bandwidth_measure_start(context, sequenceNumber,
174 	                                               RDP_BW_START_REQUEST_TYPE_CONTINUOUS);
175 }
176 
autodetect_send_connecttime_bandwidth_measure_start(rdpContext * context,UINT16 sequenceNumber)177 BOOL autodetect_send_connecttime_bandwidth_measure_start(rdpContext* context, UINT16 sequenceNumber)
178 {
179 	return autodetect_send_bandwidth_measure_start(context, sequenceNumber,
180 	                                               RDP_BW_START_REQUEST_TYPE_CONNECTTIME);
181 }
182 
autodetect_send_bandwidth_measure_payload(rdpContext * context,UINT16 payloadLength,UINT16 sequenceNumber)183 BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 payloadLength,
184                                                UINT16 sequenceNumber)
185 {
186 	wStream* s;
187 	UCHAR* buffer = NULL;
188 	BOOL bResult = FALSE;
189 	s = rdp_message_channel_pdu_init(context->rdp);
190 
191 	if (!s)
192 		return FALSE;
193 
194 	WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "",
195 	         payloadLength);
196 	/* 4-bytes aligned */
197 	payloadLength &= ~3;
198 
199 	if (!Stream_EnsureRemainingCapacity(s, 8 + payloadLength))
200 	{
201 		Stream_Release(s);
202 		return FALSE;
203 	}
204 
205 	Stream_Write_UINT8(s, 0x08);                         /* headerLength (1 byte) */
206 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);   /* headerTypeId (1 byte) */
207 	Stream_Write_UINT16(s, sequenceNumber);              /* sequenceNumber (2 bytes) */
208 	Stream_Write_UINT16(s, RDP_BW_PAYLOAD_REQUEST_TYPE); /* requestType (2 bytes) */
209 	Stream_Write_UINT16(s, payloadLength);               /* payloadLength (2 bytes) */
210 	/* Random data (better measurement in case the line is compressed) */
211 	buffer = (UCHAR*)malloc(payloadLength);
212 
213 	if (NULL == buffer)
214 	{
215 		Stream_Release(s);
216 		return FALSE;
217 	}
218 
219 	winpr_RAND(buffer, payloadLength);
220 	Stream_Write(s, buffer, payloadLength);
221 	bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
222 	free(buffer);
223 	return bResult;
224 }
225 
autodetect_send_bandwidth_measure_stop(rdpContext * context,UINT16 payloadLength,UINT16 sequenceNumber,UINT16 requestType)226 static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength,
227                                                    UINT16 sequenceNumber, UINT16 requestType)
228 {
229 	wStream* s;
230 	UCHAR* buffer = NULL;
231 	BOOL bResult = FALSE;
232 	s = rdp_message_channel_pdu_init(context->rdp);
233 
234 	if (!s)
235 		return FALSE;
236 
237 	WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "",
238 	         payloadLength);
239 	/* 4-bytes aligned */
240 	payloadLength &= ~3;
241 	Stream_Write_UINT8(s, requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
242 	                          ? 0x08
243 	                          : 0x06);                 /* headerLength (1 byte) */
244 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST); /* headerTypeId (1 byte) */
245 	Stream_Write_UINT16(s, sequenceNumber);            /* sequenceNumber (2 bytes) */
246 	Stream_Write_UINT16(s, requestType);               /* requestType (2 bytes) */
247 
248 	if (requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
249 	{
250 		Stream_Write_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
251 
252 		if (payloadLength > 0)
253 		{
254 			if (!Stream_EnsureRemainingCapacity(s, payloadLength))
255 			{
256 				Stream_Release(s);
257 				return FALSE;
258 			}
259 
260 			/* Random data (better measurement in case the line is compressed) */
261 			buffer = malloc(payloadLength);
262 
263 			if (NULL == buffer)
264 			{
265 				Stream_Release(s);
266 				return FALSE;
267 			}
268 
269 			winpr_RAND(buffer, payloadLength);
270 			Stream_Write(s, buffer, payloadLength);
271 		}
272 	}
273 
274 	bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
275 	free(buffer);
276 	return bResult;
277 }
278 
autodetect_send_continuous_bandwidth_measure_stop(rdpContext * context,UINT16 sequenceNumber)279 static BOOL autodetect_send_continuous_bandwidth_measure_stop(rdpContext* context,
280                                                               UINT16 sequenceNumber)
281 {
282 	return autodetect_send_bandwidth_measure_stop(context, 0, sequenceNumber,
283 	                                              RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS);
284 }
285 
autodetect_send_connecttime_bandwidth_measure_stop(rdpContext * context,UINT16 payloadLength,UINT16 sequenceNumber)286 BOOL autodetect_send_connecttime_bandwidth_measure_stop(rdpContext* context, UINT16 payloadLength,
287                                                         UINT16 sequenceNumber)
288 {
289 	return autodetect_send_bandwidth_measure_stop(context, payloadLength, sequenceNumber,
290 	                                              RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME);
291 }
292 
autodetect_send_bandwidth_measure_results(rdpRdp * rdp,UINT16 responseType,UINT16 sequenceNumber)293 static BOOL autodetect_send_bandwidth_measure_results(rdpRdp* rdp, UINT16 responseType,
294                                                       UINT16 sequenceNumber)
295 {
296 	BOOL success = TRUE;
297 	wStream* s;
298 	UINT64 timeDelta;
299 	/* Compute the total time */
300 	timeDelta = GetTickCount64() - rdp->autodetect->bandwidthMeasureStartTime;
301 	/* Send the result PDU to the server */
302 	s = rdp_message_channel_pdu_init(rdp);
303 
304 	if (!s)
305 		return FALSE;
306 
307 	WLog_VRB(AUTODETECT_TAG,
308 	         "sending Bandwidth Measure Results PDU -> timeDelta=%" PRIu32 ", byteCount=%" PRIu32
309 	         "",
310 	         timeDelta, rdp->autodetect->bandwidthMeasureByteCount);
311 	Stream_Write_UINT8(s, 0x0E);                        /* headerLength (1 byte) */
312 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE); /* headerTypeId (1 byte) */
313 	Stream_Write_UINT16(s, sequenceNumber);             /* sequenceNumber (2 bytes) */
314 	Stream_Write_UINT16(s, responseType);               /* responseType (1 byte) */
315 	Stream_Write_UINT32(s, timeDelta);                  /* timeDelta (4 bytes) */
316 	Stream_Write_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
317 	IFCALLRET(rdp->autodetect->ClientBandwidthMeasureResult, success, rdp->context,
318 	          rdp->autodetect);
319 
320 	if (!success)
321 		return FALSE;
322 
323 	return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
324 }
325 
autodetect_send_netchar_result(rdpContext * context,UINT16 sequenceNumber)326 static BOOL autodetect_send_netchar_result(rdpContext* context, UINT16 sequenceNumber)
327 {
328 	wStream* s;
329 	s = rdp_message_channel_pdu_init(context->rdp);
330 
331 	if (!s)
332 		return FALSE;
333 
334 	WLog_VRB(AUTODETECT_TAG, "sending Bandwidth Network Characteristics Result PDU");
335 
336 	if (context->rdp->autodetect->netCharBandwidth > 0)
337 	{
338 		Stream_Write_UINT8(s, 0x12);                        /* headerLength (1 byte) */
339 		Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);  /* headerTypeId (1 byte) */
340 		Stream_Write_UINT16(s, sequenceNumber);             /* sequenceNumber (2 bytes) */
341 		Stream_Write_UINT16(s, RDP_NETCHAR_RESULTS_0x08C0); /* requestType (2 bytes) */
342 		Stream_Write_UINT32(s, context->rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
343 		Stream_Write_UINT32(s,
344 		                    context->rdp->autodetect->netCharBandwidth); /* bandwidth (4 bytes) */
345 		Stream_Write_UINT32(s,
346 		                    context->rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
347 	}
348 	else
349 	{
350 		Stream_Write_UINT8(s, 0x0E);                        /* headerLength (1 byte) */
351 		Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_REQUEST);  /* headerTypeId (1 byte) */
352 		Stream_Write_UINT16(s, sequenceNumber);             /* sequenceNumber (2 bytes) */
353 		Stream_Write_UINT16(s, RDP_NETCHAR_RESULTS_0x0840); /* requestType (2 bytes) */
354 		Stream_Write_UINT32(s, context->rdp->autodetect->netCharBaseRTT); /* baseRTT (4 bytes) */
355 		Stream_Write_UINT32(s,
356 		                    context->rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
357 	}
358 
359 	return rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ);
360 }
361 
autodetect_send_netchar_sync(rdpRdp * rdp,UINT16 sequenceNumber)362 static BOOL autodetect_send_netchar_sync(rdpRdp* rdp, UINT16 sequenceNumber)
363 {
364 	wStream* s;
365 	/* Send the response PDU to the server */
366 	s = rdp_message_channel_pdu_init(rdp);
367 
368 	if (!s)
369 		return FALSE;
370 
371 	WLog_VRB(AUTODETECT_TAG,
372 	         "sending Network Characteristics Sync PDU -> bandwidth=%" PRIu32 ", rtt=%" PRIu32 "",
373 	         rdp->autodetect->netCharBandwidth, rdp->autodetect->netCharAverageRTT);
374 	Stream_Write_UINT8(s, 0x0E);                                /* headerLength (1 byte) */
375 	Stream_Write_UINT8(s, TYPE_ID_AUTODETECT_RESPONSE);         /* headerTypeId (1 byte) */
376 	Stream_Write_UINT16(s, sequenceNumber);                     /* sequenceNumber (2 bytes) */
377 	Stream_Write_UINT16(s, RDP_NETCHAR_SYNC_RESPONSE_TYPE);     /* responseType (1 byte) */
378 	Stream_Write_UINT32(s, rdp->autodetect->netCharBandwidth);  /* bandwidth (4 bytes) */
379 	Stream_Write_UINT32(s, rdp->autodetect->netCharAverageRTT); /* rtt (4 bytes) */
380 	return rdp_send_message_channel_pdu(rdp, s, SEC_AUTODETECT_RSP);
381 }
382 
autodetect_recv_rtt_measure_request(rdpRdp * rdp,wStream * s,AUTODETECT_REQ_PDU * autodetectReqPdu)383 static BOOL autodetect_recv_rtt_measure_request(rdpRdp* rdp, wStream* s,
384                                                 AUTODETECT_REQ_PDU* autodetectReqPdu)
385 {
386 	if (autodetectReqPdu->headerLength != 0x06)
387 		return FALSE;
388 
389 	WLog_VRB(AUTODETECT_TAG, "received RTT Measure Request PDU");
390 	/* Send a response to the server */
391 	return autodetect_send_rtt_measure_response(rdp, autodetectReqPdu->sequenceNumber);
392 }
393 
autodetect_recv_rtt_measure_response(rdpRdp * rdp,wStream * s,AUTODETECT_RSP_PDU * autodetectRspPdu)394 static BOOL autodetect_recv_rtt_measure_response(rdpRdp* rdp, wStream* s,
395                                                  AUTODETECT_RSP_PDU* autodetectRspPdu)
396 {
397 	BOOL success = TRUE;
398 
399 	if (autodetectRspPdu->headerLength != 0x06)
400 		return FALSE;
401 
402 	WLog_VRB(AUTODETECT_TAG, "received RTT Measure Response PDU");
403 	rdp->autodetect->netCharAverageRTT = GetTickCount64() - rdp->autodetect->rttMeasureStartTime;
404 
405 	if (rdp->autodetect->netCharBaseRTT == 0 ||
406 	    rdp->autodetect->netCharBaseRTT > rdp->autodetect->netCharAverageRTT)
407 		rdp->autodetect->netCharBaseRTT = rdp->autodetect->netCharAverageRTT;
408 
409 	IFCALLRET(rdp->autodetect->RTTMeasureResponse, success, rdp->context,
410 	          autodetectRspPdu->sequenceNumber);
411 	return success;
412 }
413 
autodetect_recv_bandwidth_measure_start(rdpRdp * rdp,wStream * s,AUTODETECT_REQ_PDU * autodetectReqPdu)414 static BOOL autodetect_recv_bandwidth_measure_start(rdpRdp* rdp, wStream* s,
415                                                     AUTODETECT_REQ_PDU* autodetectReqPdu)
416 {
417 	if (autodetectReqPdu->headerLength != 0x06)
418 		return FALSE;
419 
420 	WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Start PDU - time=%" PRIu64 "",
421 	         GetTickCount64());
422 	/* Initialize bandwidth measurement parameters */
423 	rdp->autodetect->bandwidthMeasureStartTime = GetTickCount64();
424 	rdp->autodetect->bandwidthMeasureByteCount = 0;
425 
426 	/* Continuous Auto-Detection: mark the start of the measurement */
427 	if (autodetectReqPdu->requestType == RDP_BW_START_REQUEST_TYPE_CONTINUOUS)
428 	{
429 		rdp->autodetect->bandwidthMeasureStarted = TRUE;
430 	}
431 
432 	return TRUE;
433 }
434 
autodetect_recv_bandwidth_measure_payload(rdpRdp * rdp,wStream * s,AUTODETECT_REQ_PDU * autodetectReqPdu)435 static BOOL autodetect_recv_bandwidth_measure_payload(rdpRdp* rdp, wStream* s,
436                                                       AUTODETECT_REQ_PDU* autodetectReqPdu)
437 {
438 	UINT16 payloadLength;
439 
440 	if (autodetectReqPdu->headerLength != 0x08)
441 		return FALSE;
442 
443 	if (Stream_GetRemainingLength(s) < 2)
444 		return FALSE;
445 
446 	Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
447 	if (!Stream_SafeSeek(s, payloadLength))
448 		return FALSE;
449 	WLog_DBG(AUTODETECT_TAG, "received Bandwidth Measure Payload PDU -> payloadLength=%" PRIu16 "",
450 	         payloadLength);
451 	/* Add the payload length to the bandwidth measurement parameters */
452 	rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
453 	return TRUE;
454 }
455 
autodetect_recv_bandwidth_measure_stop(rdpRdp * rdp,wStream * s,AUTODETECT_REQ_PDU * autodetectReqPdu)456 static BOOL autodetect_recv_bandwidth_measure_stop(rdpRdp* rdp, wStream* s,
457                                                    AUTODETECT_REQ_PDU* autodetectReqPdu)
458 {
459 	UINT16 payloadLength;
460 	UINT16 responseType;
461 
462 	if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME)
463 	{
464 		if (autodetectReqPdu->headerLength != 0x08)
465 			return FALSE;
466 
467 		if (Stream_GetRemainingLength(s) < 2)
468 			return FALSE;
469 
470 		Stream_Read_UINT16(s, payloadLength); /* payloadLength (2 bytes) */
471 	}
472 	else
473 	{
474 		if (autodetectReqPdu->headerLength != 0x06)
475 			return FALSE;
476 
477 		payloadLength = 0;
478 	}
479 
480 	if (!Stream_SafeSeek(s, payloadLength))
481 		return FALSE;
482 
483 	WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Stop PDU -> payloadLength=%" PRIu16 "",
484 	         payloadLength);
485 	/* Add the payload length to the bandwidth measurement parameters */
486 	rdp->autodetect->bandwidthMeasureByteCount += payloadLength;
487 
488 	/* Continuous Auto-Detection: mark the stop of the measurement */
489 	if (autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS)
490 	{
491 		rdp->autodetect->bandwidthMeasureStarted = FALSE;
492 	}
493 
494 	/* Send a response the server */
495 	responseType = autodetectReqPdu->requestType == RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME
496 	                   ? RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME
497 	                   : RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS;
498 	return autodetect_send_bandwidth_measure_results(rdp, responseType,
499 	                                                 autodetectReqPdu->sequenceNumber);
500 }
501 
autodetect_recv_bandwidth_measure_results(rdpRdp * rdp,wStream * s,AUTODETECT_RSP_PDU * autodetectRspPdu)502 static BOOL autodetect_recv_bandwidth_measure_results(rdpRdp* rdp, wStream* s,
503                                                       AUTODETECT_RSP_PDU* autodetectRspPdu)
504 {
505 	BOOL success = TRUE;
506 
507 	if (autodetectRspPdu->headerLength != 0x0E)
508 		return FALSE;
509 
510 	WLog_VRB(AUTODETECT_TAG, "received Bandwidth Measure Results PDU");
511 	if (Stream_GetRemainingLength(s) < 8)
512 		return -1;
513 	Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureTimeDelta); /* timeDelta (4 bytes) */
514 	Stream_Read_UINT32(s, rdp->autodetect->bandwidthMeasureByteCount); /* byteCount (4 bytes) */
515 
516 	if (rdp->autodetect->bandwidthMeasureTimeDelta > 0)
517 		rdp->autodetect->netCharBandwidth = rdp->autodetect->bandwidthMeasureByteCount * 8 /
518 		                                    rdp->autodetect->bandwidthMeasureTimeDelta;
519 	else
520 		rdp->autodetect->netCharBandwidth = 0;
521 
522 	IFCALLRET(rdp->autodetect->BandwidthMeasureResults, success, rdp->context,
523 	          autodetectRspPdu->sequenceNumber);
524 	return success;
525 }
526 
autodetect_recv_netchar_result(rdpRdp * rdp,wStream * s,AUTODETECT_REQ_PDU * autodetectReqPdu)527 static BOOL autodetect_recv_netchar_result(rdpRdp* rdp, wStream* s,
528                                            AUTODETECT_REQ_PDU* autodetectReqPdu)
529 {
530 	BOOL success = TRUE;
531 
532 	switch (autodetectReqPdu->requestType)
533 	{
534 		case RDP_NETCHAR_RESULTS_0x0840:
535 
536 			/* baseRTT and averageRTT fields are present (bandwidth field is not) */
537 			if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
538 				return FALSE;
539 
540 			Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT);    /* baseRTT (4 bytes) */
541 			Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
542 			break;
543 
544 		case RDP_NETCHAR_RESULTS_0x0880:
545 
546 			/* bandwidth and averageRTT fields are present (baseRTT field is not) */
547 			if ((autodetectReqPdu->headerLength != 0x0E) || (Stream_GetRemainingLength(s) < 8))
548 				return FALSE;
549 
550 			Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth);  /* bandwidth (4 bytes) */
551 			Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
552 			break;
553 
554 		case RDP_NETCHAR_RESULTS_0x08C0:
555 
556 			/* baseRTT, bandwidth, and averageRTT fields are present */
557 			if ((autodetectReqPdu->headerLength != 0x12) || (Stream_GetRemainingLength(s) < 12))
558 				return FALSE;
559 
560 			Stream_Read_UINT32(s, rdp->autodetect->netCharBaseRTT);    /* baseRTT (4 bytes) */
561 			Stream_Read_UINT32(s, rdp->autodetect->netCharBandwidth);  /* bandwidth (4 bytes) */
562 			Stream_Read_UINT32(s, rdp->autodetect->netCharAverageRTT); /* averageRTT (4 bytes) */
563 			break;
564 	}
565 
566 	WLog_VRB(AUTODETECT_TAG,
567 	         "received Network Characteristics Result PDU -> baseRTT=%" PRIu32
568 	         ", bandwidth=%" PRIu32 ", averageRTT=%" PRIu32 "",
569 	         rdp->autodetect->netCharBaseRTT, rdp->autodetect->netCharBandwidth,
570 	         rdp->autodetect->netCharAverageRTT);
571 	IFCALLRET(rdp->autodetect->NetworkCharacteristicsResult, success, rdp->context,
572 	          autodetectReqPdu->sequenceNumber);
573 	return success;
574 }
575 
rdp_recv_autodetect_request_packet(rdpRdp * rdp,wStream * s)576 int rdp_recv_autodetect_request_packet(rdpRdp* rdp, wStream* s)
577 {
578 	AUTODETECT_REQ_PDU autodetectReqPdu;
579 	BOOL success = FALSE;
580 
581 	if (Stream_GetRemainingLength(s) < 6)
582 		return -1;
583 
584 	Stream_Read_UINT8(s, autodetectReqPdu.headerLength);    /* headerLength (1 byte) */
585 	Stream_Read_UINT8(s, autodetectReqPdu.headerTypeId);    /* headerTypeId (1 byte) */
586 	Stream_Read_UINT16(s, autodetectReqPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
587 	Stream_Read_UINT16(s, autodetectReqPdu.requestType);    /* requestType (2 bytes) */
588 	WLog_VRB(AUTODETECT_TAG,
589 	         "rdp_recv_autodetect_request_packet: headerLength=%" PRIu8 ", headerTypeId=%" PRIu8
590 	         ", sequenceNumber=%" PRIu16 ", requestType=%04" PRIx16 "",
591 	         autodetectReqPdu.headerLength, autodetectReqPdu.headerTypeId,
592 	         autodetectReqPdu.sequenceNumber, autodetectReqPdu.requestType);
593 
594 	if (!rdp->settings->NetworkAutoDetect)
595 	{
596 		WLog_WARN(AUTODETECT_TAG,
597 		          "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request (RDP_RTT_REQUEST) [%s] "
598 		          "message but support was not enabled",
599 		          autodetect_request_type_to_string(autodetectReqPdu.requestType));
600 	}
601 
602 	if (autodetectReqPdu.headerTypeId != TYPE_ID_AUTODETECT_REQUEST)
603 	{
604 		WLog_ERR(AUTODETECT_TAG,
605 		         "Received a [MS-RDPBCGR] 2.2.14.1.1 RTT Measure Request (RDP_RTT_REQUEST) [%s] "
606 		         "message with invalid headerTypeId=0x%04" PRIx16,
607 		         autodetect_request_type_to_string(autodetectReqPdu.requestType),
608 		         autodetectReqPdu.headerTypeId);
609 		return -1;
610 	}
611 
612 	switch (autodetectReqPdu.requestType)
613 	{
614 		case RDP_RTT_REQUEST_TYPE_CONTINUOUS:
615 		case RDP_RTT_REQUEST_TYPE_CONNECTTIME:
616 			/* RTT Measure Request (RDP_RTT_REQUEST) - MS-RDPBCGR 2.2.14.1.1 */
617 			success = autodetect_recv_rtt_measure_request(rdp, s, &autodetectReqPdu);
618 			break;
619 
620 		case RDP_BW_START_REQUEST_TYPE_CONTINUOUS:
621 		case RDP_BW_START_REQUEST_TYPE_TUNNEL:
622 		case RDP_BW_START_REQUEST_TYPE_CONNECTTIME:
623 			/* Bandwidth Measure Start (RDP_BW_START) - MS-RDPBCGR 2.2.14.1.2 */
624 			success = autodetect_recv_bandwidth_measure_start(rdp, s, &autodetectReqPdu);
625 			break;
626 
627 		case RDP_BW_PAYLOAD_REQUEST_TYPE:
628 			/* Bandwidth Measure Payload (RDP_BW_PAYLOAD) - MS-RDPBCGR 2.2.14.1.3 */
629 			success = autodetect_recv_bandwidth_measure_payload(rdp, s, &autodetectReqPdu);
630 			break;
631 
632 		case RDP_BW_STOP_REQUEST_TYPE_CONNECTTIME:
633 		case RDP_BW_STOP_REQUEST_TYPE_CONTINUOUS:
634 		case RDP_BW_STOP_REQUEST_TYPE_TUNNEL:
635 			/* Bandwidth Measure Stop (RDP_BW_STOP) - MS-RDPBCGR 2.2.14.1.4 */
636 			success = autodetect_recv_bandwidth_measure_stop(rdp, s, &autodetectReqPdu);
637 			break;
638 
639 		case RDP_NETCHAR_RESULTS_0x0840:
640 		case RDP_NETCHAR_RESULTS_0x0880:
641 		case RDP_NETCHAR_RESULTS_0x08C0:
642 			/* Network Characteristics Result (RDP_NETCHAR_RESULT) - MS-RDPBCGR 2.2.14.1.5 */
643 			success = autodetect_recv_netchar_result(rdp, s, &autodetectReqPdu);
644 			break;
645 
646 		default:
647 			break;
648 	}
649 
650 	return success ? 0 : -1;
651 }
652 
rdp_recv_autodetect_response_packet(rdpRdp * rdp,wStream * s)653 int rdp_recv_autodetect_response_packet(rdpRdp* rdp, wStream* s)
654 {
655 	AUTODETECT_RSP_PDU autodetectRspPdu;
656 	BOOL success = FALSE;
657 
658 	if (Stream_GetRemainingLength(s) < 6)
659 		return -1;
660 
661 	Stream_Read_UINT8(s, autodetectRspPdu.headerLength);    /* headerLength (1 byte) */
662 	Stream_Read_UINT8(s, autodetectRspPdu.headerTypeId);    /* headerTypeId (1 byte) */
663 	Stream_Read_UINT16(s, autodetectRspPdu.sequenceNumber); /* sequenceNumber (2 bytes) */
664 	Stream_Read_UINT16(s, autodetectRspPdu.responseType);   /* responseType (2 bytes) */
665 	WLog_VRB(AUTODETECT_TAG,
666 	         "rdp_recv_autodetect_response_packet: headerLength=%" PRIu8 ", headerTypeId=%" PRIu8
667 	         ", sequenceNumber=%" PRIu16 ", requestType=%04" PRIx16 "",
668 	         autodetectRspPdu.headerLength, autodetectRspPdu.headerTypeId,
669 	         autodetectRspPdu.sequenceNumber, autodetectRspPdu.responseType);
670 
671 	if (!rdp->settings->NetworkAutoDetect)
672 	{
673 		WLog_WARN(AUTODETECT_TAG,
674 		          "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response (RDP_RTT_RESPONSE) [%s] "
675 		          "message but support was not enabled",
676 		          autodetect_request_type_to_string(autodetectRspPdu.responseType));
677 	}
678 
679 	if (autodetectRspPdu.headerTypeId != TYPE_ID_AUTODETECT_RESPONSE)
680 	{
681 		WLog_ERR(AUTODETECT_TAG,
682 		         "Received a [MS-RDPBCGR] 2.2.14.2.1 RTT Measure Response (RDP_RTT_RESPONSE) [%s] "
683 		         "message with invalid headerTypeId=0x%04" PRIx16,
684 		         autodetect_request_type_to_string(autodetectRspPdu.responseType),
685 		         autodetectRspPdu.headerTypeId);
686 		return -1;
687 	}
688 
689 	switch (autodetectRspPdu.responseType)
690 	{
691 		case RDP_RTT_RESPONSE_TYPE:
692 			/* RTT Measure Response (RDP_RTT_RESPONSE) - MS-RDPBCGR 2.2.14.2.1 */
693 			success = autodetect_recv_rtt_measure_response(rdp, s, &autodetectRspPdu);
694 			break;
695 
696 		case RDP_BW_RESULTS_RESPONSE_TYPE_CONNECTTIME:
697 		case RDP_BW_RESULTS_RESPONSE_TYPE_CONTINUOUS:
698 			/* Bandwidth Measure Results (RDP_BW_RESULTS) - MS-RDPBCGR 2.2.14.2.2 */
699 			success = autodetect_recv_bandwidth_measure_results(rdp, s, &autodetectRspPdu);
700 			break;
701 
702 		default:
703 			break;
704 	}
705 	return success ? 0 : -1;
706 }
707 
autodetect_new(void)708 rdpAutoDetect* autodetect_new(void)
709 {
710 	rdpAutoDetect* autoDetect = (rdpAutoDetect*)calloc(1, sizeof(rdpAutoDetect));
711 
712 	if (autoDetect)
713 	{
714 	}
715 
716 	return autoDetect;
717 }
718 
autodetect_free(rdpAutoDetect * autoDetect)719 void autodetect_free(rdpAutoDetect* autoDetect)
720 {
721 	free(autoDetect);
722 }
723 
autodetect_register_server_callbacks(rdpAutoDetect * autodetect)724 void autodetect_register_server_callbacks(rdpAutoDetect* autodetect)
725 {
726 	autodetect->RTTMeasureRequest = autodetect_send_continuous_rtt_measure_request;
727 	autodetect->BandwidthMeasureStart = autodetect_send_continuous_bandwidth_measure_start;
728 	autodetect->BandwidthMeasureStop = autodetect_send_continuous_bandwidth_measure_stop;
729 	autodetect->NetworkCharacteristicsResult = autodetect_send_netchar_result;
730 }
731