server: send MCS Connect Response PDU.
authorVic Lee <llyzs@163.com>
Fri, 19 Aug 2011 15:56:47 +0000 (23:56 +0800)
committerVic Lee <llyzs@163.com>
Fri, 19 Aug 2011 15:56:47 +0000 (23:56 +0800)
13 files changed:
include/freerdp/settings.h
libfreerdp-core/ber.c
libfreerdp-core/ber.h
libfreerdp-core/connection.c
libfreerdp-core/connection.h
libfreerdp-core/gcc.c
libfreerdp-core/gcc.h
libfreerdp-core/mcs.c
libfreerdp-core/mcs.h
libfreerdp-core/nego.c
libfreerdp-core/per.c
libfreerdp-core/per.h
server/test/freerdp_server.c

index 7310305..db96c9f 100644 (file)
@@ -170,6 +170,7 @@ struct rdp_settings
        uint32 kbd_subtype;
        uint32 kbd_fn_keys;
        uint32 client_build;
+       uint32 requested_protocols;
        uint32 selected_protocol;
        uint32 encryption_method;
        uint32 encryption_level;
index 127cbdc..1c7f0ad 100644 (file)
@@ -251,6 +251,13 @@ boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count)
        return True;
 }
 
+void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count)
+{
+       ber_write_universal_tag(s, BER_TAG_ENUMERATED, False);
+       ber_write_length(s, 1);
+       stream_write_uint8(s, enumerated);
+}
+
 boolean ber_read_bit_string(STREAM* s, int* length, uint8* padding)
 {
        ber_read_universal_tag(s, BER_TAG_BIT_STRING, False);
index 6da53d6..8a4c0d9 100644 (file)
@@ -60,6 +60,7 @@ boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length);
 void ber_write_application_tag(STREAM* s, uint8 tag, int length);
 boolean ber_read_application_tag(STREAM* s, uint8 tag, int* length);
 boolean ber_read_enumerated(STREAM* s, uint8* enumerated, uint8 count);
+void ber_write_enumerated(STREAM* s, uint8 enumerated, uint8 count);
 boolean ber_read_contextual_tag(STREAM* s, uint8 tag, int* length, boolean pc);
 int ber_write_contextual_tag(STREAM* s, uint8 tag, int length, boolean pc);
 int ber_skip_contextual_tag(int length);
index 163a4bd..5ee8440 100644 (file)
@@ -182,6 +182,11 @@ boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s)
        }
        printf("\n");
 
+       if (!mcs_send_connect_response(rdp->mcs))
+               return False;
+
+       rdp->state = CONNECTION_STATE_MCS_CONNECT;
+
        return True;
 }
 
index 6684cee..e0f94b5 100644 (file)
@@ -34,7 +34,8 @@
 enum CONNECTION_STATE
 {
        CONNECTION_STATE_INITIAL = 0,
-       CONNECTION_STATE_NEGO
+       CONNECTION_STATE_NEGO,
+       CONNECTION_STATE_MCS_CONNECT
 };
 
 boolean rdp_client_connect(rdpRdp* rdp);
index f034c64..094e5e5 100644 (file)
@@ -257,6 +257,40 @@ void gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
        gcc_read_server_data_blocks(s, settings, length);
 }
 
+void gcc_write_conference_create_response(STREAM* s, STREAM* user_data)
+{
+       /* ConnectData */
+       per_write_choice(s, 0);
+       per_write_object_identifier(s, t124_02_98_oid);
+
+       /* ConnectData::connectPDU (OCTET_STRING) */
+       per_write_length(s, stream_get_length(user_data) + 2);
+
+       /* ConnectGCCPDU */
+       per_write_choice(s, 0x14);
+
+       /* ConferenceCreateResponse::nodeID (UserID) */
+       per_write_integer16(s, 0x79F3, 1001);
+
+       /* ConferenceCreateResponse::tag (INTEGER) */
+       per_write_integer(s, 1);
+
+       /* ConferenceCreateResponse::result (ENUMERATED) */
+       per_write_enumerated(s, 0, MCS_Result_enum_length);
+
+       /* number of UserData sets */
+       per_write_number_of_sets(s, 1);
+
+       /* UserData::value present + select h221NonStandard (1) */
+       per_write_choice(s, 0xC0);
+
+       /* h221NonStandard */
+       per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
+
+       /* userData (OCTET_STRING) */
+       per_write_octet_string(s, user_data->data, stream_get_length(user_data), 0); /* array of server data blocks */
+}
+
 boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings *settings, int length)
 {
        uint16 type;
@@ -347,6 +381,13 @@ void gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length)
        }
 }
 
