From 135503612d3dc0c0cb41dd197d0dfade3d9fc382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 18 Dec 2011 15:15:48 -0500 Subject: [PATCH] libfreerdp-core: fix race condition in connection finalization --- libfreerdp-core/activation.c | 17 +++++++++++++---- libfreerdp-core/connection.c | 14 +++++++++++--- libfreerdp-core/connection.h | 2 ++ libfreerdp-core/rdp.c | 7 +++++++ libfreerdp-core/rdp.h | 7 +++++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/libfreerdp-core/activation.c b/libfreerdp-core/activation.c index a6efb74cf..4b7937609 100644 --- a/libfreerdp-core/activation.c +++ b/libfreerdp-core/activation.c @@ -38,6 +38,7 @@ void rdp_write_synchronize_pdu(STREAM* s, rdpSettings* settings) boolean rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s) { + rdp->finalize_sc_pdus |= FINALIZE_SC_SYNCHRONIZE_PDU; return true; } @@ -48,7 +49,6 @@ boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp) s = rdp_data_pdu_init(rdp); rdp_write_synchronize_pdu(s, rdp->settings); - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SYNCHRONIZE, rdp->mcs->user_id); return true; @@ -105,6 +105,17 @@ boolean rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s) rdp_recv_control_pdu(s, &action); + switch (action) + { + case CTRLACTION_COOPERATE: + rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_COOPERATE_PDU; + break; + + case CTRLACTION_GRANTED_CONTROL: + rdp->finalize_sc_pdus |= FINALIZE_SC_CONTROL_GRANTED_PDU; + break; + } + return true; } @@ -143,7 +154,6 @@ boolean rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action) STREAM* s; s = rdp_data_pdu_init(rdp); - rdp_write_client_control_pdu(s, action); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_CONTROL, rdp->mcs->user_id); @@ -179,7 +189,6 @@ boolean rdp_send_client_persistent_key_list_pdu(rdpRdp* rdp) STREAM* s; s = rdp_data_pdu_init(rdp); - rdp_write_client_persistent_key_list_pdu(s, rdp->settings); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_BITMAP_CACHE_PERSISTENT_LIST, rdp->mcs->user_id); @@ -206,7 +215,6 @@ boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags) STREAM* s; s = rdp_data_pdu_init(rdp); - rdp_write_client_font_list_pdu(s, flags); return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_FONT_LIST, rdp->mcs->user_id); @@ -214,6 +222,7 @@ boolean rdp_send_client_font_list_pdu(rdpRdp* rdp, uint16 flags) boolean rdp_recv_server_font_map_pdu(rdpRdp* rdp, STREAM* s) { + rdp->finalize_sc_pdus |= FINALIZE_SC_FONT_MAP_PDU; return true; } diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index b12ece210..66dbe955f 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -97,6 +97,7 @@ boolean rdp_client_connect(rdpRdp* rdp) rdp_set_blocking_mode(rdp, false); rdp->state = CONNECTION_STATE_NEGO; + rdp->finalize_sc_pdus = 0; if (mcs_send_connect_initial(rdp->mcs) != true) { @@ -390,6 +391,16 @@ boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) IFCALL(rdp->update->DesktopResize, rdp->update->context); } + rdp->state = CONNECTION_STATE_FINALIZATION; + update_reset_state(rdp->update); + + rdp_client_connect_finalize(rdp); + + return true; +} + +boolean rdp_client_connect_finalize(rdpRdp* rdp) +{ /** * [MS-RDPBCGR] 1.3.1.1 - 8. * The client-to-server PDUs sent during this phase have no dependencies on any of the server-to- @@ -407,9 +418,6 @@ boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s) if (!rdp_send_client_font_list_pdu(rdp, FONTLIST_FIRST | FONTLIST_LAST)) return false; - rdp->state = CONNECTION_STATE_ACTIVE; - update_reset_state(rdp->update); - return true; } diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index cceee5475..ebcae1f7b 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -41,6 +41,7 @@ enum CONNECTION_STATE CONNECTION_STATE_MCS_CHANNEL_JOIN, CONNECTION_STATE_LICENSE, CONNECTION_STATE_CAPABILITY, + CONNECTION_STATE_FINALIZATION, CONNECTION_STATE_ACTIVE }; @@ -51,6 +52,7 @@ boolean rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_license(rdpRdp* rdp, STREAM* s); boolean rdp_client_connect_demand_active(rdpRdp* rdp, STREAM* s); +boolean rdp_client_connect_finalize(rdpRdp* rdp); boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s); diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 3b1d7c859..08dc2ec99 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -760,6 +760,13 @@ static boolean rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra } break; + case CONNECTION_STATE_FINALIZATION: + if (!rdp_recv_pdu(rdp, s)) + return false; + if (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE) + rdp->state = CONNECTION_STATE_ACTIVE; + break; + case CONNECTION_STATE_ACTIVE: if (!rdp_recv_pdu(rdp, s)) return false; diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 7cc0c7757..7630b7032 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -71,6 +71,12 @@ #define PDU_TYPE_DATA 0x7 #define PDU_TYPE_SERVER_REDIRECTION 0xA +#define FINALIZE_SC_SYNCHRONIZE_PDU 0x01 +#define FINALIZE_SC_CONTROL_COOPERATE_PDU 0x02 +#define FINALIZE_SC_CONTROL_GRANTED_PDU 0x04 +#define FINALIZE_SC_FONT_MAP_PDU 0x08 +#define FINALIZE_SC_COMPLETE 0x0F + /* Data PDU Types */ #define DATA_PDU_TYPE_UPDATE 0x02 #define DATA_PDU_TYPE_CONTROL 0x14 @@ -147,6 +153,7 @@ struct rdp_rdp uint8 fips_encrypt_key[24]; uint8 fips_decrypt_key[24]; uint32 errorInfo; + uint32 finalize_sc_pdus; }; void rdp_read_security_header(STREAM* s, uint16* flags);