18#include <freerdp/config.h>
20#include <freerdp/freerdp.h>
21#include <freerdp/settings.h>
22#include <winpr/crypto.h>
23#include <winpr/stream.h>
26#include "../connection.h"
29#include "../security.h"
33static const BYTE demandActive[] = {
34 0x16, 0x00, 0x11, 0x00, 0xEA, 0x03,
35 0x00, 0x00, 0x01, 0x00,
36 0x00, 0x00, 0x04, 0x00,
37 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00
41static const BYTE flowResponse[] = { 0x00, 0x80, PDU_TYPE_FLOW_RESPONSE, 0, 0, 0, 0, 0 };
42static const BYTE shortDeactivate[] = { 0x04, 0x00, 0x16, 0x00 };
52static void free_client(freerdp* instance)
56 freerdp_context_free(instance);
57 freerdp_free(instance);
61WINPR_ATTR_MALLOC(free_client, 1)
62static freerdp* new_client(
void)
64 freerdp* instance = freerdp_new();
67 if (!freerdp_context_new(instance) ||
70 freerdp_free(instance);
79WINPR_ATTR_MALLOC(Stream_Free, 1)
80static
wStream* packet(const BYTE* payload,
size_t payloadLength, UINT16 declaredLength,
81 BOOL serverMode, BOOL longLength,
size_t prefix,
size_t suffix)
83 const size_t headerLength = longLength ? 15 : 14;
84 wStream* s = Stream_New(
nullptr, prefix + headerLength + payloadLength + suffix);
88 Stream_Zero(s, prefix);
89 Stream_Write_UINT8(s, 3);
90 Stream_Write_UINT8(s, 0);
91 Stream_Write_UINT16_BE(s, (UINT16)(headerLength + payloadLength));
92 Stream_Write_UINT8(s, 2);
93 Stream_Write_UINT8(s, 0xF0);
94 Stream_Write_UINT8(s, 0x80);
95 Stream_Write_UINT8(s, serverMode ? 0x64 : 0x68);
96 Stream_Write_UINT16_BE(s, 1);
97 Stream_Write_UINT16_BE(s, MCS_GLOBAL_CHANNEL_ID);
98 Stream_Write_UINT8(s, 0x70);
100 Stream_Write_UINT16_BE(s, declaredLength | 0x8000);
102 Stream_Write_UINT8(s, (BYTE)declaredLength);
103 Stream_Write(s, payload, payloadLength);
104 Stream_Zero(s, suffix);
105 Stream_SealLength(s);
106 if (!Stream_SetPosition(s, prefix))
108 Stream_Free(s, TRUE);
115static BOOL test_mcs_headers(
void)
123 } cases[] = { { 0, 0, FALSE, TRUE }, { 1, 1, FALSE, TRUE }, { 26, 26, FALSE, TRUE },
124 { 127, 127, FALSE, TRUE }, { 127, 127, TRUE, TRUE }, { 128, 128, TRUE, TRUE },
125 { 386, 386, TRUE, TRUE }, { 26, 25, FALSE, FALSE }, { 26, 27, FALSE, FALSE },
126 { 386, 130, TRUE, FALSE }, { 386, 387, TRUE, FALSE }, { 0, 1, FALSE, FALSE },
127 { 1, 0, FALSE, FALSE } };
128 BYTE body[386] = WINPR_C_ARRAY_INIT;
130 freerdp* instance = new_client();
133 rdpRdp* rdp = instance->context->rdp;
134 for (
size_t server = 0; server < 2; server++)
139 for (
size_t embedding = 0; embedding < 2; embedding++)
141 const size_t prefix = embedding ? 7 : 0;
142 const size_t suffix = embedding ? 29 : 0;
143 for (
size_t x = 0; x < ARRAYSIZE(cases); x++)
147 wStream* s = packet(body, cases[x].actual, cases[x].declared, (BOOL)server,
148 cases[x].longLength, prefix, suffix);
154 const BOOL result = rdp_read_header(rdp, s, &length, &channel);
155 if ((result != cases[x].valid) ||
156 (result && ((length != cases[x].actual) || (channel != MCS_GLOBAL_CHANNEL_ID) ||
157 (Stream_GetRemainingLength(s) != cases[x].actual + suffix))))
159 (void)fprintf(stderr,
160 "MCS framing case %zu, server=%zu, embedding=%zu failed\n", x,
164 Stream_Free(s, TRUE);
170 free_client(instance);
177static BOOL setup_security(rdpRdp* rdp, TestSecurity security)
179 static const BYTE iv[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };
181 security != TEST_TLS))
183 if (security < TEST_RC4)
186 if (security == TEST_RC4)
189 ENCRYPTION_METHOD_128BIT))
191 rdp->rc4_key_len = 16;
192 memset(rdp->sign_key, 0x3A,
sizeof(rdp->sign_key));
193 for (
size_t x = 0; x <
sizeof(rdp->encrypt_key); x++)
194 rdp->encrypt_key[x] = rdp->decrypt_key[x] = (BYTE)(x + 1);
195 return rdp_reset_rc4_encrypt_keys(rdp) && rdp_reset_rc4_decrypt_keys(rdp);
199 ENCRYPTION_METHOD_FIPS))
201 memset(rdp->fips_sign_key, 0x3A,
sizeof(rdp->fips_sign_key));
202 for (
size_t x = 0; x <
sizeof(rdp->fips_encrypt_key); x++)
203 rdp->fips_encrypt_key[x] = rdp->fips_decrypt_key[x] = (BYTE)(x + 1);
205 winpr_Cipher_NewEx(WINPR_CIPHER_DES_EDE3_CBC, WINPR_ENCRYPT, rdp->fips_encrypt_key,
206 sizeof(rdp->fips_encrypt_key), iv,
sizeof(iv));
208 winpr_Cipher_NewEx(WINPR_CIPHER_DES_EDE3_CBC, WINPR_DECRYPT, rdp->fips_decrypt_key,
209 sizeof(rdp->fips_decrypt_key), iv,
sizeof(iv));
210 return rdp->fips_encrypt && rdp->fips_decrypt;
213WINPR_ATTR_MALLOC(Stream_Free, 1)
214static
wStream* protect(rdpRdp* rdp, TestSecurity security, const BYTE* data,
size_t length)
216 BYTE signature[8] = WINPR_C_ARRAY_INIT;
217 const size_t pad = (security == TEST_FIPS) ? (8 - length % 8) % 8 : 0;
218 wStream* s = Stream_New(
nullptr, length + 24);
219 if (!s || !setup_security(rdp, security))
221 if (security != TEST_TLS)
223 Stream_Write_UINT16(s, security >= TEST_RC4 ? SEC_ENCRYPT : 0);
224 Stream_Write_UINT16(s, 0);
226 if (security == TEST_FIPS)
228 Stream_Write_UINT16(s, 0x10);
229 Stream_Write_UINT8(s, 1);
230 Stream_Write_UINT8(s, (BYTE)pad);
231 if (!security_hmac_signature(data, length, signature,
sizeof(signature), rdp))
234 else if (security == TEST_RC4)
236 if (!security_mac_signature(rdp, data, (UINT32)length, signature,
sizeof(signature)))
239 if (security >= TEST_RC4)
240 Stream_Write(s, signature,
sizeof(signature));
242 BYTE* encrypted = Stream_Pointer(s);
243 Stream_Write(s, data, length);
245 if ((security == TEST_RC4) && !security_encrypt(encrypted, length, rdp))
247 if ((security == TEST_FIPS) && !security_fips_encrypt(encrypted, length + pad, rdp))
249 Stream_SealLength(s);
252 Stream_Free(s, TRUE);
257static BOOL test_demand_active(TestSecurity security,
int shareDelta,
int mcsDelta)
262 BYTE data[
sizeof(demandActive)] = WINPR_C_ARRAY_INIT;
263 freerdp* instance = new_client();
266 rdpRdp* rdp = instance->context->rdp;
267 memcpy(data, demandActive,
sizeof(data));
268 data[0] = (BYTE)(
sizeof(data) + shareDelta);
269 protected = protect(rdp, security, data,
sizeof(data));
272 const size_t length = Stream_Length(
protected);
273 s = packet(Stream_Buffer(
protected), length, (UINT16)((
int)length + mcsDelta), FALSE, FALSE, 0,
277 const state_run_t result = rdp_client_connect_demand_active(rdp, s);
278 if ((shareDelta == 0) && (mcsDelta == 0))
280 ok = (result == STATE_RUN_ACTIVE) && (Stream_GetRemainingLength(s) == 0) &&
283 if (security >= TEST_RC4)
284 ok = ok && (rdp->decrypt_use_count == 1);
286 if (security == TEST_FIPS)
287 ok = ok && (Stream_Length(s) == length + 14 - 2);
290 ok = state_run_failed(result);
293 (void)fprintf(stderr,
"Demand Active security=%d, share delta=%d, MCS delta=%d failed\n",
294 security, shareDelta, mcsDelta);
295 Stream_Free(s, TRUE);
296 Stream_Free(
protected, TRUE);
297 free_client(instance);
302static BOOL test_share_compatibility(TestSecurity security, BOOL deactivate, BOOL demandState)
305 BYTE payload[
sizeof(flowResponse) * 2 +
sizeof(shortDeactivate)] = WINPR_C_ARRAY_INIT;
306 size_t length =
sizeof(flowResponse);
309 freerdp* instance = new_client();
312 rdpRdp* rdp = instance->context->rdp;
313 memcpy(payload, flowResponse,
sizeof(flowResponse));
317 memcpy(payload + length, flowResponse,
sizeof(flowResponse));
318 length +=
sizeof(flowResponse);
321 memcpy(payload + length, shortDeactivate,
sizeof(shortDeactivate));
322 length +=
sizeof(shortDeactivate);
325 protected = protect(rdp, security, payload, length);
328 s = packet(Stream_Buffer(
protected), Stream_Length(
protected), (UINT16)Stream_Length(
protected),
332 state_run_t result = STATE_RUN_FAILED;
334 result = rdp_client_connect_demand_active(rdp, s);
337 rdp->state = CONNECTION_STATE_ACTIVE;
338 result = rdp_recv_callback(rdp->transport, s, rdp);
340 ok = state_run_success(result) && (Stream_GetRemainingLength(s) == 0);
343 ok = ok && (rdp->inPackets == (deactivate ? 3 : 2));
345 ok = ok && (rdp->state == CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
349 (void)fprintf(stderr,
350 "Share compatibility security=%d, deactivate=%d, demand state=%d failed\n",
351 security, deactivate, demandState);
352 Stream_Free(s, TRUE);
353 Stream_Free(
protected, TRUE);
354 free_client(instance);
358int TestRdpPacketLengths(WINPR_ATTR_UNUSED
int argc, WINPR_ATTR_UNUSED
char* argv[])
360 if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT))
362 BOOL ok = test_mcs_headers();
363 for (TestSecurity security = TEST_TLS; security <= TEST_FIPS; security++)
365 for (
int delta = -1; delta <= 1; delta++)
367 if (!test_demand_active(security, delta, 0))
369 if ((delta != 0) && !test_demand_active(security, 0, delta))
372 if (!test_share_compatibility(security, FALSE, FALSE) ||
373 !test_share_compatibility(security, TRUE, FALSE) ||
374 !test_share_compatibility(security, FALSE, TRUE))
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.