From 9df9a3382ac6bc4d5f1b6b10ee7629d07f683985 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 9 Jul 2011 17:28:30 -0400 Subject: [PATCH] libfreerdp-core: parsing of GCC Conference Create Response --- cunit/test_gcc.c | 12 ++--- cunit/test_gcc.h | 2 +- libfreerdp-core/gcc.c | 73 +++++++++++++++++++++++++++- libfreerdp-core/gcc.h | 3 +- libfreerdp-core/mcs.c | 4 +- libfreerdp-core/per.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++ libfreerdp-core/per.h | 9 ++++ 7 files changed, 219 insertions(+), 12 deletions(-) diff --git a/cunit/test_gcc.c b/cunit/test_gcc.c index 85cecac..d05389e 100644 --- a/cunit/test_gcc.c +++ b/cunit/test_gcc.c @@ -39,7 +39,7 @@ int add_gcc_suite(void) { add_test_suite(gcc); - add_test_function(gcc_write_create_conference_request); + add_test_function(gcc_write_conference_create_request); add_test_function(gcc_write_client_core_data); add_test_function(gcc_write_client_security_data); add_test_function(gcc_write_client_cluster_data); @@ -68,7 +68,7 @@ uint8 gcc_user_data[284] = "\x00\x00\x80\x80\x63\x6c\x69\x70\x72\x64\x72\x00\x00\x00\xA0\xC0" "\x72\x64\x70\x73\x6e\x64\x00\x00\x00\x00\x00\xc0"; -uint8 gcc_create_conference_request_expected[307] = +uint8 gcc_conference_create_request_expected[307] = "\x00\x05\x00\x14\x7C\x00\x01\x81\x2A\x00\x08\x00\x10\x00\x01\xC0" "\x00\x44\x75\x63\x61\x81\x1c\x01\xc0\xd8\x00\x04\x00\x08\x00\x00" "\x05\x00\x04\x01\xCA\x03\xAA\x09\x04\x00\x00\xCE\x0E\x00\x00\x45" @@ -90,7 +90,7 @@ uint8 gcc_create_conference_request_expected[307] = "\x64\x72\x00\x00\x00\xA0\xC0\x72\x64\x70\x73\x6e\x64\x00\x00\x00" "\x00\x00\xc0"; -void test_gcc_write_create_conference_request(void) +void test_gcc_write_conference_create_request(void) { STREAM* s; STREAM user_data; @@ -99,10 +99,10 @@ void test_gcc_write_create_conference_request(void) user_data.size = sizeof(gcc_user_data); user_data.p = user_data.data + user_data.size; - s = stream_new(sizeof(gcc_create_conference_request_expected)); + s = stream_new(sizeof(gcc_conference_create_request_expected)); - gcc_write_create_conference_request(s, &user_data); - ASSERT_STREAM(s, (uint8*) gcc_create_conference_request_expected, sizeof(gcc_create_conference_request_expected)); + gcc_write_conference_create_request(s, &user_data); + ASSERT_STREAM(s, (uint8*) gcc_conference_create_request_expected, sizeof(gcc_conference_create_request_expected)); } uint8 gcc_client_core_data_expected[216] = diff --git a/cunit/test_gcc.h b/cunit/test_gcc.h index a672f86..2ddce03 100644 --- a/cunit/test_gcc.h +++ b/cunit/test_gcc.h @@ -23,7 +23,7 @@ int init_gcc_suite(void); int clean_gcc_suite(void); int add_gcc_suite(void); -void test_gcc_write_create_conference_request(void); +void test_gcc_write_conference_create_request(void); void test_gcc_write_client_core_data(void); void test_gcc_write_client_security_data(void); void test_gcc_write_client_cluster_data(void); diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c index 038dfa1..c4a6de8 100644 --- a/libfreerdp-core/gcc.c +++ b/libfreerdp-core/gcc.c @@ -72,6 +72,22 @@ * conferenceMode ConferenceMode OPTIONAL * } * + * ConferenceCreateResponse ::= SEQUENCE + * { + * nodeID UserID, + * tag INTEGER, + * result ENUMERATED + * { + * success (0), + * userRejected (1), + * resourcesNotAvailable (2), + * rejectedForSymmetryBreaking (3), + * lockedConferenceNotSupported (4) + * }, + * userData UserData OPTIONAL, + * ... + * } + * * ConferenceName ::= SEQUENCE * { * numeric SimpleNumericString @@ -89,6 +105,12 @@ * * H221NonStandardIdentifier ::= OCTET STRING (SIZE (4..255)) * + * UserID ::= DynamicChannelID + * + * ChannelID ::= INTEGER (1..65535) + * StaticChannelID ::= INTEGER (1..1000) + * DynamicChannelID ::= INTEGER (1001..65535) + * */ /* @@ -98,6 +120,9 @@ */ uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 }; +uint8 h221_cs_key[4] = "Duca"; +uint8 h221_sc_key[4] = "McDn"; + /** * Write a GCC Conference Create Request.\n * @msdn{cc240836} @@ -105,7 +130,7 @@ uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 }; * @param user_data client data blocks */ -void gcc_write_create_conference_request(STREAM* s, STREAM* user_data) +void gcc_write_conference_create_request(STREAM* s, STREAM* user_data) { /* ConnectData */ per_write_choice(s, 0); /* From Key select object (0) of type OBJECT_IDENTIFIER */ @@ -127,12 +152,56 @@ void gcc_write_create_conference_request(STREAM* s, STREAM* user_data) per_write_choice(s, 0xC0); /* UserData::value present + select h221NonStandard (1) */ /* h221NonStandard */ - per_write_octet_string(s, "Duca", 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */ + per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */ /* userData::value (OCTET_STRING) */ per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of client data blocks */ } +void gcc_read_conference_create_response(STREAM* s) +{ + int length; + uint32 tag; + uint16 nodeID; + uint8 result; + uint8 choice; + uint8 selection; + uint8 number; + + /* ConnectData */ + per_read_choice(s, &choice); + per_read_object_identifier(s, t124_02_98_oid); + + /* ConnectData::connectPDU (OCTET_STRING) */ + per_read_length(s, &length); + + /* ConnectGCCPDU */ + per_read_choice(s, &choice); + + /* ConferenceCreateResponse::nodeID (UserID) */ + per_read_integer16(s, &nodeID, 1001); + + /* ConferenceCreateResponse::tag (INTEGER) */ + per_read_integer(s, &tag); + + /* ConferenceCreateResponse::result (ENUMERATED) */ + per_read_enumerated(s, &result); + + /* number of UserData sets */ + per_read_number_of_sets(s, &number); + + /* UserData::value present + select h221NonStandard (1) */ + per_read_choice(s, &choice); + + /* h221NonStandard */ + per_read_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */ + + /* userData (OCTET_STRING) */ + per_read_length(s, &length); + + printf("server core data, length:%d\n", length); +} + /** * Write a user data header (TS_UD_HEADER).\n * @msdn{cc240509} diff --git a/libfreerdp-core/gcc.h b/libfreerdp-core/gcc.h index 5f38b87..8a0cbe6 100644 --- a/libfreerdp-core/gcc.h +++ b/libfreerdp-core/gcc.h @@ -99,7 +99,8 @@ /* Monitor Flags */ #define MONITOR_PRIMARY 0x00000001 -void gcc_write_create_conference_request(STREAM* s, STREAM* user_data); +void gcc_write_conference_create_request(STREAM* s, STREAM* user_data); +void gcc_read_conference_create_response(STREAM* s); void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length); void gcc_write_client_core_data(STREAM* s, rdpSettings *settings); diff --git a/libfreerdp-core/mcs.c b/libfreerdp-core/mcs.c index afab69e..93a57c8 100644 --- a/libfreerdp-core/mcs.c +++ b/libfreerdp-core/mcs.c @@ -250,7 +250,7 @@ void mcs_send_connect_initial(rdpMcs* mcs) gcc_write_client_monitor_data(client_data, mcs->transport->settings); gcc_CCrq = stream_new(512); - gcc_write_create_conference_request(gcc_CCrq, client_data); + gcc_write_conference_create_request(gcc_CCrq, client_data); length = stream_get_length(gcc_CCrq) + 7; s = stream_new(512); @@ -293,7 +293,7 @@ void mcs_recv_connect_response(rdpMcs* mcs) ber_read_octet_string(s, &length); - printf("userData, length:%d\n", length); + gcc_read_conference_create_response(s); } /** diff --git a/libfreerdp-core/per.c b/libfreerdp-core/per.c index 58930d1..058cf88 100644 --- a/libfreerdp-core/per.c +++ b/libfreerdp-core/per.c @@ -19,6 +19,26 @@ #include "per.h" +boolean per_read_length(STREAM* s, int* length) +{ + uint8 byte; + + stream_read_uint8(s, byte); + + if (byte & 0x80) + { + *length = (byte << 8); + stream_read_uint8(s, byte); + *length += byte; + } + else + { + *length = byte; + } + + return True; +} + /** * Write PER length. * @param s stream @@ -33,6 +53,12 @@ void per_write_length(STREAM* s, int length) stream_write_uint8(s, length); } +boolean per_read_choice(STREAM* s, uint8* choice) +{ + stream_read_uint8(s, *choice); + return True; +} + /** * Write PER CHOICE. * @param s stream @@ -44,6 +70,12 @@ void per_write_choice(STREAM* s, uint8 choice) stream_write_uint8(s, choice); } +boolean per_read_selection(STREAM* s, uint8* selection) +{ + stream_read_uint8(s, *selection); + return True; +} + /** * Write PER selection for OPTIONAL fields. * @param s stream @@ -55,6 +87,12 @@ void per_write_selection(STREAM* s, uint8 selection) stream_write_uint8(s, selection); } +boolean per_read_number_of_sets(STREAM* s, uint8* number) +{ + stream_read_uint8(s, *number); + return True; +} + /** * Write PER number of sets for SET OF. * @param s stream @@ -80,6 +118,73 @@ void per_write_padding(STREAM* s, int length) stream_write_uint8(s, 0); } +boolean per_read_integer(STREAM* s, uint32* integer) +{ + int length; + + per_read_length(s, &length); + + if (length == 1) + stream_read_uint8(s, *integer); + else if (length == 2) + stream_read_uint16_be(s, *integer); + else + return False; + + return True; +} + +boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min) +{ + stream_read_uint16_be(s, *integer); + + if (*integer + min > 0xFFFF) + return False; + + *integer += min; + + return True; +} + +boolean per_read_enumerated(STREAM* s, uint8* enumerated) +{ + stream_read_uint8(s, *enumerated); + return True; +} + +boolean per_read_object_identifier(STREAM* s, uint8 oid[6]) +{ + uint8 t12; + int length; + uint8 a_oid[6]; + boolean status; + + per_read_length(s, &length); /* length */ + + if (length != 5) + return False; + + stream_read_uint8(s, t12); /* first two tuples */ + a_oid[0] = (t12 >> 4); + a_oid[1] = (t12 & 0x0F); + + stream_read_uint8(s, a_oid[2]); /* tuple 3 */ + stream_read_uint8(s, a_oid[3]); /* tuple 4 */ + stream_read_uint8(s, a_oid[4]); /* tuple 5 */ + stream_read_uint8(s, a_oid[5]); /* tuple 6 */ + + if ((a_oid[0] == oid[0]) && (a_oid[1] == oid[1]) && + (a_oid[2] == oid[2]) && (a_oid[3] == oid[3]) && + (a_oid[4] == oid[4]) && (a_oid[5] == oid[5])) + { + return True; + } + else + { + return False; + } +} + /** * Write PER OBJECT_IDENTIFIER (OID) * @param s stream @@ -112,6 +217,29 @@ void per_write_string(STREAM* s, uint8* str, int length) stream_write_uint8(s, str[i]); } +boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min) +{ + int i; + int mlength; + uint8* a_oct_str; + + per_read_length(s, &mlength); + + if (mlength + min != length) + return False; + + a_oct_str = s->p; + stream_seek(s, length); + + for (i = 0; i < length; i++) + { + if (a_oct_str[i] != oct_str[i]) + return False; + } + + return True; +} + /** * Write PER OCTET_STRING * @param s stream diff --git a/libfreerdp-core/per.h b/libfreerdp-core/per.h index 456e6a0..8c9cb50 100644 --- a/libfreerdp-core/per.h +++ b/libfreerdp-core/per.h @@ -22,12 +22,21 @@ #include +boolean per_read_length(STREAM* s, int* length); void per_write_length(STREAM* s, int length); +boolean per_read_choice(STREAM* s, uint8* choice); void per_write_choice(STREAM* s, uint8 choice); +boolean per_read_selection(STREAM* s, uint8* selection); void per_write_selection(STREAM* s, uint8 selection); +boolean per_read_number_of_sets(STREAM* s, uint8* number); void per_write_number_of_sets(STREAM* s, uint8 number); void per_write_padding(STREAM* s, int length); +boolean per_read_integer(STREAM* s, uint32* integer); +boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min); +boolean per_read_enumerated(STREAM* s, uint8* enumerated); void per_write_object_identifier(STREAM* s, uint8 oid[6]); +boolean per_read_object_identifier(STREAM* s, uint8 oid[6]); +boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min); void per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min); void per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min); -- 2.7.4