server: start reading MCS Connect Initial PDU and Client Core Data.

This commit is contained in:
Vic Lee 2011-08-19 17:39:37 +08:00
parent 10f8aab40b
commit b7f62964a4
12 changed files with 426 additions and 2 deletions

View File

@ -294,6 +294,27 @@ int ber_skip_octet_string(int length)
return 1 + _ber_skip_length(length) + length;
}
/**
* Read a BER BOOLEAN
* @param s
* @param value
*/
boolean ber_read_boolean(STREAM* s, boolean* value)
{
int length;
uint8 v;
if (!ber_read_universal_tag(s, BER_TAG_BOOLEAN, False))
return False;
ber_read_length(s, &length);
if (length != 1)
return False;
stream_read_uint8(s, v);
*value = (v ? True : False);
return True;
}
/**
* Write a BER BOOLEAN
* @param s

View File

@ -72,6 +72,7 @@ boolean ber_read_octet_string(STREAM* s, int* length);
void ber_write_octet_string(STREAM* s, uint8* oct_str, int length);
int ber_write_octet_string_tag(STREAM* s, int length);
int ber_skip_octet_string(int length);
boolean ber_read_boolean(STREAM* s, boolean* value);
void ber_write_boolean(STREAM* s, boolean value);
boolean ber_read_integer(STREAM* s, uint32* value);
int ber_write_integer(STREAM* s, uint32 value);

View File

@ -167,3 +167,11 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s)
return True;
}
boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s)
{
if (!mcs_read_connect_initial(rdp->mcs, s))
return False;
return True;
}

View File

@ -40,5 +40,6 @@ enum CONNECTION_STATE
boolean rdp_client_connect(rdpRdp* rdp);
boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s);
boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s);
#endif /* __CONNECTION_H */

View File