+void gcc_write_server_data_blocks(STREAM* s, rdpSettings *settings)
+{
+       gcc_write_server_core_data(s, settings);
+       gcc_write_server_network_data(s, settings);
+       gcc_write_server_security_data(s, settings);
+}
+
 void gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length)
 {
        stream_read_uint16(s, *type); /* type */
@@ -390,7 +431,7 @@ boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 block
                return False;
 
        stream_read_uint32(s, version); /* version */
-       settings->rdp_version = (version == RDP_VERSION_4 ? 5 : 4);
+       settings->rdp_version = (version == RDP_VERSION_4 ? 4 : 7);
 
        stream_read_uint16(s, settings->width); /* desktopWidth */
        stream_read_uint16(s, settings->height); /* desktopHeight */
@@ -634,6 +675,14 @@ void gcc_read_server_core_data(STREAM* s, rdpSettings *settings)
                settings->rdp_version = 7;
 }
 
+void gcc_write_server_core_data(STREAM* s, rdpSettings *settings)
+{
+       gcc_write_user_data_header(s, SC_CORE, 12);
+
+       stream_write_uint32(s, settings->rdp_version == 4 ? RDP_VERSION_4 : RDP_VERSION_5_PLUS);
+       stream_write_uint32(s, settings->requested_protocols); /* clientRequestedProtocols */
+}
+
 /**
  * Read a client security data block (TS_UD_CS_SEC).\n
  * @msdn{cc240511}
@@ -712,6 +761,18 @@ void gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
        }
 }
 
+void gcc_write_server_security_data(STREAM* s, rdpSettings *settings)
+{
+       gcc_write_user_data_header(s, SC_SECURITY, 12);
+
+       stream_write_uint32(s, ENCRYPTION_METHOD_NONE); /* encryptionMethod */
+       stream_write_uint32(s, ENCRYPTION_LEVEL_NONE); /* encryptionLevel */
+#if 0
+       stream_write_uint32(s, 0); /* serverRandomLen */
+       stream_write_uint32(s, 0); /* serverCertLen */
+#endif
+}
+
 /**
  * Read a client network data block (TS_UD_CS_NET).\n
  * @msdn{cc240512}
@@ -738,6 +799,7 @@ boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings, uint16 bl
                /* CHANNEL_DEF */
                stream_read(s, settings->channels[i].name, 8); /* name (8 bytes) */
                stream_read_uint32(s, settings->channels[i].options); /* options (4 bytes) */
+               settings->channels[i].chan_id = MCS_GLOBAL_CHANNEL_ID + 1 + i;
        }
 
        return True;
@@ -798,6 +860,24 @@ void gcc_read_server_network_data(STREAM* s, rdpSettings *settings)
                stream_seek(s, 2); /* padding */
 }
 
