diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c index 8c8b7ad6..d110c987 100644 --- a/libxrdp/xrdp_mcs.c +++ b/libxrdp/xrdp_mcs.c @@ -291,7 +291,7 @@ xrdp_mcs_parse_domain_params(struct xrdp_mcs *self, struct stream *s) return 1; } - if (!s_check_rem(s, len)) + if ((len < 0) || !s_check_rem(s, len)) { return 1; } @@ -337,6 +337,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) @@ -345,6 +351,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) @@ -353,6 +365,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) @@ -379,6 +397,7 @@ 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); @@ -596,6 +615,11 @@ xrdp_mcs_recv_cjrq(struct xrdp_mcs *self) if (opcode & 2) { + if (!s_check_rem(s, 2)) + { + free_stream(s); + return 1; + } in_uint8s(s, 2); } diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 0bbd411f..214202f5 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -514,6 +514,11 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) p = &(self->sec_layer->client_mcs_data); p->p = p->data; + if (!s_check_rem(p, 31 + 2 + 2 + 120 + 2)) + { + g_writeln("xrdp_rdp_parse_client_mcs_data: error"); + return 1; + } in_uint8s(p, 31); in_uint16_le(p, self->client_info.width); in_uint16_le(p, self->client_info.height); @@ -524,6 +529,10 @@ xrdp_rdp_parse_client_mcs_data(struct xrdp_rdp *self) switch (i) { case 0xca01: + if (!s_check_rem(p, 6 + 1)) + { + return 1; + } in_uint8s(p, 6); in_uint8(p, i); @@ -837,6 +846,11 @@ xrdp_process_capset_general(struct xrdp_rdp *self, struct stream *s, { int i; + if (len < 10 + 2) + { + g_writeln("xrdp_process_capset_general: error"); + return 1; + } in_uint8s(s, 10); in_uint16_le(s, i); /* use_compact_packets is pretty much 'use rdp5' */ @@ -858,6 +872,11 @@ xrdp_process_capset_order(struct xrdp_rdp *self, struct stream *s, int cap_flags; DEBUG(("order capabilities")); + if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4) + { + g_writeln("xrdp_process_capset_order: error"); + return 1; + } in_uint8s(s, 20); /* Terminal desc, pad */ in_uint8s(s, 2); /* Cache X granularity */ in_uint8s(s, 2); /* Cache Y granularity */ @@ -917,6 +936,11 @@ xrdp_process_capset_bmpcache(struct xrdp_rdp *self, struct stream *s, { int i; + if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2) + { + g_writeln("xrdp_process_capset_bmpcache: error"); + return 1; + } self->client_info.bitmap_cache_version |= 1; in_uint8s(s, 24); /* cache 1 */ @@ -955,6 +979,11 @@ xrdp_process_capset_bmpcache2(struct xrdp_rdp *self, struct stream *s, int Bpp = 0; int i = 0; + if (len < 2 + 2 + 4 + 4 + 4) + { + g_writeln("xrdp_process_capset_bmpcache2: error"); + return 1; + } self->client_info.bitmap_cache_version |= 2; Bpp = (self->client_info.bpp + 7) / 8; in_uint16_le(s, i); /* cache flags */ @@ -992,6 +1021,11 @@ xrdp_process_capset_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s, { int codec_id; + if (len < 1) + { + g_writeln("xrdp_process_capset_cache_v3_codec_id: error"); + return 1; + } in_uint8(s, codec_id); g_writeln("xrdp_process_capset_cache_v3_codec_id: cache_v3_codec_id %d", codec_id); @@ -1009,6 +1043,11 @@ xrdp_process_capset_pointercache(struct xrdp_rdp *self, struct stream *s, int colorPointerFlag; int no_new_cursor; + if (len < 2 + 2 + 2) + { + g_writeln("xrdp_process_capset_pointercache: error"); + return 1; + } no_new_cursor = self->client_info.pointer_flags & 2; in_uint16_le(s, colorPointerFlag); self->client_info.pointer_flags = colorPointerFlag; @@ -1045,6 +1084,11 @@ xrdp_process_capset_brushcache(struct xrdp_rdp *self, struct stream *s, { int code; + if (len < 4) + { + g_writeln("xrdp_process_capset_brushcache: error"); + return 1; + } in_uint32_le(s, code); self->client_info.brush_cache_code = code; return 0; @@ -1057,12 +1101,11 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp *self, struct stream *s, { int i32; - if (len - 4 < 8) + if (len < 4 + 2 + 2) { - g_writeln("xrdp_process_offscreen_bmpcache: bad len"); + g_writeln("xrdp_process_offscreen_bmpcache: error"); return 1; } - in_uint32_le(s, i32); self->client_info.offscreen_support_level = i32; in_uint16_le(s, i32); @@ -1083,12 +1126,11 @@ xrdp_process_capset_rail(struct xrdp_rdp *self, struct stream *s, int len) { int i32; - if (len - 4 < 4) + if (len < 4) { - g_writeln("xrdp_process_capset_rail: bad len"); + g_writeln("xrdp_process_capset_rail: error"); return 1; } - in_uint32_le(s, i32); self->client_info.rail_support_level = i32; g_writeln("xrdp_process_capset_rail: rail_support_level %d", @@ -1102,12 +1144,11 @@ xrdp_process_capset_window(struct xrdp_rdp *self, struct stream *s, int len) { int i32; - if (len - 4 < 7) + if (len < 4 + 1 + 2) { - g_writeln("xrdp_process_capset_window: bad len"); + g_writeln("xrdp_process_capset_window: error"); return 1; } - in_uint32_le(s, i32); self->client_info.wnd_support_level = i32; in_uint8(s, i32); @@ -1134,14 +1175,32 @@ xrdp_process_capset_codecs(struct xrdp_rdp *self, struct stream *s, int len) char *codec_guid; char *next_guid; + if (len < 1) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } in_uint8(s, codec_count); + len--; for (index = 0; index < codec_count; index++) { codec_guid = s->p; + if (len < 16 + 1 + 2) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } in_uint8s(s, 16); in_uint8(s, codec_id); in_uint16_le(s, codec_properties_length); + len -= 16 + 1 + 2; + if (len < codec_properties_length) + { + g_writeln("xrdp_process_capset_codecs: error"); + return 1; + } + len -= codec_properties_length; next_guid = s->p + codec_properties_length; if (g_memcmp(codec_guid, XR_CODEC_GUID_NSCODEC, 16) == 0) @@ -1207,9 +1266,19 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) for (index = 0; index < num_caps; index++) { p = s->p; + if (!s_check_rem(s, 4)) + { + g_writeln("xrdp_rdp_process_confirm_active: error 1"); + return 1; + } in_uint16_le(s, type); in_uint16_le(s, len); - + if ((len < 4) || !s_check_rem(s, len - 4)) + { + g_writeln("xrdp_rdp_process_confirm_active: error len %d", len, s->end - s->p); + return 1; + } + len -= 4; switch (type) { case RDP_CAPSET_GENERAL: /* 1 */ @@ -1295,7 +1364,7 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp *self, struct stream *s) break; } - s->p = p + len; + s->p = p + len + 4; } DEBUG(("out xrdp_rdp_process_confirm_active")); diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 6d3e8374..fbdc99a4 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -331,12 +331,20 @@ unicode_in(struct stream *s, int uni_len, char *dst, int dst_len) break; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint8(s, dst[dst_index]); in_uint8s(s, 1); dst_index++; src_index += 2; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint8s(s, 2); return 0; } @@ -359,6 +367,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) /* initialize (zero out) local variables */ g_memset(tmpdata, 0, sizeof(char) * 256); + if (!s_check_rem(s, 8)) + { + return 1; + } in_uint8s(s, 4); in_uint32_le(s, flags); DEBUG(("in xrdp_sec_process_logon_info flags $%x", flags)); @@ -398,6 +410,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) } } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_domain); if (len_domain > 511) @@ -406,6 +422,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_user); if (len_user > 511) @@ -414,6 +434,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_password); if (len_password > 511) @@ -422,6 +446,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_program); if (len_program > 511) @@ -430,6 +458,10 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_directory); if (len_directory > 511) @@ -438,35 +470,75 @@ xrdp_sec_process_logon_info(struct xrdp_sec *self, struct stream *s) return 1; } - unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255); + if (unicode_in(s, len_domain, self->rdp_layer->client_info.domain, 255) != 0) + { + return 1; + } DEBUG(("domain %s", self->rdp_layer->client_info.domain)); - unicode_in(s, len_user, self->rdp_layer->client_info.username, 255); + if (unicode_in(s, len_user, self->rdp_layer->client_info.username, 255) != 0) + { + return 1; + } DEBUG(("username %s", self->rdp_layer->client_info.username)); if (flags & RDP_LOGON_AUTO) { - unicode_in(s, len_password, self->rdp_layer->client_info.password, 255); + if (unicode_in(s, len_password, self->rdp_layer->client_info.password, 255) != 0) + { + return 1; + } DEBUG(("flag RDP_LOGON_AUTO found")); } else { + if (!s_check_rem(s, len_password + 2)) + { + return 1; + } in_uint8s(s, len_password + 2); if (self->rdp_layer->client_info.require_credentials) + { + g_writeln("xrdp_sec_process_logon_info: credentials on cmd line is mandatory"); return 1; /* credentials on cmd line is mandatory */ + } } - unicode_in(s, len_program, self->rdp_layer->client_info.program, 255); + if (unicode_in(s, len_program, self->rdp_layer->client_info.program, 255) != 0) + { + return 1; + } DEBUG(("program %s", self->rdp_layer->client_info.program)); - unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255); + if (unicode_in(s, len_directory, self->rdp_layer->client_info.directory, 255) != 0) + { + return 1; + } DEBUG(("directory %s", self->rdp_layer->client_info.directory)); if (flags & RDP_LOGON_BLOB) { + if (!s_check_rem(s, 4)) + { + return 1; + } in_uint8s(s, 2); /* unknown */ in_uint16_le(s, len_ip); - unicode_in(s, len_ip - 2, tmpdata, 255); + if (unicode_in(s, len_ip - 2, tmpdata, 255) != 0) + { + return 1; + } + if (!s_check_rem(s, 2)) + { + return 1; + } in_uint16_le(s, len_dll); - unicode_in(s, len_dll - 2, tmpdata, 255); + if (unicode_in(s, len_dll - 2, tmpdata, 255) != 0) + { + return 1; + } + if (!s_check_rem(s, 4 + 62 + 22 + 62 + 26 + 4)) + { + return 1; + } in_uint32_le(s, tzone); /* len of timetone */ in_uint8s(s, 62); /* skip */ in_uint8s(s, 22); /* skip misc. */ @@ -676,17 +748,29 @@ xrdp_sec_recv(struct xrdp_sec *self, struct stream *s, int *chan) return 1; } + if (!s_check_rem(s, 4)) + { + return 1; + } in_uint32_le(s, flags); DEBUG((" in xrdp_sec_recv flags $%x", flags)); if (flags & SEC_ENCRYPT) /* 0x08 */ { + if (!s_check_rem(s, 8)) + { + return 1; + } in_uint8s(s, 8); /* signature */ xrdp_sec_decrypt(self, s->p, (int)(s->end - s->p)); } if (flags & SEC_CLIENT_RANDOM) /* 0x01 */ { + if (!s_check_rem(s, 4 + 64)) + { + return 1; + } in_uint32_le(s, len); in_uint8a(s, self->client_crypt_random, 64); xrdp_sec_rsa_op(self->client_random, self->client_crypt_random,