diff options
Diffstat (limited to 'libxrdp/xrdp_mcs.c')
| -rw-r--r-- | libxrdp/xrdp_mcs.c | 138 |
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); } |