@ -123,6 +123,63 @@ uint8 t124_02_98_oid[6] = { 0, 0, 20, 124, 0, 1 };
uint8 h221_cs_key[4] = "Duca";
uint8 h221_sc_key[4] = "McDn";
/**
* Read a GCC Conference Create Request.\n
* @msdn{cc240836}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_conference_create_request(STREAM* s, rdpSettings* settings)
{
uint16 length;
uint8 choice;
uint8 number;
uint8 selection;
/* ConnectData */
if (!per_read_choice(s, &choice))
return False;
if (!per_read_object_identifier(s, t124_02_98_oid))
return False;
/* ConnectData::connectPDU (OCTET_STRING) */
if (!per_read_length(s, &length))
return False;
/* ConnectGCCPDU */
if (!per_read_choice(s, &choice))
return False;
if (!per_read_selection(s, &selection))
return False;
/* ConferenceCreateRequest::conferenceName */
if (!per_read_numeric_string(s, 1)) /* ConferenceName::numeric */
return False;
if (!per_read_padding(s, 1)) /* padding */
return False;
/* UserData (SET OF SEQUENCE) */
if (!per_read_number_of_sets(s, &number) || number != 1) /* one set of UserData */
return False;
if (!per_read_choice(s, &choice) || choice != 0xC0) /* UserData::value present + select h221NonStandard (1) */
return False;
/* h221NonStandard */
if (!per_read_octet_string(s, h221_cs_key, 4, 4)) /* h221NonStandard, client-to-server H.221 key, "Duca" */
return False;
/* userData::value (OCTET_STRING) */
if (!per_read_length(s, &length))
return False;
if (stream_get_left(s) < length)
return False;
if (!gcc_read_client_data_blocks(s, settings, length))
return False;
return True;
}
/**
* Write a GCC Conference Create Request.\n
* @msdn{cc240836}
@ -200,6 +257,55 @@ void gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
gcc_read_server_data_blocks(s, settings, length);
}
boolean gcc_read_client_data_blocks(STREAM* s, rdpSettings *settings, int length)
{
uint16 type;
uint16 blockLength;
int pos;
while (length > 0)
{
pos = stream_get_pos(s);
gcc_read_user_data_header(s, &type, &blockLength);
switch (type)
{
case CS_CORE:
if (!gcc_read_client_core_data(s, settings, blockLength - 4))
return False;
break;
case CS_SECURITY:
if (!gcc_read_client_security_data(s, settings))
return False;
break;
case CS_NET:
if (!gcc_read_client_network_data(s, settings))
return False;
break;
case CS_CLUSTER:
if (!gcc_read_client_cluster_data(s, settings))
return False;
break;
case CS_MONITOR:
if (!gcc_read_client_monitor_data(s, settings))
return False;
break;
default:
break;
}
length -= blockLength;
stream_set_pos(s, pos + blockLength);
}
return True;
}
void gcc_write_client_data_blocks(STREAM* s, rdpSettings *settings)
{
gcc_write_client_core_data(s, settings);
@ -261,6 +367,121 @@ void gcc_write_user_data_header(STREAM* s, uint16 type, uint16 length)
stream_write_uint16(s, length); /* length */
}
/**
* Read a client core data block (TS_UD_CS_CORE).\n
* @msdn{cc240510}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_client_core_data(STREAM* s, rdpSettings *settings, uint16 blockLength)
{
uint32 version;
uint16 colorDepth = 0;
uint16 postBeta2ColorDepth = 0;
uint16 highColorDepth = 0;
uint16 supportedColorDepths = 0;
uint16 earlyCapabilityFlags = 0;
uint32 serverSelectedProtocol = 0;
char* str;
/* Length of all required fields, until imeFileName */
if (blockLength < 128)
return False;
stream_read_uint32(s, version); /* version */
settings->rdp_version = (version == RDP_VERSION_4 ? 5 : 4);
stream_read_uint16(s, settings->width); /* desktopWidth */
stream_read_uint16(s, settings->height); /* desktopHeight */
stream_read_uint16(s, colorDepth); /* colorDepth */
stream_seek_uint16(s); /* SASSequence (Secure Access Sequence) */
stream_read_uint32(s, settings->kbd_layout); /* keyboardLayout */
stream_read_uint32(s, settings->client_build); /* clientBuild */
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 32);
stream_seek(s, 32);
snprintf(settings->client_hostname, sizeof(settings->client_hostname), "%s", str);
xfree(str);
stream_read_uint32(s, settings->kbd_type); /* keyboardType */
stream_read_uint32(s, settings->kbd_subtype); /* keyboardSubType */
stream_read_uint32(s, settings->kbd_fn_keys); /* keyboardFunctionKey */
stream_seek(s, 64); /* imeFileName */
blockLength -= 128;
/**
* The following fields are all optional. If one field is present, all of the preceding
* fields MUST also be present. If one field is not present, all of the subsequent fields
* MUST NOT be present.
* We must check the bytes left before reading each field.
*/
do
{
if (blockLength < 2)
break;
stream_read_uint16(s, postBeta2ColorDepth); /* postBeta2ColorDepth */
blockLength -= 2;
if (blockLength < 2)
break;
stream_seek_uint16(s); /* clientProductID */
blockLength -= 2;
if (blockLength < 4)
break;
stream_seek_uint32(s); /* serialNumber */
blockLength -= 4;
if (blockLength < 2)
break;
stream_read_uint16(s, highColorDepth); /* highColorDepth */
blockLength -= 2;
if (blockLength < 2)
break;
stream_read_uint16(s, supportedColorDepths); /* supportedColorDepths */
blockLength -= 2;
if (blockLength < 2)
break;
stream_read_uint16(s, earlyCapabilityFlags); /* earlyCapabilityFlags */
blockLength -= 2;
if (blockLength < 64)
break;
str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64);
stream_seek(s, 64);
snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str);
xfree(str);
blockLength -= 64;
if (blockLength < 1)
break;
stream_read_uint8(s, settings->performance_flags); /* connectionType */
blockLength -= 1;
if (blockLength < 1)
break;
stream_seek_uint8(s); /* pad1octet */
blockLength -= 1;
if (blockLength < 4)
break;
stream_read_uint32(s, serverSelectedProtocol); /* serverSelectedProtocol */
blockLength -= 4;
if (settings->selected_protocol != serverSelectedProtocol)
return False;
} while (0);
return True;
}
/**
* Write a client core data block (TS_UD_CS_CORE).\n
* @msdn{cc240510}
@ -373,6 +594,19 @@ void gcc_read_server_core_data(STREAM* s, rdpSettings *settings)
settings->rdp_version = 7;
}
/**
* Read a client security data block (TS_UD_CS_SEC).\n
* @msdn{cc240511}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings)
{
printf("CS_SECURITY\n");
return True;
}
/**
* Write a client security data block (TS_UD_CS_SEC).\n
* @msdn{cc240511}
@ -432,6 +666,19 @@ void gcc_read_server_security_data(STREAM* s, rdpSettings *settings)
}
}
/**
* Read a client network data block (TS_UD_CS_NET).\n
* @msdn{cc240512}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings)
{
printf("CS_NETWORK\n");
return True;
}
/**
* Write a client network data block (TS_UD_CS_NET).\n
* @msdn{cc240512}
@ -487,6 +734,19 @@ void gcc_read_server_network_data(STREAM* s, rdpSettings *settings)
stream_seek(s, 2); /* padding */
}
/**
* Read a client cluster data block (TS_UD_CS_CLUSTER).\n
* @msdn{cc240514}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings)
{
printf("CS_CLUSTER\n");
return True;
}
/**
* Write a client cluster data block (TS_UD_CS_CLUSTER).\n
* @msdn{cc240514}
@ -509,6 +769,19 @@ void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings)
stream_write_uint32(s, settings->redirected_session_id); /* redirectedSessionID */
}
/**
* Read a client monitor data block (TS_UD_CS_MONITOR).\n
* @msdn{dd305336}
* @param s stream
* @param settings rdp settings
*/
boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings)
{
printf("CS_MONITOR\n");
return True;
}
/**
* Write a client monitor data block (TS_UD_CS_MONITOR).\n
* @msdn{dd305336}
@ -546,3 +819,4 @@ void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings)
}
}
}

View File

@ -100,19 +100,26 @@
/* Monitor Flags */
#define MONITOR_PRIMARY 0x00000001
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);
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_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);
boolean gcc_read_client_security_data(STREAM* s, rdpSettings *settings);
void gcc_write_client_security_data(STREAM* s, rdpSettings *settings);
void gcc_read_server_security_data(STREAM* s, rdpSettings *settings);
boolean gcc_read_client_network_data(STREAM* s, rdpSettings *settings);
void gcc_write_client_network_data(STREAM* s, rdpSettings *settings);
void gcc_read_server_network_data(STREAM* s, rdpSettings *settings);
boolean gcc_read_client_cluster_data(STREAM* s, rdpSettings *settings);
void gcc_write_client_cluster_data(STREAM* s, rdpSettings *settings);
boolean gcc_read_client_monitor_data(STREAM* s, rdpSettings *settings);
void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings);
#endif /* __GCC_H */

