From 6c337328ce50d603f0970f4ffcdb7fadacf77ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 11 Jul 2011 14:47:55 -0400 Subject: [PATCH] libfreerdp-core: fix MCS connection sequence --- libfreerdp-core/connection.c | 27 ++---- libfreerdp-core/mcs.c | 174 ++++++++++++++++++++++++++++------- libfreerdp-core/mcs.h | 5 +- 3 files changed, 148 insertions(+), 58 deletions(-) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index b25ebb8e0..f7181b5a9 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -51,9 +51,7 @@ void connection_client_connect(rdpConnection* connection) { - int i; STREAM* s; - uint16 channelId; connection->settings->autologon = 1; connection->transport = transport_new(connection->settings); @@ -69,27 +67,15 @@ void connection_client_connect(rdpConnection* connection) connection->mcs = mcs_new(connection->transport); - mcs_send_connect_initial(connection->mcs); - mcs_recv_connect_response(connection->mcs); - - mcs_send_erect_domain_request(connection->mcs); - mcs_send_attach_user_request(connection->mcs); - mcs_recv_attach_user_confirm(connection->mcs); - - mcs_send_channel_join_request(connection->mcs, connection->mcs->user_id); - mcs_recv_channel_join_confirm(connection->mcs); - - for (i = 0; i < connection->settings->num_channels; i++) - { - channelId = connection->settings->channels[i].chan_id; - mcs_send_channel_join_request(connection->mcs, channelId); - mcs_recv_channel_join_confirm(connection->mcs); - } + mcs_connect(connection->mcs); connection_send_client_info(connection); s = transport_recv_stream_init(connection->transport, 4096); transport_read(connection->transport, s); + + s = transport_recv_stream_init(connection->transport, 4096); + transport_read(connection->transport, s); } void connection_write_system_time(STREAM* s, SYSTEM_TIME* system_time) @@ -356,9 +342,8 @@ void connection_send_client_info(rdpConnection* connection) length = (em - bm); stream_set_mark(s, bm); - tpkt_write_header(s, length); - tpdu_write_data(s); - per_write_choice(s, DomainMCSPDU_SendDataRequest << 2); + mcs_write_domain_mcspdu_header(s, DomainMCSPDU_SendDataRequest, length); + per_write_integer16(s, connection->mcs->user_id, MCS_BASE_CHANNEL_ID); /* initiator */ per_write_integer16(s, MCS_GLOBAL_CHANNEL_ID, 0); /* channelId */ stream_write_uint8(s, 0x70); /* dataPriority + segmentation */ diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index 9dc1deef1..9fe96ad77 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -159,6 +159,83 @@ uint8 mcs_result_enumerated[16][32] = "rt-user-rejected" }; +/** + * MCS Connection Sequence. + * @param mcs mcs module + * @return + */ + +boolean mcs_connect(rdpMcs* mcs) +{ + int i; + uint16 channelId; + rdpSettings* settings; + + settings = mcs->transport->settings; + + mcs_send_connect_initial(mcs); + mcs_recv_connect_response(mcs); + + mcs_send_erect_domain_request(mcs); + mcs_send_attach_user_request(mcs); + mcs_recv_attach_user_confirm(mcs); + + mcs_send_channel_join_request(mcs, mcs->user_id); + mcs_recv_channel_join_confirm(mcs); + + mcs_send_channel_join_request(mcs, MCS_GLOBAL_CHANNEL_ID); + mcs_recv_channel_join_confirm(mcs); + + for (i = 0; i < settings->num_channels; i++) + { + channelId = settings->channels[i].chan_id; + mcs_send_channel_join_request(mcs, channelId); + mcs_recv_channel_join_confirm(mcs); + } + + return True; +} + +/** + * Read a DomainMCSPDU header. + * @param s stream + * @param domainMCSPDU DomainMCSPDU type + * @param length TPKT length + * @return + */ + +boolean mcs_read_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU* domainMCSPDU, int* length) +{ + uint8 choice; + enum DomainMCSPDU MCSPDU; + + *length = tpkt_read_header(s); + tpdu_read_data(s); + + MCSPDU = *domainMCSPDU; + per_read_choice(s, &choice); + *domainMCSPDU = (choice >> 2); + + if (*domainMCSPDU != MCSPDU) + return False; + + return True; +} + +/** + * Write a DomainMCSPDU header. + * @param s stream + * @param domainMCSPDU DomainMCSPDU type + * @param length TPKT length + */ + +void mcs_write_domain_mcspdu_header(STREAM* s, enum DomainMCSPDU domainMCSPDU, int length) +{ + tpkt_write_header(s, length); + tpdu_write_data(s); + per_write_choice(s, domainMCSPDU << 2); +} + /** * Initialize MCS Domain Parameters. * @param domainParameters domain parameters @@ -182,7 +259,13 @@ static void mcs_init_domain_parameters(DomainParameters* domainParameters, domainParameters->protocolVersion = 2; } -static void mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters) +/** + * Read MCS Domain Parameters. + * @param s stream + * @param domainParameters domain parameters + */ + +void mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; ber_read_sequence_of_tag(s, &length); @@ -202,7 +285,7 @@ static void mcs_read_domain_parameters(STREAM* s, DomainParameters* domainParame * @param domainParameters domain parameters */ -static void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters) +void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParameters) { int length; uint8 *bm, *em; @@ -227,6 +310,11 @@ static void mcs_write_domain_parameters(STREAM* s, DomainParameters* domainParam stream_set_mark(s, em); } +/** + * Print MCS Domain Parameters. + * @param domainParameters domain parameters + */ + void mcs_print_domain_parameters(DomainParameters* domainParameters) { printf("DomainParameters {\n"); @@ -288,6 +376,11 @@ void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data) stream_set_mark(s, em); } +/** + * Send MCS Connect Initial. + * @param mcs mcs module + */ + void mcs_send_connect_initial(rdpMcs* mcs) { STREAM* s; @@ -317,8 +410,16 @@ void mcs_send_connect_initial(rdpMcs* mcs) stream_set_mark(s, em); transport_write(mcs->transport, s); + + stream_free(gcc_CCrq); + stream_free(client_data); } +/** + * Receive MCS Connect Response. + * @param mcs mcs module + */ + void mcs_recv_connect_response(rdpMcs* mcs) { STREAM* s; @@ -343,107 +444,110 @@ void mcs_recv_connect_response(rdpMcs* mcs) gcc_read_conference_create_response(s, mcs->transport->settings); } +/** + * Send MCS Erect Domain Request. + * @param mcs + */ + void mcs_send_erect_domain_request(rdpMcs* mcs) { STREAM* s; int length = 12; s = transport_send_stream_init(mcs->transport, length); - tpkt_write_header(s, length); - tpdu_write_data(s); + mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ErectDomainRequest, length); - /* DomainMCSPDU, ErectDomainRequest */ - per_write_choice(s, DomainMCSPDU_ErectDomainRequest << 2); per_write_integer(s, 0); /* subHeight (INTEGER) */ per_write_integer(s, 0); /* subInterval (INTEGER) */ transport_write(mcs->transport, s); } +/** + * Send MCS Attach User Request. + * @param mcs mcs module + */ + void mcs_send_attach_user_request(rdpMcs* mcs) { STREAM* s; int length = 8; s = transport_send_stream_init(mcs->transport, length); - tpkt_write_header(s, length); - tpdu_write_data(s); - - /* DomainMCSPDU, AttachUserRequest */ - per_write_choice(s, DomainMCSPDU_AttachUserRequest << 2); + mcs_write_domain_mcspdu_header(s, DomainMCSPDU_AttachUserRequest, length); transport_write(mcs->transport, s); } +/** + * Receive MCS Attach User Confirm. + * @param mcs mcs module + */ + void mcs_recv_attach_user_confirm(rdpMcs* mcs) { STREAM* s; int length; uint8 result; - uint8 choice; + enum DomainMCSPDU MCSPDU; s = transport_recv_stream_init(mcs->transport, 32); transport_read(mcs->transport, s); - tpkt_read_header(s); - tpdu_read_data(s); + MCSPDU = DomainMCSPDU_AttachUserConfirm; + mcs_read_domain_mcspdu_header(s, &MCSPDU, &length); - per_read_choice(s, &choice); per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */ per_read_integer16(s, &(mcs->user_id), MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ } +/** + * Send MCS Channel Join Request. + * @param mcs mcs module + * @param channel_id channel id + */ + void mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id) { STREAM* s; int length = 12; s = transport_send_stream_init(mcs->transport, 12); - tpkt_write_header(s, length); - tpdu_write_data(s); + mcs_write_domain_mcspdu_header(s, DomainMCSPDU_ChannelJoinRequest, length); - /* DomainMCSPDU, ChannelJoinRequest*/ - per_write_choice(s, DomainMCSPDU_ChannelJoinRequest << 2); per_write_integer16(s, mcs->user_id, MCS_BASE_CHANNEL_ID); - per_write_integer16(s, channel_id + MCS_BASE_CHANNEL_ID, 0); + per_write_integer16(s, channel_id, 0); transport_write(mcs->transport, s); } +/** + * Receive MCS Channel Join Confirm. + * @param mcs mcs module + */ + void mcs_recv_channel_join_confirm(rdpMcs* mcs) { STREAM* s; int length; - uint8 choice; uint8 result; uint16 initiator; uint16 requested; uint16 channelId; + enum DomainMCSPDU MCSPDU; s = transport_recv_stream_init(mcs->transport, 32); transport_read(mcs->transport, s); - tpkt_read_header(s); - tpdu_read_data(s); + MCSPDU = DomainMCSPDU_ChannelJoinConfirm; + mcs_read_domain_mcspdu_header(s, &MCSPDU, &length); - per_read_choice(s, &choice); per_read_enumerated(s, &result, MCS_Result_enum_length); /* result */ per_read_integer16(s, &initiator, MCS_BASE_CHANNEL_ID); /* initiator (UserId) */ per_read_integer16(s, &requested, 0); /* requested (ChannelId) */ per_read_integer16(s, &channelId, 0); /* channelId */ } -void mcs_recv(rdpMcs* mcs) -{ - STREAM* s; - int length; - uint8 result; - uint8 choice; - - s = transport_recv_stream_init(mcs->transport, 1024); - transport_read(mcs->transport, s); -} - /** * Instantiate new MCS module. * @param transport transport diff --git a/libfreerdp-core/mcs.h b/libfreerdp-core/mcs.h index 46fd6f57f..daae2dd77 100644 --- a/libfreerdp-core/mcs.h +++ b/libfreerdp-core/mcs.h @@ -124,17 +124,18 @@ typedef struct rdp_mcs rdpMcs; #define MCS_TYPE_CONNECT_INITIAL 0x65 #define MCS_TYPE_CONNECT_RESPONSE 0x66 +boolean mcs_connect(rdpMcs* mcs); + void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data); void mcs_send_connect_initial(rdpMcs* mcs); void mcs_recv_connect_response(rdpMcs* mcs); void mcs_send_erect_domain_request(rdpMcs* mcs); +void mcs_send_attach_user_request(rdpMcs* mcs); void mcs_recv_attach_user_confirm(rdpMcs* mcs); void mcs_send_channel_join_request(rdpMcs* mcs, uint16 channel_id); void mcs_recv_channel_join_confirm(rdpMcs* mcs); -void mcs_recv(rdpMcs* mcs); - rdpMcs* mcs_new(rdpTransport* transport); void mcs_free(rdpMcs* mcs);