+void gcc_write_server_network_data(STREAM* s, rdpSettings *settings)
+{
+       int i;
+
+       gcc_write_user_data_header(s, SC_NET, 8 + settings->num_channels * 2 + (settings->num_channels % 2 == 1 ? 2 : 0));
+
+       stream_write_uint16(s, MCS_GLOBAL_CHANNEL_ID); /* MCSChannelId */
+       stream_write_uint16(s, settings->num_channels); /* channelCount */
+
+       for (i = 0; i < settings->num_channels; i++)
+       {
+               stream_write_uint16(s, settings->channels[i].chan_id);
+       }
+
+       if (settings->num_channels % 2 == 1)
+               stream_write_uint16(s, 0);
+}
+
 /**
  * Read a client cluster data block (TS_UD_CS_CLUSTER).\n
  * @msdn{cc240514}
index ff109d6..9ee45f6 100644 (file)
 boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings);
 void gcc_write_conference_create_request(STREAM* s, STREAM* user_data);
 void gcc_read_conference_create_response(STREAM* s, rdpSettings* settings);
+void gcc_write_conference_create_response(STREAM* s, STREAM* user_data);
 boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings *settings, int length);
 void gcc_write_client_data_blocks(STREAM* s, rdpSettings *settings);
 void gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length);
+void gcc_write_server_data_blocks(STREAM* s, rdpSettings *settings);
 void gcc_read_user_data_header(STREAM* s, uint16* type, uint16* length);
 void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length);
 boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength);
 void gcc_write_client_core_data(STREAM* s, rdpSettings *settings);
 void gcc_read_server_core_data(STREAM* s, rdpSettings *settings);
+void gcc_write_server_core_data(STREAM* s, rdpSettings *settings);
 boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings, uint16 blockLength);
 void gcc_write_client_security_data(STREAM* s, rdpSettings *settings);
 void gcc_read_server_security_data(STREAM* s, rdpSettings *settings);
+void gcc_write_server_security_data(STREAM* s, rdpSettings *settings);
 boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings, uint16 blockLength);
 void gcc_write_client_network_data(STREAM* s, rdpSettings *settings);
 void gcc_read_server_network_data(STREAM* s, rdpSettings *settings);
+void gcc_write_server_network_data(STREAM* s, rdpSettings *settings);
 boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings, uint16 blockLength);
 void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings);
 boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings, uint16 blockLength);
index 438c17d..bc61e1f 100644 (file)
@@ -448,6 +448,41 @@ void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data)
 }
 
 /**
+ * Write an MCS Connect Response PDU.\n
+ * @msdn{cc240508}
+ * @param s stream
+ * @param mcs MCS module
+ * @param user_data GCC Conference Create Response
+ */
+
+void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data)
+{
+       int length;
+       uint8 *bm, *em;
+
+       int gcc_CCrsp_length = stream_get_length(user_data);
+
+       stream_get_mark(s, bm);
+       stream_seek(s, 3);
+
+       ber_write_enumerated(s, 0, MCS_Result_enum_length);
+       ber_write_integer(s, 0); /* calledConnectId */
+
+       mcs->domainParameters = mcs->targetParameters;
+       mcs_write_domain_parameters(s, &(mcs->domainParameters));
+
+       /* userData (OCTET_STRING) */
+       ber_write_octet_string(s, user_data->data, gcc_CCrsp_length);
+
+       stream_get_mark(s, em);
+       length = (em - bm) - 3;
+       stream_set_mark(s, bm);
+
+       ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);
+       stream_set_mark(s, em);
+}
+
+/**
  * Send MCS Connect Initial.\n
  * @msdn{cc240508}
  * @param mcs mcs module
@@ -527,6 +562,37 @@ void mcs_recv_connect_response(rdpMcs* mcs)
 
 boolean mcs_send_connect_response(rdpMcs* mcs)
 {
+       STREAM* s;
+       int length;
+       uint8 *bm, *em;
+       STREAM* gcc_CCrsp;
+       STREAM* server_data;
+
+       server_data = stream_new(512);
+       gcc_write_server_data_blocks(server_data, mcs->transport->settings);
+
+       gcc_CCrsp = stream_new(512);
+       gcc_write_conference_create_response(gcc_CCrsp, server_data);
+       length = stream_get_length(gcc_CCrsp) + 7;
+
+       s = transport_send_stream_init(mcs->transport, 1024);
+       stream_get_mark(s, bm);
+       stream_seek(s, 7);
+
+       mcs_write_connect_response(s, mcs, gcc_CCrsp);
+       stream_get_mark(s, em);
+       length = (em - bm);
+       stream_set_mark(s, bm);
+
+       tpkt_write_header(s, length);
+       tpdu_write_data(s);
+       stream_set_mark(s, em);
+
+       transport_write(mcs->transport, s);
+
+       stream_free(gcc_CCrsp);
+       stream_free(server_data);
+
        return True;
 }
 
index f4e85e3..f8416a5 100644 (file)
@@ -129,6 +129,7 @@ typedef struct rdp_mcs rdpMcs;
 boolean mcs_connect(rdpMcs* mcs);
 
 void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data);
+void mcs_write_connect_response(STREAM* s, rdpMcs* mcs, STREAM* user_data);
 
 boolean mcs_read_connect_initial(rdpMcs* mcs, STREAM* s);
 void mcs_send_connect_initial(rdpMcs* mcs);
index 8181a7e..c121bb9 100644 (file)
@@ -82,6 +82,7 @@ boolean nego_connect(rdpNego* nego)
        DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]);
 
        /* update settings with negotiated protocol security */
+       nego->transport->settings->requested_protocols = nego->requested_protocols;
        nego->transport->settings->selected_protocol = nego->selected_protocol;
 
        return True;
@@ -510,6 +511,7 @@ void nego_send_negotiation_response(rdpNego* nego)
        transport_write(nego->transport, s);
 
        /* update settings with negotiated protocol security */
+       nego->transport->settings->requested_protocols = nego->requested_protocols;
        nego->transport->settings->selected_protocol = nego->selected_protocol;
 }
 
index 1ea2477..0789cfa 100644 (file)
@@ -260,6 +260,19 @@ boolean per_read_enumerated(STREAM* s, uint8* enumerated, uint8 count)
 }
 
 /**
+ * Write PER ENUMERATED.
+ * @param s stream
+ * @param enumerated enumerated
+ * @param count enumeration count
+ * @return
+ */
+
+void per_write_enumerated(STREAM* s, uint8 enumerated, uint8 count)
+{
+       stream_write_uint8(s, enumerated);
+}
+
+/**
  * Read PER OBJECT_IDENTIFIER (OID).
  * @param s stream
  * @param oid object identifier (OID)
index 19821ab..f246cfe 100644 (file)
@@ -37,6 +37,7 @@ boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min);
 void per_write_integer(STREAM* s, uint32 integer);
 void per_write_integer16(STREAM* s, uint16 integer, uint16 min);
 boolean per_read_enumerated(STREAM* s, uint8* enumerated, uint8 count);
+void per_write_enumerated(STREAM* s, uint8 enumerated, uint8 count);
 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);
index ca83f57..5d9e58f 100644 (file)
@@ -42,6 +42,7 @@ static void* test_peer_mainloop(void* arg)
 
        client->settings->cert_file = xstrdup("server.crt");
        client->settings->privatekey_file = xstrdup("server.key");
+       client->settings->nla_security = False;
        client->Initialize(client);
 
        while (1)