1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Activation Sequence
4 *
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.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 "activation.h"
25 #include "display.h"
26
27 #define TAG FREERDP_TAG("core.activation")
28
29 /*
30 static const char* const CTRLACTION_STRINGS[] =
31 {
32 "",
33 "CTRLACTION_REQUEST_CONTROL",
34 "CTRLACTION_GRANTED_CONTROL",
35 "CTRLACTION_DETACH",
36 "CTRLACTION_COOPERATE"
37 };
38 */
39 static BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s);
40 static BOOL rdp_recv_client_font_list_pdu(wStream* s);
41 static BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s);
42 static BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s);
43 static BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s);
44 static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
45
rdp_write_synchronize_pdu(wStream * s,rdpSettings * settings)46 static BOOL rdp_write_synchronize_pdu(wStream* s, rdpSettings* settings)
47 {
48 if (Stream_GetRemainingCapacity(s) < 4)
49 return FALSE;
50 Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC); /* messageType (2 bytes) */
51 Stream_Write_UINT16(s, settings->PduSource); /* targetUser (2 bytes) */
52 return TRUE;
53 }
54
rdp_recv_synchronize_pdu(rdpRdp * rdp,wStream * s)55 BOOL rdp_recv_synchronize_pdu(rdpRdp* rdp, wStream* s)
56 {
57 if (rdp->settings->ServerMode)
58 return rdp_recv_server_synchronize_pdu(rdp, s);
59 else
60 return rdp_recv_client_synchronize_pdu(rdp, s);
61 }
62
rdp_recv_server_synchronize_pdu(rdpRdp * rdp,wStream * s)63 BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp, wStream* s)
64 {
65 rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
66 return TRUE;
67 }
68
rdp_send_server_synchronize_pdu(rdpRdp * rdp)69 BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
70 {
71 wStream* s = rdp_data_pdu_init(rdp);
72 if (!s)
73 return FALSE;
74 if (!rdp_write_synchronize_pdu(s, rdp->settings))
75 {
76 Stream_Free(s, TRUE);
77 return FALSE;
78 }
79 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
80 }
81
rdp_recv_client_synchronize_pdu(rdpRdp * rdp,wStream * s)82 BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp, wStream* s)
83 {
84 UINT16 messageType;
85 rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU;
86
87 if (Stream_GetRemainingLength(s) < 4)
88 return FALSE;
89
90 Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
91
92 if (messageType != SYNCMSGTYPE_SYNC)
93 return FALSE;
94
95 /* targetUser (2 bytes) */
96 Stream_Seek_UINT16(s);
97 return TRUE;
98 }
99
rdp_send_client_synchronize_pdu(rdpRdp * rdp)100 BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
101 {
102 wStream* s = rdp_data_pdu_init(rdp);
103 if (!s)
104 return FALSE;
105 if (!rdp_write_synchronize_pdu(s, rdp->settings))
106 {
107 Stream_Free(s, TRUE);
108 return FALSE;
109 }
110 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
111 }
112
rdp_recv_control_pdu(wStream * s,UINT16 * action)113 static BOOL rdp_recv_control_pdu(wStream* s, UINT16* action)
114 {
115 if (Stream_GetRemainingLength(s) < 8)
116 return FALSE;
117
118 Stream_Read_UINT16(s, *action); /* action (2 bytes) */
119 Stream_Seek_UINT16(s); /* grantId (2 bytes) */
120 Stream_Seek_UINT32(s); /* controlId (4 bytes) */
121 return TRUE;
122 }
123
rdp_write_client_control_pdu(wStream * s,UINT16 action)124 static BOOL rdp_write_client_control_pdu(wStream* s, UINT16 action)
125 {
126 if (Stream_GetRemainingCapacity(s) < 8)
127 return FALSE;
128 Stream_Write_UINT16(s, action); /* action (2 bytes) */
129 Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
130 Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
131 return TRUE;
132 }
133
rdp_recv_server_control_pdu(rdpRdp * rdp,wStream * s)134 BOOL rdp_recv_server_control_pdu(rdpRdp* rdp, wStream* s)
135 {
136 UINT16 action;
137
138 if (rdp_recv_control_pdu(s, &action) == FALSE)
139 return FALSE;
140
141 switch (action)
142 {
143 case CTRLACTION_COOPERATE:
144 rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU;
145 break;
146
147 case CTRLACTION_GRANTED_CONTROL:
148 rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU;
149 rdp->resendFocus = TRUE;
150 break;
151 }
152
153 return TRUE;
154 }
155
rdp_send_server_control_cooperate_pdu(rdpRdp * rdp)156 BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
157 {
158 wStream* s = rdp_data_pdu_init(rdp);
159 if (!s)
160 return FALSE;
161 if (Stream_GetRemainingCapacity(s) < 8)
162 {
163 Stream_Free(s, TRUE);
164 return FALSE;
165 }
166 Stream_Write_UINT16(s, CTRLACTION_COOPERATE); /* action (2 bytes) */
167 Stream_Write_UINT16(s, 0); /* grantId (2 bytes) */
168 Stream_Write_UINT32(s, 0); /* controlId (4 bytes) */
169 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
170 }
171
rdp_send_server_control_granted_pdu(rdpRdp * rdp)172 BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
173 {
174 wStream* s = rdp_data_pdu_init(rdp);
175 if (!s)
176 return FALSE;
177 if (Stream_GetRemainingCapacity(s) < 8)
178 {
179 Stream_Free(s, TRUE);
180 return FALSE;
181 }
182 Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL); /* action (2 bytes) */
183 Stream_Write_UINT16(s, rdp->mcs->userId); /* grantId (2 bytes) */
184 Stream_Write_UINT32(s, 0x03EA); /* controlId (4 bytes) */
185 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
186 }
187
rdp_send_client_control_pdu(rdpRdp * rdp,UINT16 action)188 BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
189 {
190 wStream* s = rdp_data_pdu_init(rdp);
191 if (!s)
192 return FALSE;
193 if (!rdp_write_client_control_pdu(s, action))
194 {
195 Stream_Free(s, TRUE);
196 return FALSE;
197 }
198 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
199 }
200
rdp_write_persistent_list_entry(wStream * s,UINT32 key1,UINT32 key2)201 static BOOL rdp_write_persistent_list_entry(wStream* s, UINT32 key1, UINT32 key2)
202 {
203 if (Stream_GetRemainingCapacity(s) < 8)
204 return FALSE;
205 Stream_Write_UINT32(s, key1); /* key1 (4 bytes) */
206 Stream_Write_UINT32(s, key2); /* key2 (4 bytes) */
207 return TRUE;
208 }
209
rdp_write_client_persistent_key_list_pdu(wStream * s,const rdpSettings * settings)210 static BOOL rdp_write_client_persistent_key_list_pdu(wStream* s, const rdpSettings* settings)
211 {
212 if (Stream_GetRemainingCapacity(s) < 24)
213 return FALSE;
214 Stream_Write_UINT16(s, 0); /* numEntriesCache0 (2 bytes) */
215 Stream_Write_UINT16(s, 0); /* numEntriesCache1 (2 bytes) */
216 Stream_Write_UINT16(s, 0); /* numEntriesCache2 (2 bytes) */
217 Stream_Write_UINT16(s, 0); /* numEntriesCache3 (2 bytes) */
218 Stream_Write_UINT16(s, 0); /* numEntriesCache4 (2 bytes) */
219 Stream_Write_UINT16(s, 0); /* totalEntriesCache0 (2 bytes) */
220 Stream_Write_UINT16(s, 0); /* totalEntriesCache1 (2 bytes) */
221 Stream_Write_UINT16(s, 0); /* totalEntriesCache2 (2 bytes) */
222 Stream_Write_UINT16(s, 0); /* totalEntriesCache3 (2 bytes) */
223 Stream_Write_UINT16(s, 0); /* totalEntriesCache4 (2 bytes) */
224 Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU); /* bBitMask (1 byte) */
225 Stream_Write_UINT8(s, 0); /* pad1 (1 byte) */
226 Stream_Write_UINT16(s, 0); /* pad3 (2 bytes) */
227 /* entries */
228 return TRUE;
229 }
230
rdp_send_client_persistent_key_list_pdu(rdpRdp * rdp)231 BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
232 {
233 wStream* s = rdp_data_pdu_init(rdp);
234 if (!s)
235 return FALSE;
236 if (!rdp_write_client_persistent_key_list_pdu(s, rdp->settings))
237 {
238 Stream_Free(s, TRUE);
239 return FALSE;
240 }
241 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId);
242 }
243
rdp_recv_client_font_list_pdu(wStream * s)244 BOOL rdp_recv_client_font_list_pdu(wStream* s)
245 {
246 /* 2.2.1.18 Client Font List PDU */
247 return Stream_SafeSeek(s, 8);
248 }
249
rdp_recv_client_persistent_key_list_pdu(wStream * s)250 BOOL rdp_recv_client_persistent_key_list_pdu(wStream* s)
251 {
252 BYTE flags;
253 size_t count = 0;
254 UINT16 cache, x;
255 /* 2.2.1.17.1 Persistent Key List PDU Data (TS_BITMAPCACHE_PERSISTENT_LIST_PDU) */
256 if (Stream_GetRemainingLength(s) < 21)
257 return FALSE;
258 /* Read numEntriesCacheX for variable length data in PDU */
259 for (x = 0; x < 5; x++)
260 {
261 Stream_Read_UINT16(s, cache);
262 count += cache;
263 }
264
265 /* Skip totalEntriesCacheX */
266 if (!Stream_SafeSeek(s, 10))
267 return FALSE;
268
269 Stream_Read_UINT8(s, flags);
270
271 /* Skip padding */
272 if (!Stream_SafeSeek(s, 3))
273 return FALSE;
274 /* Skip actual entries sent by client */
275 return Stream_SafeSeek(s, count * sizeof(UINT64));
276 }
277
rdp_write_client_font_list_pdu(wStream * s,UINT16 flags)278 static BOOL rdp_write_client_font_list_pdu(wStream* s, UINT16 flags)
279 {
280 if (Stream_GetRemainingCapacity(s) < 8)
281 return FALSE;
282 Stream_Write_UINT16(s, 0); /* numberFonts (2 bytes) */
283 Stream_Write_UINT16(s, 0); /* totalNumFonts (2 bytes) */
284 Stream_Write_UINT16(s, flags); /* listFlags (2 bytes) */
285 Stream_Write_UINT16(s, 50); /* entrySize (2 bytes) */
286 return TRUE;
287 }
288
rdp_send_client_font_list_pdu(rdpRdp * rdp,UINT16 flags)289 BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
290 {
291 wStream* s = rdp_data_pdu_init(rdp);
292 if (!s)
293 return FALSE;
294 if (!rdp_write_client_font_list_pdu(s, flags))
295 {
296 Stream_Free(s, TRUE);
297 return FALSE;
298 }
299 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId);
300 }
301
rdp_recv_font_map_pdu(rdpRdp * rdp,wStream * s)302 BOOL rdp_recv_font_map_pdu(rdpRdp* rdp, wStream* s)
303 {
304 if (rdp->settings->ServerMode)
305 return rdp_recv_server_font_map_pdu(rdp, s);
306 else
307 return rdp_recv_client_font_map_pdu(rdp, s);
308 }
309
rdp_recv_server_font_map_pdu(rdpRdp * rdp,wStream * s)310 BOOL rdp_recv_server_font_map_pdu(rdpRdp* rdp, wStream* s)
311 {
312 rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
313 return TRUE;
314 }
315
rdp_recv_client_font_map_pdu(rdpRdp * rdp,wStream * s)316 BOOL rdp_recv_client_font_map_pdu(rdpRdp* rdp, wStream* s)
317 {
318 rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU;
319
320 if (Stream_GetRemainingLength(s) >= 8)
321 {
322 Stream_Seek_UINT16(s); /* numberEntries (2 bytes) */
323 Stream_Seek_UINT16(s); /* totalNumEntries (2 bytes) */
324 Stream_Seek_UINT16(s); /* mapFlags (2 bytes) */
325 Stream_Seek_UINT16(s); /* entrySize (2 bytes) */
326 }
327
328 return TRUE;
329 }
330
rdp_send_server_font_map_pdu(rdpRdp * rdp)331 BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
332 {
333 wStream* s = rdp_data_pdu_init(rdp);
334 if (!s)
335 return FALSE;
336 if (Stream_GetRemainingCapacity(s) < 8)
337 {
338 Stream_Free(s, TRUE);
339 return FALSE;
340 }
341 Stream_Write_UINT16(s, 0); /* numberEntries (2 bytes) */
342 Stream_Write_UINT16(s, 0); /* totalNumEntries (2 bytes) */
343 Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST); /* mapFlags (2 bytes) */
344 Stream_Write_UINT16(s, 4); /* entrySize (2 bytes) */
345 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId);
346 }
347
rdp_recv_deactivate_all(rdpRdp * rdp,wStream * s)348 BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s)
349 {
350 UINT16 lengthSourceDescriptor;
351 UINT32 timeout;
352
353 if (rdp->state == CONNECTION_STATE_ACTIVE)
354 rdp->deactivation_reactivation = TRUE;
355 else
356 rdp->deactivation_reactivation = FALSE;
357
358 /*
359 * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain
360 * the following fields.
361 */
362 if (Stream_GetRemainingLength(s) > 0)
363 {
364 do
365 {
366 if (Stream_GetRemainingLength(s) < 4)
367 break;
368
369 Stream_Read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
370
371 if (Stream_GetRemainingLength(s) < 2)
372 break;
373
374 Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */
375
376 if (Stream_GetRemainingLength(s) < lengthSourceDescriptor)
377 break;
378
379 Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */
380 } while (0);
381 }
382
383 rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE);
384
385 for (timeout = 0; timeout < rdp->settings->TcpAckTimeout; timeout += 100)
386 {
387 if (rdp_check_fds(rdp) < 0)
388 return FALSE;
389
390 if (freerdp_shall_disconnect(rdp->instance))
391 return TRUE;
392
393 if (rdp->state == CONNECTION_STATE_ACTIVE)
394 return TRUE;
395
396 Sleep(100);
397 }
398
399 WLog_ERR(TAG, "Timeout waiting for activation");
400 return FALSE;
401 }
402
rdp_send_deactivate_all(rdpRdp * rdp)403 BOOL rdp_send_deactivate_all(rdpRdp* rdp)
404 {
405 wStream* s = rdp_send_stream_pdu_init(rdp);
406 BOOL status = FALSE;
407
408 if (!s)
409 return FALSE;
410
411 if (Stream_GetRemainingCapacity(s) < 7)
412 goto fail;
413 Stream_Write_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */
414 Stream_Write_UINT16(s, 1); /* lengthSourceDescriptor (2 bytes) */
415 Stream_Write_UINT8(s, 0); /* sourceDescriptor (should be 0x00) */
416 status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId);
417 fail:
418 Stream_Release(s);
419 return status;
420 }
421
rdp_server_accept_client_control_pdu(rdpRdp * rdp,wStream * s)422 BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp, wStream* s)
423 {
424 UINT16 action;
425
426 if (!rdp_recv_control_pdu(s, &action))
427 return FALSE;
428
429 if (action == CTRLACTION_REQUEST_CONTROL)
430 {
431 if (!rdp_send_server_control_granted_pdu(rdp))
432 return FALSE;
433 }
434
435 return TRUE;
436 }
437
rdp_server_accept_client_font_list_pdu(rdpRdp * rdp,wStream * s)438 BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp, wStream* s)
439 {
440 rdpSettings* settings = rdp->settings;
441 freerdp_peer* peer = rdp->context->peer;
442
443 if (!rdp_recv_client_font_list_pdu(s))
444 return FALSE;
445
446 if (settings->SupportMonitorLayoutPdu && settings->MonitorCount && peer->AdjustMonitorsLayout &&
447 peer->AdjustMonitorsLayout(peer))
448 {
449 /* client supports the monitorLayout PDU, let's send him the monitors if any */
450 MONITOR_DEF* monitors = (MONITOR_DEF*)calloc(settings->MonitorCount, sizeof(MONITOR_DEF));
451
452 if (!monitors)
453 return FALSE;
454
455 if (!display_convert_rdp_monitor_to_monitor_def(settings->MonitorCount,
456 settings->MonitorDefArray, &monitors))
457 {
458 free(monitors);
459 return FALSE;
460 }
461
462 if (!freerdp_display_send_monitor_layout(rdp->context, settings->MonitorCount, monitors))
463 {
464 free(monitors);
465 return FALSE;
466 }
467
468 free(monitors);
469 }
470
471 if (!rdp_send_server_font_map_pdu(rdp))
472 return FALSE;
473
474 if (rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE) < 0)
475 return FALSE;
476
477 return TRUE;
478 }
479
rdp_server_accept_client_persistent_key_list_pdu(rdpRdp * rdp,wStream * s)480 BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp, wStream* s)
481 {
482 if (!rdp_recv_client_persistent_key_list_pdu(s))
483 return FALSE;
484
485 // TODO: Actually do something with this
486 return TRUE;
487 }
488