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; 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 * Write a BER BOOLEAN
* @param s * @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); void ber_write_octet_string(STREAM* s, uint8* oct_str, int length);
int ber_write_octet_string_tag(STREAM* s, int length); int ber_write_octet_string_tag(STREAM* s, int length);
int ber_skip_octet_string(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); void ber_write_boolean(STREAM* s, boolean value);
boolean ber_read_integer(STREAM* s, uint32* value); boolean ber_read_integer(STREAM* s, uint32* value);
int ber_write_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; 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_client_connect(rdpRdp* rdp);
boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s);
boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s);
#endif /* __CONNECTION_H */ #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_cs_key[4] = "Duca";
uint8 h221_sc_key[4] = "McDn"; 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 * Write a GCC Conference Create Request.\n
* @msdn{cc240836} * @msdn{cc240836}
@ -200,6 +257,55 @@ void gcc_read_conference_create_response(STREAM* s, rdpSettings* settings)
gcc_read_server_data_blocks(s, settings, length); 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) void gcc_write_client_data_blocks(STREAM* s, rdpSettings *settings)
{ {
gcc_write_client_core_data(s, 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 */ 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 * Write a client core data block (TS_UD_CS_CORE).\n
* @msdn{cc240510} * @msdn{cc240510}
@ -373,6 +594,19 @@ void gcc_read_server_core_data(STREAM* s, rdpSettings *settings)
settings->rdp_version = 7; 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 * Write a client security data block (TS_UD_CS_SEC).\n
* @msdn{cc240511} * @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 * Write a client network data block (TS_UD_CS_NET).\n
* @msdn{cc240512} * @msdn{cc240512}
@ -487,6 +734,19 @@ void gcc_read_server_network_data(STREAM* s, rdpSettings *settings)
stream_seek(s, 2); /* padding */ 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 * Write a client cluster data block (TS_UD_CS_CLUSTER).\n
* @msdn{cc240514} * @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 */ 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 * Write a client monitor data block (TS_UD_CS_MONITOR).\n
* @msdn{dd305336} * @msdn{dd305336}
@ -546,3 +819,4 @@ void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings)
} }
} }
} }

View File

@ -100,19 +100,26 @@
/* Monitor Flags */ /* Monitor Flags */
#define MONITOR_PRIMARY 0x00000001 #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_write_conference_create_request(STREAM* s, STREAM* user_data);
void gcc_read_conference_create_response(STREAM* s, rdpSettings* settings); 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_write_client_data_blocks(STREAM* s, rdpSettings *settings);
void gcc_read_server_data_blocks(STREAM* s, rdpSettings *settings, int length); 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_read_user_data_header(STREAM* s, uint16* type, uint16* length);
void gcc_write_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_write_client_core_data(STREAM* s, rdpSettings *settings);
void gcc_read_server_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_write_client_security_data(STREAM* s, rdpSettings *settings);
void gcc_read_server_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_write_client_network_data(STREAM* s, rdpSettings *settings);
void gcc_read_server_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); 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); void gcc_write_client_monitor_data(STREAM* s, rdpSettings *settings);
#endif /* __GCC_H */ #endif /* __GCC_H */

View File

@ -347,6 +347,58 @@ void mcs_print_domain_parameters(DomainParameters* domainParameters)
printf("}\n"); 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 * Write an MCS Connect Initial PDU.\n
* @msdn{cc240508} * @msdn{cc240508}
@ -467,6 +519,17 @@ void mcs_recv_connect_response(rdpMcs* mcs)
gcc_read_conference_create_response(s, mcs->transport->settings); 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 * Send MCS Erect Domain Request.\n
* @msdn{cc240523} * @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); 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_send_connect_initial(rdpMcs* mcs);
void mcs_recv_connect_response(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_erect_domain_request(rdpMcs* mcs);
void mcs_send_attach_user_request(rdpMcs* mcs); void mcs_send_attach_user_request(rdpMcs* mcs);
void mcs_recv_attach_user_confirm(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); stream_set_mark(s, em);
transport_write(nego->transport, s); 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; return -1;
break; break;
case CONNECTION_STATE_NEGO:
if (!rdp_server_accept_mcs_connect_initial(peer->rdp, s))
return -1;
break;
default: default:
printf("Invalid state %d\n", peer->rdp->state); printf("Invalid state %d\n", peer->rdp->state);
return -1; return -1;

View File

@ -133,6 +133,19 @@ void per_write_number_of_sets(STREAM* s, uint8 number)
stream_write_uint8(s, 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. * Write PER padding with zeros.
* @param s stream * @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]); 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. * Write PER NumericString.
* @param s stream * @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); void per_write_selection(STREAM* s, uint8 selection);
boolean per_read_number_of_sets(STREAM* s, uint8* number); boolean per_read_number_of_sets(STREAM* s, uint8* number);
void per_write_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); void per_write_padding(STREAM* s, int length);
boolean per_read_integer(STREAM* s, uint32* integer); boolean per_read_integer(STREAM* s, uint32* integer);
boolean per_read_integer16(STREAM* s, uint16* integer, uint16 min); 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_object_identifier(STREAM* s, uint8 oid[6]);
boolean per_read_octet_string(STREAM* s, uint8* oct_str, int length, int min); 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_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); 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 */ #endif /* __PER_H */