View File

@ -347,6 +347,58 @@ void mcs_print_domain_parameters(DomainParameters* domainParameters)
printf("}\n");
}
/**
* Read an MCS Connect Initial PDU.\n
* @msdn{cc240508}
* @param mcs MCS module
* @param s stream
*/
boolean mcs_read_connect_initial(rdpMcs* mcs, STREAM* s)
{
int length;
boolean upwardFlag;
tpkt_read_header(s);
if (tpdu_read_data(s) == 0)
return False;
if (!ber_read_application_tag(s, MCS_TYPE_CONNECT_INITIAL, &length))
return False;
/* callingDomainSelector (OCTET_STRING) */
if (!ber_read_octet_string(s, &length))
return False;
stream_seek(s, length);
/* calledDomainSelector (OCTET_STRING) */
if (!ber_read_octet_string(s, &length))
return False;
stream_seek(s, length);
/* upwardFlag (BOOLEAN) */
if (!ber_read_boolean(s, &upwardFlag))
return False;
/* targetParameters (DomainParameters) */
mcs_read_domain_parameters(s, &mcs->targetParameters);
/* minimumParameters (DomainParameters) */
mcs_read_domain_parameters(s, &mcs->minimumParameters);
/* maximumParameters (DomainParameters) */
mcs_read_domain_parameters(s, &mcs->maximumParameters);
if (!ber_read_octet_string(s, &length))
return False;
if (!gcc_read_conference_create_request(s, mcs->transport->settings))
return False;
return True;
}
/**
* Write an MCS Connect Initial PDU.\n
* @msdn{cc240508}
@ -467,6 +519,17 @@ void mcs_recv_connect_response(rdpMcs* mcs)
gcc_read_conference_create_response(s, mcs->transport->settings);
}
/**
* Send MCS Connect Response.\n
* @msdn{cc240501}
* @param mcs mcs module
*/
boolean mcs_send_connect_response(rdpMcs* mcs)
{
return True;
}
/**
* Send MCS Erect Domain Request.\n
* @msdn{cc240523}

View File

@ -130,8 +130,10 @@ boolean mcs_connect(rdpMcs* mcs);
void mcs_write_connect_initial(STREAM* s, rdpMcs* mcs, STREAM* user_data);
boolean mcs_read_connect_initial(rdpMcs* mcs, STREAM* s);
void mcs_send_connect_initial(rdpMcs* mcs);
void mcs_recv_connect_response(rdpMcs* mcs);
boolean mcs_send_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);

View File

@ -508,6 +508,9 @@ void nego_send_negotiation_response(rdpNego* nego)
stream_set_mark(s, em);
transport_write(nego->transport, s);
/* update settings with negotiated protocol security */
nego->transport->settings->selected_protocol = nego->selected_protocol;
}
/**

View File

@ -64,6 +64,11 @@ static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra)
return -1;
break;
case CONNECTION_STATE_NEGO:
if (!rdp_server_accept_mcs_connect_initial(peer->rdp, s))
return -1;
break;
default:
printf("Invalid state %d\n", peer->rdp->state);
return -1;

View File

@ -133,6 +133,19 @@ void per_write_number_of_sets(STREAM* s, uint8 number)
stream_write_uint8(s, number);
}
/**
* Read PER padding with zeros.
* @param s stream
* @param length
*/
boolean per_read_padding(STREAM* s, int length)
{
stream_seek(s, length);
return True;
}
/**
* Write PER padding with zeros.
* @param s stream
@ -371,6 +384,32 @@ void per_write_octet_string(STREAM* s, uint8* oct_str, int length, int min)
stream_write_uint8(s, oct_str[i]);
}
/**
* Read PER NumericString.
* @param s stream
* @param num_str numeric string
* @param length string length
* @param min minimum string length
*/
boolean per_read_numeric_string(STREAM* s, int min)
{
int i;
int length;
uint16 mlength;
per_read_length(s, &mlength);
length = mlength + min;
for (i = 0; i < length; i += 2)
{
stream_seek(s, 1);
}
return True;
}
/**
* Write PER NumericString.
* @param s stream

View File

@ -30,6 +30,7 @@ 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);
boolean per_read_padding(STREAM* s, int length);
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);
@ -40,8 +41,7 @@ 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);
boolean per_read_numeric_string(STREAM* s, int min);
void per_write_numeric_string(STREAM* s, uint8* num_str, int length, int min);
boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min);
void per_write_integer16(STREAM* s, uint16 integer, uint16 min);
#endif /* __PER_H */