20 #include <freerdp/config.h>
24 #include <winpr/assert.h>
26 #include "activation.h"
29 #define TAG FREERDP_TAG("core.activation")
31 static BOOL rdp_recv_client_font_list_pdu(
wStream* s);
32 static BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s);
33 static BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp);
35 static BOOL rdp_write_synchronize_pdu(
wStream* s,
const rdpSettings* settings)
39 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 4))
41 Stream_Write_UINT16(s, SYNCMSGTYPE_SYNC);
42 Stream_Write_UINT16(s, PduSource);
46 static BOOL rdp_recv_sync_pdu(rdpRdp* rdp,
wStream* s,
const char* what)
49 UINT16 targetUser = 0;
52 if (!Stream_CheckAndLogRequiredLengthEx(TAG, WLOG_WARN, s, 4, 1,
"%s(%s:%" PRIuz
") %s",
53 __func__, __FILE__, (
size_t)__LINE__, what))
55 Stream_Read_UINT16(s, msgType);
56 if (msgType != SYNCMSGTYPE_SYNC)
58 WLog_WARN(TAG,
"%s: Invalid messageType=0x%04" PRIx16
", expected 0x%04" PRIx16, what,
59 msgType, SYNCMSGTYPE_SYNC);
62 Stream_Read_UINT16(s, targetUser);
63 WLog_VRB(TAG,
"%s: targetUser=0x%04" PRIx16, what, targetUser);
67 BOOL rdp_recv_server_synchronize_pdu(rdpRdp* rdp,
wStream* s)
69 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.19 Server Synchronize PDU"))
71 return rdp_finalize_set_flag(rdp, FINALIZE_SC_SYNCHRONIZE_PDU);
74 BOOL rdp_send_server_synchronize_pdu(rdpRdp* rdp)
76 wStream* s = rdp_data_pdu_init(rdp);
81 if (!rdp_write_synchronize_pdu(s, rdp->settings))
87 WINPR_ASSERT(rdp->mcs);
88 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
91 BOOL rdp_recv_client_synchronize_pdu(rdpRdp* rdp,
wStream* s)
93 if (!rdp_recv_sync_pdu(rdp, s,
"[MS-RDPBCGR] 2.2.1.14 Client Synchronize PDU"))
95 return rdp_finalize_set_flag(rdp, FINALIZE_CS_SYNCHRONIZE_PDU);
98 BOOL rdp_send_client_synchronize_pdu(rdpRdp* rdp)
100 wStream* s = rdp_data_pdu_init(rdp);
105 if (!rdp_write_synchronize_pdu(s, rdp->settings))
107 Stream_Free(s, TRUE);
111 WINPR_ASSERT(rdp->mcs);
112 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->userId);
115 static BOOL rdp_recv_control_pdu(
wStream* s, UINT16* action, UINT16* grantId, UINT32* controlId)
118 WINPR_ASSERT(action);
119 WINPR_ASSERT(grantId);
120 WINPR_ASSERT(controlId);
122 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
125 Stream_Read_UINT16(s, *action);
126 Stream_Read_UINT16(s, *grantId);
127 Stream_Read_UINT32(s, *controlId);
131 static BOOL rdp_write_client_control_pdu(
wStream* s, UINT16 action, UINT16 grantId,
135 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
137 Stream_Write_UINT16(s, action);
138 Stream_Write_UINT16(s, grantId);
139 Stream_Write_UINT32(s, controlId);
143 BOOL rdp_recv_server_control_pdu(rdpRdp* rdp,
wStream* s)
147 UINT32 controlId = 0;
152 if (!rdp_recv_control_pdu(s, &action, &grantId, &controlId))
157 case CTRLACTION_COOPERATE:
158 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_COOPERATE_PDU);
160 case CTRLACTION_GRANTED_CONTROL:
161 rdp->resendFocus = TRUE;
162 return rdp_finalize_set_flag(rdp, FINALIZE_SC_CONTROL_GRANTED_PDU);
165 char buffer[128] = { 0 };
166 WLog_WARN(TAG,
"Unexpected control PDU %s",
167 rdp_ctrlaction_string(action, buffer,
sizeof(buffer)));
174 BOOL rdp_send_server_control_cooperate_pdu(rdpRdp* rdp)
176 wStream* s = rdp_data_pdu_init(rdp);
179 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
181 Stream_Free(s, TRUE);
184 Stream_Write_UINT16(s, CTRLACTION_COOPERATE);
185 Stream_Write_UINT16(s, 0);
186 Stream_Write_UINT32(s, 0);
188 WINPR_ASSERT(rdp->mcs);
189 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
192 BOOL rdp_send_server_control_granted_pdu(rdpRdp* rdp)
194 wStream* s = rdp_data_pdu_init(rdp);
197 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
199 Stream_Free(s, TRUE);
203 WINPR_ASSERT(rdp->mcs);
204 Stream_Write_UINT16(s, CTRLACTION_GRANTED_CONTROL);
205 Stream_Write_UINT16(s, rdp->mcs->userId);
206 Stream_Write_UINT32(s, 0x03EA);
207 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
210 BOOL rdp_send_client_control_pdu(rdpRdp* rdp, UINT16 action)
212 wStream* s = rdp_data_pdu_init(rdp);
214 UINT16 ControlId = 0;
218 case CTRLACTION_COOPERATE:
219 case CTRLACTION_REQUEST_CONTROL:
223 "Invalid client control PDU::action 0x%04" PRIx16
", not allowed by client",
230 if (!rdp_write_client_control_pdu(s, action, GrantId, ControlId))
232 Stream_Free(s, TRUE);
236 WINPR_ASSERT(rdp->mcs);
237 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->userId);
240 static BOOL rdp_write_client_persistent_key_list_pdu(
wStream* s,
246 if (!Stream_EnsureRemainingCapacity(s, 24))
249 Stream_Write_UINT16(s, info->numEntriesCache0);
250 Stream_Write_UINT16(s, info->numEntriesCache1);
251 Stream_Write_UINT16(s, info->numEntriesCache2);
252 Stream_Write_UINT16(s, info->numEntriesCache3);
253 Stream_Write_UINT16(s, info->numEntriesCache4);
254 Stream_Write_UINT16(s, info->totalEntriesCache0);
255 Stream_Write_UINT16(s, info->totalEntriesCache1);
256 Stream_Write_UINT16(s, info->totalEntriesCache2);
257 Stream_Write_UINT16(s, info->totalEntriesCache3);
258 Stream_Write_UINT16(s, info->totalEntriesCache4);
259 Stream_Write_UINT8(s, PERSIST_FIRST_PDU | PERSIST_LAST_PDU);
260 Stream_Write_UINT8(s, 0);
261 Stream_Write_UINT16(s, 0);
264 if (!Stream_EnsureRemainingCapacity(s, info->keyCount * 8ull))
267 for (UINT32 index = 0; index < info->keyCount; index++)
269 const UINT64 val = info->keyList[index];
270 Stream_Write_UINT64(s, val);
276 static UINT16 rdp_load_persistent_key_list(rdpRdp* rdp, UINT64** pKeyList)
279 UINT64* keyList = NULL;
280 rdpPersistentCache* persistent = NULL;
281 rdpSettings* settings = rdp->settings;
288 if (!settings->BitmapCachePersistFile)
291 persistent = persistent_cache_new();
297 persistent_cache_open(persistent, settings->BitmapCachePersistFile, FALSE, 0);
302 const int count = persistent_cache_get_count(persistent);
303 if ((count < 0) || (count > UINT16_MAX))
306 keyCount = (UINT16)count;
307 keyList = (UINT64*)calloc(keyCount,
sizeof(UINT64));
312 for (
int index = 0; index < count; index++)
316 if (persistent_cache_read_entry(persistent, &cacheEntry) < 1)
319 keyList[index] = cacheEntry.key64;
324 persistent_cache_free(persistent);
327 persistent_cache_free(persistent);
332 BOOL rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp)
334 UINT32 keyMaxFrag = 2042;
335 UINT64* keyList = NULL;
337 rdpSettings* settings = rdp->settings;
338 UINT32 keyCount = rdp_load_persistent_key_list(rdp, &keyList);
340 WLog_DBG(TAG,
"Persistent Key List: TotalKeyCount: %" PRIu32
" MaxKeyFrag: %" PRIu32, keyCount,
349 if (keyCount > keyMaxFrag)
350 keyCount = keyMaxFrag;
352 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[0].numEntries <= UINT16_MAX);
353 info.totalEntriesCache0 = (UINT16)settings->BitmapCacheV2CellInfo[0].numEntries;
355 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[1].numEntries <= UINT16_MAX);
356 info.totalEntriesCache1 = (UINT16)settings->BitmapCacheV2CellInfo[1].numEntries;
358 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[2].numEntries <= UINT16_MAX);
359 info.totalEntriesCache2 = (UINT16)settings->BitmapCacheV2CellInfo[2].numEntries;
361 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[3].numEntries <= UINT16_MAX);
362 info.totalEntriesCache3 = (UINT16)settings->BitmapCacheV2CellInfo[3].numEntries;
364 WINPR_ASSERT(settings->BitmapCacheV2CellInfo[4].numEntries <= UINT16_MAX);
365 info.totalEntriesCache4 = (UINT16)settings->BitmapCacheV2CellInfo[4].numEntries;
367 info.numEntriesCache0 = MIN(keyCount, info.totalEntriesCache0);
368 keyCount -= info.numEntriesCache0;
369 info.numEntriesCache1 = MIN(keyCount, info.totalEntriesCache1);
370 keyCount -= info.numEntriesCache1;
371 info.numEntriesCache2 = MIN(keyCount, info.totalEntriesCache2);
372 keyCount -= info.numEntriesCache2;
373 info.numEntriesCache3 = MIN(keyCount, info.totalEntriesCache3);
374 keyCount -= info.numEntriesCache3;
375 info.numEntriesCache4 = MIN(keyCount, info.totalEntriesCache4);
377 info.totalEntriesCache0 = info.numEntriesCache0;
378 info.totalEntriesCache1 = info.numEntriesCache1;
379 info.totalEntriesCache2 = info.numEntriesCache2;
380 info.totalEntriesCache3 = info.numEntriesCache3;
381 info.totalEntriesCache4 = info.numEntriesCache4;
383 keyCount = info.totalEntriesCache0 + info.totalEntriesCache1 + info.totalEntriesCache2 +
384 info.totalEntriesCache3 + info.totalEntriesCache4;
386 info.keyCount = keyCount;
387 info.keyList = keyList;
389 WLog_DBG(TAG,
"persistentKeyList count: %" PRIu32, info.keyCount);
392 "numEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
394 info.numEntriesCache0, info.numEntriesCache1, info.numEntriesCache2,
395 info.numEntriesCache3, info.numEntriesCache4);
398 "totalEntriesCache: [0]: %" PRIu16
" [1]: %" PRIu16
" [2]: %" PRIu16
" [3]: %" PRIu16
400 info.totalEntriesCache0, info.totalEntriesCache1, info.totalEntriesCache2,
401 info.totalEntriesCache3, info.totalEntriesCache4);
403 wStream* s = rdp_data_pdu_init(rdp);
411 if (!rdp_write_client_persistent_key_list_pdu(s, &info))
413 Stream_Free(s, TRUE);
418 WINPR_ASSERT(rdp->mcs);
421 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->userId);
424 BOOL rdp_recv_client_font_list_pdu(
wStream* s)
428 if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
431 return Stream_SafeSeek(s, 8);
434 BOOL rdp_recv_client_persistent_key_list_pdu(
wStream* s)
444 if (!Stream_CheckAndLogRequiredLength(TAG, s, 21))
446 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 21 bytes, got %" PRIuz,
447 Stream_GetRemainingLength(s));
451 for (
size_t x = 0; x < 5; x++)
453 Stream_Read_UINT16(s, cache);
458 for (
size_t x = 0; x < 5; x++)
461 Stream_Read_UINT16(s, tmp);
468 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::totalEntriesCacheX exceeds 262144 entries");
472 Stream_Read_UINT8(s, flags);
473 if ((flags & ~(PERSIST_LAST_PDU | PERSIST_FIRST_PDU)) != 0)
476 "TS_BITMAPCACHE_PERSISTENT_LIST_PDU::bBitMask has an invalid value of 0x%02" PRIx8,
482 if (!Stream_SafeSeek(s, 3))
484 WLog_ERR(TAG,
"short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need 3 bytes, got %" PRIuz,
485 Stream_GetRemainingLength(s));
489 if (!Stream_SafeSeek(s, count *
sizeof(UINT64)))
492 "short TS_BITMAPCACHE_PERSISTENT_LIST_PDU, need %" PRIuz
" bytes, got %" PRIuz,
493 count *
sizeof(UINT64), Stream_GetRemainingLength(s));
499 static BOOL rdp_write_client_font_list_pdu(
wStream* s, UINT16 flags)
503 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
505 Stream_Write_UINT16(s, 0);
506 Stream_Write_UINT16(s, 0);
507 Stream_Write_UINT16(s, flags);
508 Stream_Write_UINT16(s, 50);
512 BOOL rdp_send_client_font_list_pdu(rdpRdp* rdp, UINT16 flags)
514 wStream* s = rdp_data_pdu_init(rdp);
517 if (!rdp_write_client_font_list_pdu(s, flags))
519 Stream_Free(s, TRUE);
523 WINPR_ASSERT(rdp->mcs);
524 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->userId);
527 BOOL rdp_recv_font_map_pdu(rdpRdp* rdp,
wStream* s)
529 UINT16 numberEntries = 0;
530 UINT16 totalNumEntries = 0;
532 UINT16 entrySize = 0;
535 WINPR_ASSERT(rdp->settings);
540 if (Stream_CheckAndLogRequiredLength(TAG, s, 8))
542 Stream_Read_UINT16(s, numberEntries);
543 if (numberEntries != 0)
546 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::numberEntries != 0 "
549 Stream_Read_UINT16(s, totalNumEntries);
550 if (totalNumEntries != 0)
553 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::totalNumEntries != "
556 Stream_Read_UINT16(s, mapFlags);
557 if (mapFlags != (FONTLIST_FIRST | FONTLIST_LAST))
560 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::mapFlags != 0x0003 "
561 "(FONTLIST_FIRST | FONTLIST_LAST) "
564 Stream_Read_UINT16(s, entrySize);
567 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU)::entrySize != 4 "
573 "[MS-RDPBCGR] 2.2.1.22.1 Font Map PDU Data (TS_FONT_MAP_PDU) paylaod size is "
576 return rdp_finalize_set_flag(rdp, FINALIZE_SC_FONT_MAP_PDU);
579 BOOL rdp_send_server_font_map_pdu(rdpRdp* rdp)
581 wStream* s = rdp_data_pdu_init(rdp);
584 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 8))
586 Stream_Free(s, TRUE);
589 Stream_Write_UINT16(s, 0);
590 Stream_Write_UINT16(s, 0);
591 Stream_Write_UINT16(s, FONTLIST_FIRST | FONTLIST_LAST);
592 Stream_Write_UINT16(s, 4);
594 WINPR_ASSERT(rdp->mcs);
595 return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_MAP, rdp->mcs->userId);
598 BOOL rdp_recv_deactivate_all(rdpRdp* rdp,
wStream* s)
600 UINT16 lengthSourceDescriptor = 0;
605 if (rdp_get_state(rdp) == CONNECTION_STATE_ACTIVE)
607 if (!rdp_finalize_set_flag(rdp, FINALIZE_DEACTIVATE_REACTIVATE))
610 rdp->was_deactivated = TRUE;
620 WINPR_ASSERT(rdp->settings);
621 if (Stream_GetRemainingLength(s) > 0)
626 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
629 Stream_Read_UINT32(s, ShareId);
633 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
636 Stream_Read_UINT16(s, lengthSourceDescriptor);
638 if (!Stream_CheckAndLogRequiredLength(TAG, s, lengthSourceDescriptor))
641 Stream_Seek(s, lengthSourceDescriptor);
645 return rdp_client_transition_to_state(rdp,
646 CONNECTION_STATE_CAPABILITIES_EXCHANGE_DEMAND_ACTIVE);
649 BOOL rdp_send_deactivate_all(rdpRdp* rdp)
651 wStream* s = rdp_send_stream_pdu_init(rdp);
657 if (!Stream_CheckAndLogRequiredCapacity(TAG, (s), 7))
660 WINPR_ASSERT(rdp->settings);
662 Stream_Write_UINT32(s, ShareId);
663 Stream_Write_UINT16(s, 1);
664 Stream_Write_UINT8(s, 0);
666 WINPR_ASSERT(rdp->mcs);
667 status = rdp_send_pdu(rdp, s, PDU_TYPE_DEACTIVATE_ALL, rdp->mcs->userId);
673 BOOL rdp_server_accept_client_control_pdu(rdpRdp* rdp,
wStream* s)
677 UINT32 ControlId = 0;
678 const CONNECTION_STATE state = rdp_get_state(rdp);
683 if (!rdp_recv_control_pdu(s, &action, &GrantId, &ControlId))
689 case CTRLACTION_REQUEST_CONTROL:
690 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU))
692 char abuffer[128] = { 0 };
693 char buffer[1024] = { 0 };
695 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
696 " in unexpected state %s [missing %s]",
697 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId,
698 ControlId, rdp_state_string(state),
699 rdp_finalize_flags_to_str(FINALIZE_CS_CONTROL_COOPERATE_PDU, buffer,
703 if ((GrantId != 0) || (ControlId != 0))
706 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
707 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
711 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_REQUEST_PDU);
712 case CTRLACTION_COOPERATE:
713 if (!rdp_finalize_is_flag_set(rdp, FINALIZE_CS_SYNCHRONIZE_PDU))
715 char abuffer[128] = { 0 };
716 char buffer[1024] = { 0 };
719 "Received action=%s with GrantId=0x%04" PRIx16
", ControlId=0x%08" PRIx32
720 " in unexpected state %s [missing %s]",
721 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId,
722 rdp_state_string(state),
723 rdp_finalize_flags_to_str(FINALIZE_CS_SYNCHRONIZE_PDU, buffer,
sizeof(buffer)));
726 if ((GrantId != 0) || (ControlId != 0))
729 "Received CTRLACTION_COOPERATE with GrantId=0x%04" PRIx16
730 " != 0x00, ControlId=0x%08" PRIx32
" != 0x00",
734 return rdp_finalize_set_flag(rdp, FINALIZE_CS_CONTROL_COOPERATE_PDU);
737 char abuffer[128] = { 0 };
739 "Received unexpected action=%s with GrantId=0x%04" PRIx16
740 ", ControlId=0x%08" PRIx32,
741 rdp_ctrlaction_string(action, abuffer,
sizeof(abuffer)), GrantId, ControlId);
749 BOOL rdp_server_accept_client_font_list_pdu(rdpRdp* rdp,
wStream* s)
751 rdpSettings* settings = NULL;
752 freerdp_peer* peer = NULL;
757 settings = rdp->settings;
758 WINPR_ASSERT(settings);
760 WINPR_ASSERT(rdp->context);
761 peer = rdp->context->peer;
764 if (!rdp_recv_client_font_list_pdu(s))
766 rdp_finalize_set_flag(rdp, FINALIZE_CS_FONT_LIST_PDU);
768 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION_CLIENT_FONT_MAP))
771 if (!rdp_send_server_font_map_pdu(rdp))
774 if (!rdp_server_transition_to_state(rdp, CONNECTION_STATE_ACTIVE))
780 BOOL rdp_server_accept_client_persistent_key_list_pdu(rdpRdp* rdp,
wStream* s)
785 if (!rdp_recv_client_persistent_key_list_pdu(s))
788 rdp_finalize_set_flag(rdp, FINALIZE_CS_PERSISTENT_KEY_LIST_PDU);
793 const char* rdp_ctrlaction_string(UINT16 action,
char* buffer,
size_t size)
795 const char* actstr = NULL;
798 case CTRLACTION_COOPERATE:
799 actstr =
"CTRLACTION_COOPERATE";
801 case CTRLACTION_DETACH:
802 actstr =
"CTRLACTION_DETACH";
804 case CTRLACTION_GRANTED_CONTROL:
805 actstr =
"CTRLACTION_GRANTED_CONTROL";
807 case CTRLACTION_REQUEST_CONTROL:
808 actstr =
"CTRLACTION_REQUEST_CONTROL";
811 actstr =
"CTRLACTION_UNKNOWN";
815 (void)_snprintf(buffer, size,
"%s [0x%04" PRIx16
"]", actstr, action);
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets a UINT32 settings value.