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.c138
1 files changed, 137 insertions, 1 deletions
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index 4bf3d025..86212bb1 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -38,6 +38,7 @@ xrdp_mcs_create(struct xrdp_sec *owner, struct trans *trans,
self->server_mcs_data = server_mcs_data;
self->iso_layer = xrdp_iso_create(self, trans);
self->channel_list = list_create();
+ self->monitor_list = list_create();
DEBUG((" out xrdp_mcs_create"));
return self;
}
@@ -47,6 +48,7 @@ void APP_CC
xrdp_mcs_delete(struct xrdp_mcs *self)
{
struct mcs_channel_item *channel_item;
+ struct mcs_monitor_item *monitor_item;
int index;
int count;
@@ -66,6 +68,19 @@ xrdp_mcs_delete(struct xrdp_mcs *self)
}
list_delete(self->channel_list);
+
+ /* here we have to free the monitor items and anything in them */
+ count = self->monitor_list->count;
+
+ for (index = count - 1; index >= 0; index--)
+ {
+ monitor_item = (struct mcs_monitor_item *)
+ list_get_item(self->monitor_list, index);
+ g_free(monitor_item);
+ }
+
+ list_delete(self->monitor_list);
+
xrdp_iso_delete(self->iso_layer);
/* make sure we get null pointer exception if struct is used again. */
DEBUG(("xrdp_mcs_delete processed"))
@@ -132,6 +147,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
+
in_uint8(s, opcode);
appid = opcode >> 2;
@@ -145,6 +165,11 @@ 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_check_rem(s, 4))
+ {
+ return 1;
+ }
+
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
log_message(LOG_LEVEL_DEBUG,"MCS_CJRQ - channel join request received");
@@ -176,6 +201,11 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
return 1;
}
+ if (!s_check_rem(s, 6))
+ {
+ return 1;
+ }
+
in_uint8s(s, 2);
in_uint16_be(s, *chan);
in_uint8s(s, 1);
@@ -183,6 +213,10 @@ xrdp_mcs_recv(struct xrdp_mcs *self, struct stream *s, int *chan)
if (len & 0x80)
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8s(s, 1);
}
@@ -202,10 +236,18 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
if (tag_val > 0xff)
{
+ if (!s_check_rem(s, 2))
+ {
+ return 1;
+ }
in_uint16_be(s, tag);
}
else
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8(s, tag);
}
@@ -214,6 +256,11 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
+
in_uint8(s, l);
if (l & 0x80)
@@ -223,6 +270,10 @@ xrdp_mcs_ber_parse_header(struct xrdp_mcs *self, struct stream *s,
while (l > 0)
{
+ if (!s_check_rem(s, 1))
+ {
+ return 1;
+ }
in_uint8(s, i);
*len = (*len << 8) | i;
l--;
@@ -255,6 +306,11 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ return 1;
+ }
+
in_uint8s(s, len);
if (s_check(s))
@@ -276,7 +332,7 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
struct stream *s;
make_stream(s);
- init_stream(s, 8192);
+ init_stream(s, 16 * 1024);
if (xrdp_iso_recv(self->iso_layer, s) != 0)
{
@@ -296,6 +352,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_OCTET_STRING, &len) != 0)
@@ -304,6 +366,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_ber_parse_header(self, s, BER_TAG_BOOLEAN, &len) != 0)
@@ -312,6 +380,12 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
return 1;
}
+ if ((len < 0) || !s_check_rem(s, len))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, len);
if (xrdp_mcs_parse_domain_params(self, s) != 0)
@@ -338,6 +412,19 @@ xrdp_mcs_recv_connect_initial(struct xrdp_mcs *self)
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;
+ }
+
/* make a copy of client mcs data */
init_stream(self->client_mcs_data, len);
out_uint8a(self->client_mcs_data, s->p, len);
@@ -364,6 +451,7 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
int opcode;
struct stream *s;
+ DEBUG((" in xrdp_mcs_recv_edrq"));
make_stream(s);
init_stream(s, 8192);
@@ -372,6 +460,12 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
free_stream(s);
return 1;
}
+
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint8(s, opcode);
@@ -381,11 +475,22 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 4))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, 2);
in_uint8s(s, 2);
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint16_be(s, self->userid);
}
@@ -396,6 +501,7 @@ xrdp_mcs_recv_edrq(struct xrdp_mcs *self)
}
free_stream(s);
+ DEBUG((" out xrdp_mcs_recv_edrq"));
return 0;
}
@@ -407,6 +513,7 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
int opcode;
struct stream *s;
+ DEBUG((" in xrdp_mcs_recv_aurq"));
make_stream(s);
init_stream(s, 8192);
@@ -416,6 +523,12 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8(s, opcode);
if ((opcode >> 2) != MCS_AURQ)
@@ -426,6 +539,11 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint16_be(s, self->userid);
}
@@ -436,6 +554,7 @@ xrdp_mcs_recv_aurq(struct xrdp_mcs *self)
}
free_stream(s);
+ DEBUG((" out xrdp_mcs_recv_aurq"));
return 0;
}
@@ -491,6 +610,12 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 1))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8(s, opcode);
if ((opcode >> 2) != MCS_CJRQ)
@@ -499,10 +624,21 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self)
return 1;
}
+ if (!s_check_rem(s, 4))
+ {
+ free_stream(s);
+ return 1;
+ }
+
in_uint8s(s, 4);
if (opcode & 2)
{
+ if (!s_check_rem(s, 2))
+ {
+ free_stream(s);
+ return 1;
+ }
in_uint8s(s, 2);
}