From 23281121bf3f895d5c85a65e00710235a4699f32 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 20 Jan 2023 09:03:16 +0100 Subject: [PATCH] [core] implement skip channel join --- libfreerdp/core/connection.c | 114 +++++++++++++++++++++++------------ libfreerdp/core/connection.h | 2 + libfreerdp/core/gcc.c | 9 ++- libfreerdp/core/rdp.c | 26 +++++--- libfreerdp/core/settings.c | 2 + 5 files changed, 100 insertions(+), 53 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 00568b7b9..488481b36 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -952,6 +952,54 @@ end: return ret; } +static BOOL rdp_client_send_client_info_and_change_state(rdpRdp* rdp) +{ + WINPR_ASSERT(rdp); + if (!rdp_client_establish_keys(rdp)) + return FALSE; + if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE)) + return FALSE; + if (!rdp_send_client_info(rdp)) + return FALSE; + if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST)) + return FALSE; + return TRUE; +} + +BOOL rdp_client_skip_mcs_channel_join(rdpRdp* rdp) +{ + WINPR_ASSERT(rdp); + + rdpMcs* mcs = rdp->mcs; + WINPR_ASSERT(mcs); + + mcs->userChannelJoined = TRUE; + mcs->globalChannelJoined = TRUE; + mcs->messageChannelJoined = TRUE; + + for (UINT32 i = 0; i < mcs->channelCount; i++) + { + rdpMcsChannel* cur = &mcs->channels[i]; + cur->joined = TRUE; + } + + return rdp_client_send_client_info_and_change_state(rdp); +} + +static BOOL rdp_client_join_channel(rdpRdp* rdp, UINT16 ChannelId) +{ + WINPR_ASSERT(rdp); + + rdpMcs* mcs = rdp->mcs; + if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + return FALSE; + if (!mcs_send_channel_join_request(mcs, ChannelId)) + return FALSE; + if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) + return FALSE; + return TRUE; +} + BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) { UINT32 i; @@ -968,12 +1016,7 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) return FALSE; mcs->userChannelJoined = TRUE; - - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) - return FALSE; - if (!mcs_send_channel_join_request(mcs, MCS_GLOBAL_CHANNEL_ID)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) + if (!rdp_client_join_channel(rdp, MCS_GLOBAL_CHANNEL_ID)) return FALSE; } else if (!mcs->globalChannelJoined) @@ -985,13 +1028,8 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) if (mcs->messageChannelId != 0) { - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + if (!rdp_client_join_channel(rdp, mcs->messageChannelId)) return FALSE; - if (!mcs_send_channel_join_request(mcs, mcs->messageChannelId)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) - return FALSE; - allJoined = FALSE; } else @@ -999,14 +1037,8 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) if (mcs->channelCount > 0) { const rdpMcsChannel* cur = &mcs->channels[0]; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + if (!rdp_client_join_channel(rdp, cur->ChannelId)) return FALSE; - if (!mcs_send_channel_join_request(mcs, cur->ChannelId)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, - CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) - return FALSE; - allJoined = FALSE; } } @@ -1021,13 +1053,8 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) if (mcs->channelCount > 0) { const rdpMcsChannel* cur = &mcs->channels[0]; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + if (!rdp_client_join_channel(rdp, cur->ChannelId)) return FALSE; - if (!mcs_send_channel_join_request(mcs, cur->ChannelId)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) - return FALSE; - allJoined = FALSE; } } @@ -1049,27 +1076,15 @@ BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) if (i + 1 < mcs->channelCount) { const rdpMcsChannel* cur = &mcs->channels[i + 1]; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + if (!rdp_client_join_channel(rdp, cur->ChannelId)) return FALSE; - if (!mcs_send_channel_join_request(mcs, cur->ChannelId)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) - return FALSE; - allJoined = FALSE; } } if (mcs->userChannelJoined && mcs->globalChannelJoined && allJoined) { - if (!rdp_client_establish_keys(rdp)) - return FALSE; - - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE)) - return FALSE; - if (!rdp_send_client_info(rdp)) - return FALSE; - if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_CONNECT_TIME_AUTO_DETECT_REQUEST)) + if (!rdp_client_send_client_info_and_change_state(rdp)) return FALSE; } @@ -1477,6 +1492,25 @@ BOOL rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, wStream* s) return rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER); } +static BOOL rdp_server_skip_mcs_channel_join(rdpRdp* rdp) +{ + WINPR_ASSERT(rdp); + + rdpMcs* mcs = rdp->mcs; + WINPR_ASSERT(mcs); + + mcs->userChannelJoined = TRUE; + mcs->globalChannelJoined = TRUE; + mcs->messageChannelJoined = TRUE; + + for (UINT32 i = 0; i < mcs->channelCount; i++) + { + rdpMcsChannel* cur = &mcs->channels[i]; + cur->joined = TRUE; + } + return rdp_server_transition_to_state(rdp, CONNECTION_STATE_SECURE_SETTINGS_EXCHANGE); +} + BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s) { if (!mcs_recv_attach_user_request(rdp->mcs, s)) @@ -1488,6 +1522,8 @@ BOOL rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, wStream* s) if (!mcs_send_attach_user_confirm(rdp->mcs)) return FALSE; + if (freerdp_settings_get_bool(rdp->settings, FreeRDP_SupportSkipChannelJoin)) + return rdp_server_skip_mcs_channel_join(rdp); return rdp_server_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST); } diff --git a/libfreerdp/core/connection.h b/libfreerdp/core/connection.h index c84cefee5..291ea262d 100644 --- a/libfreerdp/core/connection.h +++ b/libfreerdp/core/connection.h @@ -43,6 +43,8 @@ FREERDP_LOCAL BOOL rdp_client_disconnect(rdpRdp* rdp); FREERDP_LOCAL BOOL rdp_client_disconnect_and_clear(rdpRdp* rdp); FREERDP_LOCAL BOOL rdp_client_reconnect(rdpRdp* rdp); FREERDP_LOCAL BOOL rdp_client_redirect(rdpRdp* rdp); + +FREERDP_LOCAL BOOL rdp_client_skip_mcs_channel_join(rdpRdp* rdp); FREERDP_LOCAL BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s); FREERDP_LOCAL BOOL rdp_client_connect_auto_detect(rdpRdp* rdp, wStream* s); FREERDP_LOCAL state_run_t rdp_client_connect_license(rdpRdp* rdp, wStream* s); diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index eb6e7192d..e3f967514 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -857,8 +857,7 @@ static UINT32 filterAndLogEarlyServerCapabilityFlags(UINT32 flags) { const UINT32 mask = (RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V1 | RNS_UD_SC_DYNAMIC_DST_SUPPORTED | - RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2); // TODO: Not implemented - // RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED + RNS_UD_SC_EDGE_ACTIONS_SUPPORTED_V2 | RNS_UD_SC_SKIP_CHANNELJOIN_SUPPORTED); const UINT32 filtered = flags & mask; const UINT32 unknown = flags & (~mask); if (unknown != 0) @@ -896,8 +895,8 @@ static UINT16 filterAndLogEarlyClientCapabilityFlags(UINT32 flags) RNS_UD_CS_SUPPORT_STATUSINFO_PDU | RNS_UD_CS_STRONG_ASYMMETRIC_KEYS | RNS_UD_CS_VALID_CONNECTION_TYPE | RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU | RNS_UD_CS_SUPPORT_NETCHAR_AUTODETECT | RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL | - RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE | - RNS_UD_CS_SUPPORT_HEARTBEAT_PDU); // unsupported RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN + RNS_UD_CS_SUPPORT_DYNAMIC_TIME_ZONE | RNS_UD_CS_SUPPORT_HEARTBEAT_PDU | + RNS_UD_CS_SUPPORT_SKIP_CHANNELJOIN); const UINT32 filtered = flags & mask; const UINT32 unknown = flags & ~mask; if (unknown != 0) @@ -2033,7 +2032,7 @@ BOOL gcc_read_server_network_data(wStream* s, rdpMcs* mcs) if (!Stream_CheckAndLogRequiredLength(TAG, s, 2ull * channelCount)) return FALSE; - for (i = 0; i < parsedChannelCount; i++) + for (UINT32 i = 0; i < parsedChannelCount; i++) { rdpMcsChannel* channel = &mcs->channels[i]; Stream_Read_UINT16(s, channelId); /* channelId */ diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 72918e99a..f3ae3faa6 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1793,17 +1793,25 @@ static state_run_t rdp_recv_callback_int(rdpTransport* transport, wStream* s, vo WLog_ERR(TAG, "mcs_recv_attach_user_confirm failure"); status = STATE_RUN_FAILED; } - else if (!rdp_client_transition_to_state(rdp, - CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) - status = STATE_RUN_FAILED; - else if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId)) + else if (!freerdp_settings_get_bool(rdp->settings, FreeRDP_SupportSkipChannelJoin)) { - WLog_ERR(TAG, "mcs_send_channel_join_request failure"); - status = STATE_RUN_FAILED; + if (!rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_REQUEST)) + status = STATE_RUN_FAILED; + else if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId)) + { + WLog_ERR(TAG, "mcs_send_channel_join_request failure"); + status = STATE_RUN_FAILED; + } + else if (!rdp_client_transition_to_state( + rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) + status = STATE_RUN_FAILED; + } + else + { + /* SKIP_CHANNELJOIN is active, consider channels to be joined */ + if (!rdp_client_skip_mcs_channel_join(rdp)) + status = STATE_RUN_FAILED; } - else if (!rdp_client_transition_to_state(rdp, - CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE)) - status = STATE_RUN_FAILED; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN_RESPONSE: diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 4656aaa64..10f94959c 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -754,6 +754,8 @@ rdpSettings* freerdp_settings_new(DWORD flags) goto out_fail; } } + if (!freerdp_settings_set_bool(settings, FreeRDP_SupportSkipChannelJoin, TRUE)) + goto out_fail; return settings; out_fail: