summaryrefslogtreecommitdiffstats
path: root/libxrdp/xrdp_mcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxrdp/xrdp_mcs.c')
-rw-r--r--libxrdp/xrdp_mcs.c288
1 files changed, 208 insertions, 80 deletions
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index 9dcb5b51..716ad13f 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -122,14 +122,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
int len;
int userid;
int chanid;
-
DEBUG((" in xrdp_mcs_recv"));
while (1)
{
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
- DEBUG((" out xrdp_mcs_recv xrdp_iso_recv returned non zero"));
+ DEBUG((" out xrdp_mcs_recv, xrdp_iso_recv return non zero"));
+ g_writeln("xrdp_mcs_recv: xrdp_iso_recv failed");
return 1;
}
@@ -151,12 +151,7 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
/* this is channels getting added from the client */
if (appid == MCS_CJRQ)
{
- if (s == self->iso_layer->trans->in_s)
- {
- /* this should not happen */
- g_writeln("xrdp_mcs_recv: error, MCS_CJRQ at wrong time");
- return 1;
- }
+
if (!s_check_rem(s, 4))
{
return 1;
@@ -171,6 +166,14 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
{
log_message(LOG_LEVEL_ERROR,"Non handled error from xrdp_mcs_send_cjcf") ;
}
+
+ s = libxrdp_force_read(self->iso_layer->trans);
+ if (s == 0)
+ {
+ g_writeln("xrdp_mcs_recv: libxrdp_force_read failed");
+ return 1;
+ }
+
continue;
}
@@ -322,30 +325,29 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
int len;
struct stream *s;
- make_stream(s);
- init_stream(s, 16 * 1024);
+ s = libxrdp_force_read(self->iso_layer->trans);
+ if (s == 0)
+ {
+ return 1;
+ }
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
- free_stream(s);
return 1;
}
if (xrdp_mcs_ber_parse_header(self, s, MCS_CONNECT_INITIAL, &len) != 0)
{
- free_stream(s);
return 1;
}
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
{
- free_stream(s);
return 1;
}
if ((len < 0) || !s_check_rem(s, len))
{
- free_stream(s);
return 1;
}
@@ -353,13 +355,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
{
- free_stream(s);
return 1;
}
if ((len < 0) || !s_check_rem(s, len))
{
- free_stream(s);
return 1;
}
@@ -367,13 +367,11 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
{
- free_stream(s);
return 1;
}
if ((len < 0) || !s_check_rem(s, len))
{
- free_stream(s);
return 1;
}
@@ -381,38 +379,32 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
if (xrdp_mcs_parse_domain_params(self, s) != 0)
{
- free_stream(s);
return 1;
}
if (xrdp_mcs_parse_domain_params(self, s) != 0)
{
- free_stream(s);
return 1;
}
if (xrdp_mcs_parse_domain_params(self, s) != 0)
{
- free_stream(s);
return 1;
}
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
{
- free_stream(s);
return 1;
}
/* mcs data can not be zero length */
if ((len <= 0) || (len > 16 * 1024))
{
- free_stream(s);
return 1;
}
if (!s_check_rem(s, len))
{
- free_stream(s);
return 1;
}
@@ -424,12 +416,10 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
if (s_check_end(s))
{
- free_stream(s);
return 0;
}
else
{
- free_stream(s);
return 1;
}
}
@@ -443,18 +433,20 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
struct stream *s;
DEBUG((" in xrdp_mcs_recv_edrq"));
- make_stream(s);
- init_stream(s, 8192);
+
+ s = libxrdp_force_read(self->iso_layer->trans);
+ if (s == 0)
+ {
+ return 1;
+ }
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
- free_stream(s);
return 1;
}
-
+
if (!s_check_rem(s, 1))
{
- free_stream(s);
return 1;
}
@@ -462,13 +454,11 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
if ((opcode >> 2) != MCS_EDRQ)
{
- free_stream(s);
return 1;
}
if (!s_check_rem(s, 4))
{
- free_stream(s);
return 1;
}
@@ -479,7 +469,6 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
{
if (!s_check_rem(s, 2))
{
- free_stream(s);
return 1;
}
in_uint16_be(s, self->userid);
@@ -487,11 +476,9 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
if (!(s_check_end(s)))
{
- free_stream(s);
return 1;
}
- free_stream(s);
DEBUG((" out xrdp_mcs_recv_edrq"));
return 0;
}
@@ -505,18 +492,20 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
struct stream *s;
DEBUG((" in xrdp_mcs_recv_aurq"));
- make_stream(s);
- init_stream(s, 8192);
+
+ s = libxrdp_force_read(self->iso_layer->trans);
+ if (s == 0)
+ {
+ return 1;
+ }
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
- free_stream(s);
return 1;
}
if (!s_check_rem(s, 1))
{
- free_stream(s);
return 1;
}
@@ -524,7 +513,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
if ((opcode >> 2) != MCS_AURQ)
{
- free_stream(s);
return 1;
}
@@ -532,7 +520,6 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
{
if (!s_check_rem(s, 2))
{
- free_stream(s);
return 1;
}
in_uint16_be(s, self->userid);
@@ -540,11 +527,9 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
if (!(s_check_end(s)))
{
- free_stream(s);
return 1;
}
- free_stream(s);
DEBUG((" out xrdp_mcs_recv_aurq"));
return 0;
}
@@ -592,18 +577,19 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
int opcode;
struct stream *s;
- make_stream(s);
- init_stream(s, 8192);
+ s = libxrdp_force_read(self->iso_layer->trans);
+ if (s == 0)
+ {
+ return 1;
+ }
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
- free_stream(s);
return 1;
}
if (!s_check_rem(s, 1))
{
- free_stream(s);
return 1;
}
@@ -611,13 +597,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
if ((opcode >> 2) != MCS_CJRQ)
{
- free_stream(s);
return 1;
}
if (!s_check_rem(s, 4))
{
- free_stream(s);
return 1;
}
@@ -627,7 +611,6 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
{
if (!s_check_rem(s, 2))
{
- free_stream(s);
return 1;
}
in_uint8s(s, 2);
@@ -635,11 +618,9 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
if (!(s_check_end(s)))
{
- free_stream(s);
return 1;
}
- free_stream(s);
return 0;
}
@@ -725,7 +706,163 @@ xrdp_mcs_out_domain_params(struct xrdp_mcs *self, struct stream *s,
xrdp_mcs_ber_out_int8(self, s, 2);
return 0;
}
+/*****************************************************************************/
+/* prepare server gcc data to send in mcs response msg */
+int APP_CC
+xrdp_mcs_out_gcc_data(struct xrdp_sec *self)
+{
+ struct stream *s;
+ int num_channels_even;
+ int num_channels;
+ int index;
+ int channel;
+ int gcc_size;
+ char* gcc_size_ptr;
+ char* ud_ptr;
+
+ num_channels = self->mcs_layer->channel_list->count;
+ num_channels_even = num_channels + (num_channels & 1);
+ s = &(self->server_mcs_data);
+ init_stream(s, 8192);
+ out_uint16_be(s, 5); /* AsnBerObjectIdentifier */
+ out_uint16_be(s, 0x14);
+ out_uint8(s, 0x7c);
+ out_uint16_be(s, 1); /* -- */
+ out_uint8(s, 0x2a); /* ConnectPDULen */
+ out_uint8(s, 0x14);
+ out_uint8(s, 0x76);
+ out_uint8(s, 0x0a);
+ out_uint8(s, 1);
+ out_uint8(s, 1);
+ out_uint8(s, 0);
+ out_uint16_le(s, 0xc001);
+ out_uint8(s, 0);
+ out_uint8(s, 0x4d); /* M */
+ out_uint8(s, 0x63); /* c */
+ out_uint8(s, 0x44); /* D */
+ out_uint8(s, 0x6e); /* n */
+ /* GCC Response Total Length - 2 bytes , set later */
+ gcc_size_ptr = s->p; /* RDPGCCUserDataResponseLength */
+ out_uint8s(s, 2);
+ ud_ptr = s->p; /* User Data */
+ out_uint16_le(s, SEC_TAG_SRV_INFO);
+ if (self->mcs_layer->iso_layer->rdpNegData)
+ {
+ out_uint16_le(s, 12); /* len */
+ }
+ else
+ {
+ out_uint16_le(s, 8); /* len */
+ }
+ out_uint8(s, 4); /* 4 = rdp5 1 = rdp4 */
+ out_uint8(s, 0);
+ out_uint8(s, 8);
+ out_uint8(s, 0);
+ if (self->mcs_layer->iso_layer->rdpNegData)
+ {
+ /* ReqeustedProtocol */
+ out_uint32_le(s, self->mcs_layer->iso_layer->requestedProtocol);
+ }
+ out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
+ out_uint16_le(s, 8 + (num_channels_even * 2)); /* len */
+ out_uint16_le(s, MCS_GLOBAL_CHANNEL); /* 1003, 0x03eb main channel */
+ out_uint16_le(s, num_channels); /* number of other channels */
+
+ for (index = 0; index < num_channels_even; index++)
+ {
+ if (index < num_channels)
+ {
+ channel = MCS_GLOBAL_CHANNEL + (index + 1);
+ out_uint16_le(s, channel);
+ }
+ else
+ {
+ out_uint16_le(s, 0);
+ }
+ }
+
+ if (self->rsa_key_bytes == 64)
+ {
+ g_writeln("xrdp_sec_out_mcs_data: using 512 bit RSA key");
+ out_uint16_le(s, SEC_TAG_SRV_CRYPT);
+ out_uint16_le(s, 0x00ec); /* len is 236 */
+ out_uint32_le(s, self->crypt_method);
+ out_uint32_le(s, self->crypt_level);
+ out_uint32_le(s, 32); /* 32 bytes random len */
+ out_uint32_le(s, 0xb8); /* 184 bytes rsa info(certificate) len */
+ out_uint8a(s, self->server_random, 32);
+ /* here to end is certificate */
+ /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */
+ /* TermService\Parameters\Certificate */
+ out_uint32_le(s, 1);
+ out_uint32_le(s, 1);
+ out_uint32_le(s, 1);
+ out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */
+ out_uint16_le(s, 0x005c); /* 92 bytes length of SEC_TAG_PUBKEY */
+ out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */
+ out_uint32_le(s, 0x0048); /* 72 bytes modulus len */
+ out_uint32_be(s, 0x00020000); /* bit len */
+ out_uint32_be(s, 0x3f000000); /* data len */
+ out_uint8a(s, self->pub_exp, 4); /* pub exp */
+ out_uint8a(s, self->pub_mod, 64); /* pub mod */
+ out_uint8s(s, 8); /* pad */
+ out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */
+ out_uint16_le(s, 72); /* len */
+ out_uint8a(s, self->pub_sig, 64); /* pub sig */
+ out_uint8s(s, 8); /* pad */
+ }
+ else if (self->rsa_key_bytes == 256)
+ {
+ g_writeln("xrdp_sec_out_mcs_data: using 2048 bit RSA key");
+ out_uint16_le(s, SEC_TAG_SRV_CRYPT);
+ out_uint16_le(s, 0x01ac); /* len is 428 */
+ out_uint32_le(s, self->crypt_method);
+ out_uint32_le(s, self->crypt_level);
+ out_uint32_le(s, 32); /* 32 bytes random len */
+ out_uint32_le(s, 0x178); /* 376 bytes rsa info(certificate) len */
+ out_uint8a(s, self->server_random, 32);
+ /* here to end is certificate */
+ /* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ */
+ /* TermService\Parameters\Certificate */
+ out_uint32_le(s, 1);
+ out_uint32_le(s, 1);
+ out_uint32_le(s, 1);
+ out_uint16_le(s, SEC_TAG_PUBKEY); /* 0x0006 */
+ out_uint16_le(s, 0x011c); /* 284 bytes length of SEC_TAG_PUBKEY */
+ out_uint32_le(s, SEC_RSA_MAGIC); /* 0x31415352 'RSA1' */
+ out_uint32_le(s, 0x0108); /* 264 bytes modulus len */
+ out_uint32_be(s, 0x00080000); /* bit len */
+ out_uint32_be(s, 0xff000000); /* data len */
+ out_uint8a(s, self->pub_exp, 4); /* pub exp */
+ out_uint8a(s, self->pub_mod, 256); /* pub mod */
+ out_uint8s(s, 8); /* pad */
+ out_uint16_le(s, SEC_TAG_KEYSIG); /* 0x0008 */
+ out_uint16_le(s, 72); /* len */
+ out_uint8a(s, self->pub_sig, 64); /* pub sig */
+ out_uint8s(s, 8); /* pad */
+ }
+ else if (self->rsa_key_bytes == 0) /* no security */
+ {
+ g_writeln("xrdp_sec_out_mcs_data: using no security");
+ out_uint16_le(s, SEC_TAG_SRV_CRYPT);
+ out_uint16_le(s, 12); /* len is 12 */
+ out_uint32_le(s, self->crypt_method);
+ out_uint32_le(s, self->crypt_level);
+ }
+ else
+ {
+ g_writeln("xrdp_sec_out_mcs_data: error");
+ }
+ /* end certificate */
+ s_mark_end(s);
+
+ gcc_size = (int)(s->end - ud_ptr) | 0x8000;
+ gcc_size_ptr[0] = gcc_size >> 8;
+ gcc_size_ptr[1] = gcc_size;
+
+ return 0;
+}
/*****************************************************************************/
/* returns error */
static int APP_CC
@@ -737,9 +874,11 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self)
DEBUG((" in xrdp_mcs_send_connect_response"));
make_stream(s);
init_stream(s, 8192);
- data_len = self->server_mcs_data->end - self->server_mcs_data->data;
+ data_len = (int) (self->server_mcs_data->end - self->server_mcs_data->data);
xrdp_iso_init(self->iso_layer, s);
- xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE, data_len + 38);
+ //TODO: we should calculate the whole length include MCS_CONNECT_RESPONSE
+ xrdp_mcs_ber_out_header(self, s, MCS_CONNECT_RESPONSE,
+ data_len > 0x80 ? data_len + 38 : data_len + 36);
xrdp_mcs_ber_out_header(self, s, BER_TAG_RESULT, 1);
out_uint8(s, 0);
xrdp_mcs_ber_out_header(self, s, BER_TAG_INTEGER, 1);
@@ -767,13 +906,9 @@ xrdp_mcs_send_connect_response(struct xrdp_mcs *self)
int APP_CC
xrdp_mcs_incoming(struct xrdp_mcs *self)
{
+ int i;
DEBUG((" in xrdp_mcs_incoming"));
- if (xrdp_iso_incoming(self->iso_layer) != 0)
- {
- return 1;
- }
-
if (xrdp_mcs_recv_connect_initial(self) != 0)
{
return 1;
@@ -785,8 +920,7 @@ xrdp_mcs_incoming(struct xrdp_mcs *self)
return 1;
}
- /* in xrdp_sec.c */
- if (xrdp_sec_out_mcs_data(self->sec_layer) != 0)
+ if (xrdp_mcs_out_gcc_data(self->sec_layer) != 0)
{
return 1;
}
@@ -811,25 +945,18 @@ xrdp_mcs_incoming(struct xrdp_mcs *self)
return 1;
}
- if (xrdp_mcs_recv_cjrq(self) != 0)
- {
- return 1;
- }
-
- if (xrdp_mcs_send_cjcf(self, self->userid,
- self->userid + MCS_USERCHANNEL_BASE) != 0)
- {
- return 1;
- }
-
- if (xrdp_mcs_recv_cjrq(self) != 0)
+ for (i = 0; i < self->channel_list->count + 2; i++)
{
- return 1;
- }
+ if (xrdp_mcs_recv_cjrq(self) != 0)
+ {
+ return 1;
+ }
- if (xrdp_mcs_send_cjcf(self, self->userid, MCS_GLOBAL_CHANNEL) != 0)
- {
- return 1;
+ if (xrdp_mcs_send_cjcf(self, self->userid,
+ self->userid + MCS_USERCHANNEL_BASE + i) != 0)
+ {
+ return 1;
+ }
}
DEBUG((" out xrdp_mcs_incoming"));
@@ -895,7 +1022,7 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan)
if (len > 8192 * 2)
{
- g_writeln("error in xrdp_mcs_send, size too bog, its %d", len);
+ g_writeln("error in xrdp_mcs_send, size too big, its %d", len);
}
//if (len > max_len)
@@ -958,6 +1085,7 @@ close_rdp_socket(struct xrdp_mcs *self)
{
if (self->iso_layer->trans != 0)
{
+ trans_shutdown_tls_mode(self->iso_layer->trans);
g_tcp_close(self->iso_layer->trans->sck);
self->iso_layer->trans->sck = 0 ;
g_writeln("xrdp_mcs_disconnect - socket closed");