uint32 kbd_subtype;
uint32 kbd_fn_keys;
uint32 client_build;
+ uint32 requested_protocols;
uint32 selected_protocol;
uint32 encryption_method;
uint32 encryption_level;
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);
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);
}
printf("\n");
+ if (!mcs_send_connect_response(rdp->mcs))
+ return False;
+
+ rdp->state = CONNECTION_STATE_MCS_CONNECT;
+
return True;
}
enum CONNECTION_STATE
{
CONNECTION_STATE_INITIAL = 0,
- CONNECTION_STATE_NEGO
+ CONNECTION_STATE_NEGO,
+ CONNECTION_STATE_MCS_CONNECT
};
boolean rdp_client_connect(rdpRdp* rdp);
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;
}
}
+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 */
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 */
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}
}
}
+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}
/* 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;
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}
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);
}
/**
+ * 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
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;
}
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);
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;
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;
}
}
/**
+ * 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)
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);
client->settings->cert_file = xstrdup("server.crt");
client->settings->privatekey_file = xstrdup("server.key");
+ client->settings->nla_security = False;
client->Initialize(client);
while (1)