Malicious RDP server security fixes

This commit includes fixes for a set of 21 vulnerabilities in
rdesktop when a malicious RDP server is used.

All vulnerabilities was identified and reported by Eyal Itkin.

 * Add rdp_protocol_error function that is used in several fixes
 * Refactor of process_bitmap_updates
 * Fix possible integer overflow in s_check_rem() on 32bit arch
 * Fix memory corruption in process_bitmap_data - CVE-2018-8794
 * Fix remote code execution in process_bitmap_data - CVE-2018-8795
 * Fix remote code execution in process_plane - CVE-2018-8797
 * Fix Denial of Service in mcs_recv_connect_response - CVE-2018-20175
 * Fix Denial of Service in mcs_parse_domain_params - CVE-2018-20175
 * Fix Denial of Service in sec_parse_crypt_info - CVE-2018-20176
 * Fix Denial of Service in sec_recv - CVE-2018-20176
 * Fix minor information leak in rdpdr_process - CVE-2018-8791
 * Fix Denial of Service in cssp_read_tsrequest - CVE-2018-8792
 * Fix remote code execution in cssp_read_tsrequest - CVE-2018-8793
 * Fix Denial of Service in process_bitmap_data - CVE-2018-8796
 * Fix minor information leak in rdpsnd_process_ping - CVE-2018-8798
 * Fix Denial of Service in process_secondary_order - CVE-2018-8799
 * Fix remote code execution in in ui_clip_handle_data - CVE-2018-8800
 * Fix major information leak in ui_clip_handle_data - CVE-2018-20174
 * Fix memory corruption in rdp_in_unistr - CVE-2018-20177
 * Fix Denial of Service in process_demand_active - CVE-2018-20178
 * Fix remote code execution in lspci_process - CVE-2018-20179
 * Fix remote code execution in rdpsnddbg_process - CVE-2018-20180
 * Fix remote code execution in seamless_process - CVE-2018-20181
 * Fix remote code execution in seamless_process_line - CVE-2018-20182
This commit is contained in:
Henrik Andersson 2019-01-16 10:45:33 +01:00
parent 1f13bf5c5e
commit 4dca546d04
16 changed files with 255 additions and 76 deletions

2
asn.c
View File

@ -22,7 +22,7 @@
/* Parse an ASN.1 BER header */ /* Parse an ASN.1 BER header */
RD_BOOL RD_BOOL
ber_parse_header(STREAM s, int tagval, int *length) ber_parse_header(STREAM s, int tagval, uint32 *length)
{ {
int tag, len; int tag, len;

View File

@ -794,7 +794,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
replen = revcode; replen = revcode;
collen = 0; collen = 0;
} }
while (collen > 0) while (indexw < width && collen > 0)
{ {
color = CVAL(in); color = CVAL(in);
*out = color; *out = color;
@ -802,7 +802,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
indexw++; indexw++;
collen--; collen--;
} }
while (replen > 0) while (indexw < width && replen > 0)
{ {
*out = color; *out = color;
out += 4; out += 4;
@ -824,7 +824,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
replen = revcode; replen = revcode;
collen = 0; collen = 0;
} }
while (collen > 0) while (indexw < width && collen > 0)
{ {
x = CVAL(in); x = CVAL(in);
if (x & 1) if (x & 1)
@ -844,7 +844,7 @@ process_plane(uint8 * in, int width, int height, uint8 * out, int size)
indexw++; indexw++;
collen--; collen--;
} }
while (replen > 0) while (indexw < width && replen > 0)
{ {
x = last_line[indexw * 4] + color; x = last_line[indexw * 4] + color;
*out = x; *out = x;

View File

@ -118,6 +118,7 @@ cliprdr_process(STREAM s)
uint16 type, status; uint16 type, status;
uint32 length, format; uint32 length, format;
uint8 *data; uint8 *data;
struct stream packet = *s;
in_uint16_le(s, type); in_uint16_le(s, type);
in_uint16_le(s, status); in_uint16_le(s, status);
@ -127,6 +128,11 @@ cliprdr_process(STREAM s)
logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status, logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
length); length);
if (!s_check_rem(s, length))
{
rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
}
if (status == CLIPRDR_ERROR) if (status == CLIPRDR_ERROR)
{ {
switch (type) switch (type)

View File

@ -751,6 +751,9 @@ enum RDP_DESKTOP_ORIENTATION
#define ENC_SALTED_CHECKSUM 0x0010 #define ENC_SALTED_CHECKSUM 0x0010
#define NO_BITMAP_COMPRESSION_HDR 0x0400 #define NO_BITMAP_COMPRESSION_HDR 0x0400
/* [MS-RDPBCGR], TS_BITMAP_DATA, flags */
#define BITMAP_COMPRESSION 0x0001
/* orderFlags, [MS-RDPBCGR] 2.2.7.1.3 */ /* orderFlags, [MS-RDPBCGR] 2.2.7.1.3 */
#define NEGOTIATEORDERSUPPORT 0x0002 #define NEGOTIATEORDERSUPPORT 0x0002
#define ZEROBOUNDSDELTASSUPPORT 0x0008 #define ZEROBOUNDSDELTASSUPPORT 0x0008

17
cssp.c
View File

@ -595,6 +595,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
STREAM s; STREAM s;
int length; int length;
int tagval; int tagval;
struct stream packet;
s = tcp_recv(NULL, 4); s = tcp_recv(NULL, 4);
@ -622,6 +623,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
// receive the remainings of message // receive the remainings of message
s = tcp_recv(s, length); s = tcp_recv(s, length);
packet = *s;
// parse the response and into nego token // parse the response and into nego token
if (!ber_in_header(s, &tagval, &length) || if (!ber_in_header(s, &tagval, &length) ||
@ -632,6 +634,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
if (!ber_in_header(s, &tagval, &length) || if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0)) tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
return False; return False;
if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
&packet);
}
in_uint8s(s, length); in_uint8s(s, length);
// negoToken [1] // negoToken [1]
@ -653,7 +661,14 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING) if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
return False; return False;
token->end = token->p = token->data; if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
&packet);
}
s_realloc(token, length);
s_reset(token);
out_uint8p(token, s->p, length); out_uint8p(token, s->p, length);
s_mark_end(token); s_mark_end(token);
} }

View File

@ -1,7 +1,8 @@
/* -*- c-basic-offset: 8 -*- /* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Support for the Matrox "lspci" channel Support for the Matrox "lspci" channel
Copyright (C) 2005 Matrox Graphics Inc. Copyright (C) 2005 Matrox Graphics Inc.
Copyright 2018 Henrik Andersson <hean01@cendio.se> for Cendio AB
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -134,6 +135,12 @@ lspci_process(STREAM s)
unsigned int pkglen; unsigned int pkglen;
static char *rest = NULL; static char *rest = NULL;
char *buf; char *buf;
struct stream packet = *s;
if (!s_check(s))
{
rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
}
pkglen = s->end - s->p; pkglen = s->end - s->p;
/* str_handle_lines requires null terminated strings */ /* str_handle_lines requires null terminated strings */

20
mcs.c
View File

@ -45,9 +45,16 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
static RD_BOOL static RD_BOOL
mcs_parse_domain_params(STREAM s) mcs_parse_domain_params(STREAM s)
{ {
int length; uint32 length;
struct stream packet = *s;
ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length); ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
}
in_uint8s(s, length); in_uint8s(s, length);
return s_check(s); return s_check(s);
@ -89,8 +96,9 @@ mcs_recv_connect_response(STREAM mcs_data)
{ {
UNUSED(mcs_data); UNUSED(mcs_data);
uint8 result; uint8 result;
int length; uint32 length;
STREAM s; STREAM s;
struct stream packet;
RD_BOOL is_fastpath; RD_BOOL is_fastpath;
uint8 fastpath_hdr; uint8 fastpath_hdr;
@ -99,6 +107,8 @@ mcs_recv_connect_response(STREAM mcs_data)
if (s == NULL) if (s == NULL)
return False; return False;
packet = *s;
ber_parse_header(s, MCS_CONNECT_RESPONSE, &length); ber_parse_header(s, MCS_CONNECT_RESPONSE, &length);
@ -112,6 +122,12 @@ mcs_recv_connect_response(STREAM mcs_data)
ber_parse_header(s, BER_TAG_INTEGER, &length); ber_parse_header(s, BER_TAG_INTEGER, &length);
in_uint8s(s, length); /* connect id */ in_uint8s(s, length); /* connect id */
if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
}
mcs_parse_domain_params(s); mcs_parse_domain_params(s);
ber_parse_header(s, BER_TAG_OCTET_STRING, &length); ber_parse_header(s, BER_TAG_OCTET_STRING, &length);

View File

@ -1259,11 +1259,17 @@ process_secondary_order(STREAM s)
uint16 flags; uint16 flags;
uint8 type; uint8 type;
uint8 *next_order; uint8 *next_order;
struct stream packet = *s;
in_uint16_le(s, length); in_uint16_le(s, length);
in_uint16_le(s, flags); /* used by bmpcache2 */ in_uint16_le(s, flags); /* used by bmpcache2 */
in_uint8(s, type); in_uint8(s, type);
if (!s_check_rem(s, length + 7))
{
rdp_protocol_error("process_secondary_order(), next order pointer would overrun stream", &packet);
}
next_order = s->p + (sint16) length + 7; next_order = s->p + (sint16) length + 7;
switch (type) switch (type)

View File

@ -164,6 +164,7 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
char *directory, RD_BOOL reconnect); char *directory, RD_BOOL reconnect);
void rdp_reset_state(void); void rdp_reset_state(void);
void rdp_disconnect(void); void rdp_disconnect(void);
void rdp_protocol_error(const char *message, STREAM s);
/* rdpdr.c */ /* rdpdr.c */
int get_device_index(RD_NTHANDLE handle); int get_device_index(RD_NTHANDLE handle);
void convert_to_unix_filename(char *filename); void convert_to_unix_filename(char *filename);
@ -224,7 +225,7 @@ void tcp_run_ui(RD_BOOL run);
/* asn.c */ /* asn.c */
RD_BOOL ber_in_header(STREAM s, int *tagval, int *length); RD_BOOL ber_in_header(STREAM s, int *tagval, int *length);
void ber_out_header(STREAM s, int tagval, int length); void ber_out_header(STREAM s, int tagval, int length);
RD_BOOL ber_parse_header(STREAM s, int tagval, int *length); RD_BOOL ber_parse_header(STREAM s, int tagval, uint32 *length);
void ber_out_integer(STREAM s, int value); void ber_out_integer(STREAM s, int value);
void ber_out_sequence(STREAM s, STREAM contents); void ber_out_sequence(STREAM s, STREAM contents);

202
rdp.c
View File

@ -285,6 +285,19 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
size_t ibl, obl; size_t ibl, obl;
char *pin, *pout; char *pin, *pout;
struct stream packet = *s;
if ((in_len < 0) || ((uint32)in_len >= (RD_UINT32_MAX / 2)))
{
logger(Protocol, Error, "rdp_in_unistr(), length of unicode data is out of bounds.");
abort();
}
if (!s_check_rem(s, in_len))
{
rdp_protocol_error("rdp_in_unistr(), consume of unicode data from stream would overrun", &packet);
}
// if not already open // if not already open
if (!icv_utf16_to_local) if (!icv_utf16_to_local)
{ {
@ -1211,6 +1224,7 @@ process_demand_active(STREAM s)
{ {
uint8 type; uint8 type;
uint16 len_src_descriptor, len_combined_caps; uint16 len_src_descriptor, len_combined_caps;
struct stream packet = *s;
/* at this point we need to ensure that we have ui created */ /* at this point we need to ensure that we have ui created */
rd_create_ui(); rd_create_ui();
@ -1218,6 +1232,11 @@ process_demand_active(STREAM s)
in_uint32_le(s, g_rdp_shareid); in_uint32_le(s, g_rdp_shareid);
in_uint16_le(s, len_src_descriptor); in_uint16_le(s, len_src_descriptor);
in_uint16_le(s, len_combined_caps); in_uint16_le(s, len_combined_caps);
if (!s_check_rem(s, len_src_descriptor))
{
rdp_protocol_error("rdp_demand_active(), consume of source descriptor from stream would overrun", &packet);
}
in_uint8s(s, len_src_descriptor); in_uint8s(s, len_src_descriptor);
logger(Protocol, Debug, "process_demand_active(), shareid=0x%x", g_rdp_shareid); logger(Protocol, Debug, "process_demand_active(), shareid=0x%x", g_rdp_shareid);
@ -1390,78 +1409,113 @@ process_pointer_pdu(STREAM s)
} }
} }
/* Process bitmap updates */ /* Process TS_BITMAP_DATA */
static void
process_bitmap_data(STREAM s)
{
uint16 left, top, right, bottom, width, height;
uint16 cx, cy, bpp, Bpp, flags, bufsize, size;
uint8 *data, *bmpdata;
logger(Protocol, Debug, "%s()", __func__);
struct stream packet = *s;
in_uint16_le(s, left); /* destLeft */
in_uint16_le(s, top); /* destTop */
in_uint16_le(s, right); /* destRight */
in_uint16_le(s, bottom); /* destBottom */
in_uint16_le(s, width); /* width */
in_uint16_le(s, height); /* height */
in_uint16_le(s, bpp); /*bitsPerPixel */
Bpp = (bpp + 7) / 8;
in_uint16_le(s, flags); /* flags */
in_uint16_le(s, bufsize); /* bitmapLength */
cx = right - left + 1;
cy = bottom - top + 1;
/* FIXME: There are a assumtion that we do not consider in
this code. The value of bpp is not passed to
ui_paint_bitmap() which relies on g_server_bpp for drawing
the bitmap data.
Does this means that we can sanity check bpp with g_server_bpp ?
*/
if (Bpp == 0 || width == 0 || height == 0)
{
logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
left, top, right, bottom, width, height, bpp, flags);
rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
}
if ((RD_UINT32_MAX / Bpp) <= (width * height))
{
logger(Protocol, Warning, "%s(), [%d,%d,%d,%d], [%d,%d], bpp=%d, flags=%x", __func__,
left, top, right, bottom, width, height, bpp, flags);
rdp_protocol_error("TS_BITMAP_DATA, unsafe size of bitmap data received from server", &packet);
}
if (flags == 0)
{
/* read uncompressed bitmap data */
int y;
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
for (y = 0; y < height; y++)
{
in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)], width * Bpp);
}
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
xfree(bmpdata);
return;
}
if (flags & NO_BITMAP_COMPRESSION_HDR)
{
size = bufsize;
}
else
{
/* Read TS_CD_HEADER */
in_uint8s(s, 2); /* skip cbCompFirstRowSize (must be 0x0000) */
in_uint16_le(s, size); /* cbCompMainBodySize */
in_uint8s(s, 2); /* skip cbScanWidth */
in_uint8s(s, 2); /* skip cbUncompressedSize */
}
/* read compressed bitmap data */
if (!s_check_rem(s, size))
{
rdp_protocol_error("process_bitmap_data(), consume of bitmap data from stream would overrun", &packet);
}
in_uint8p(s, data, size);
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
{
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
}
else
{
logger(Protocol, Warning, "%s(), failed to decompress bitmap", __func__);
}
xfree(bmpdata);
}
/* Process TS_UPDATE_BITMAP_DATA */
void void
process_bitmap_updates(STREAM s) process_bitmap_updates(STREAM s)
{ {
uint16 num_updates;
uint16 left, top, right, bottom, width, height;
uint16 cx, cy, bpp, Bpp, compress, bufsize, size;
uint8 *data, *bmpdata;
int i; int i;
uint16 num_updates;
logger(Protocol, Debug, "%s()", __func__);
in_uint16_le(s, num_updates); /* rectangles */
in_uint16_le(s, num_updates);
for (i = 0; i < num_updates; i++) for (i = 0; i < num_updates; i++)
{ {
in_uint16_le(s, left); process_bitmap_data(s);
in_uint16_le(s, top);
in_uint16_le(s, right);
in_uint16_le(s, bottom);
in_uint16_le(s, width);
in_uint16_le(s, height);
in_uint16_le(s, bpp);
Bpp = (bpp + 7) / 8;
in_uint16_le(s, compress);
in_uint16_le(s, bufsize);
cx = right - left + 1;
cy = bottom - top + 1;
logger(Graphics, Debug,
"process_bitmap_updates(), [%d,%d,%d,%d], [%d,%d], bpp=%d, compression=%d",
left, top, right, bottom, width, height, Bpp, compress);
if (!compress)
{
int y;
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
for (y = 0; y < height; y++)
{
in_uint8a(s, &bmpdata[(height - y - 1) * (width * Bpp)],
width * Bpp);
}
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
xfree(bmpdata);
continue;
}
if (compress & 0x400)
{
size = bufsize;
}
else
{
in_uint8s(s, 2); /* pad */
in_uint16_le(s, size);
in_uint8s(s, 4); /* line_size, final_size */
}
in_uint8p(s, data, size);
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
{
ui_paint_bitmap(left, top, cx, cy, width, height, bmpdata);
}
else
{
logger(Graphics, Warning,
"process_bitmap_updates(), failed to decompress bitmap");
}
xfree(bmpdata);
} }
} }
@ -2013,3 +2067,21 @@ rdp_disconnect(void)
logger(Protocol, Debug, "%s()", __func__); logger(Protocol, Debug, "%s()", __func__);
sec_disconnect(); sec_disconnect();
} }
/* Abort rdesktop upon protocol error
A protocol error is defined as:
- A value is outside specified range for example;
bpp for a bitmap is not allowed to be greater than the
value 32 but is represented by a byte in protocol.
*/
void
rdp_protocol_error(const char *message, STREAM s)
{
logger(Protocol, Error, "%s(), %s", __func__, message);
if (s)
hexdump(s->p, s_length(s));
exit(0);
}

11
rdpdr.c
View File

@ -854,6 +854,7 @@ rdpdr_process(STREAM s)
uint16 vmin; uint16 vmin;
uint16 component; uint16 component;
uint16 pakid; uint16 pakid;
struct stream packet = *s;
logger(Protocol, Debug, "rdpdr_process()"); logger(Protocol, Debug, "rdpdr_process()");
/* hexdump(s->p, s->end - s->p); */ /* hexdump(s->p, s->end - s->p); */
@ -873,8 +874,18 @@ rdpdr_process(STREAM s)
/* DR_CORE_SERVER_ANNOUNCE_REQ */ /* DR_CORE_SERVER_ANNOUNCE_REQ */
in_uint8s(s, 2); /* skip versionMajor */ in_uint8s(s, 2); /* skip versionMajor */
in_uint16_le(s, vmin); /* VersionMinor */ in_uint16_le(s, vmin); /* VersionMinor */
in_uint32_le(s, g_client_id); /* ClientID */ in_uint32_le(s, g_client_id); /* ClientID */
/* g_client_id is sent back to server,
so lets check that we actually got
valid data from stream to prevent
that we leak back data to server */
if (!s_check(s))
{
rdp_protocol_error("rdpdr_process(), consume of g_client_id from stream did overrun", &packet);
}
/* The RDP client is responsibility to provide a random client id /* The RDP client is responsibility to provide a random client id
if server version is < 12 */ if server version is < 12 */
if (vmin < 0x000c) if (vmin < 0x000c)

View File

@ -269,6 +269,12 @@ rdpsnd_process_training(STREAM in)
uint16 tick; uint16 tick;
uint16 packsize; uint16 packsize;
STREAM out; STREAM out;
struct stream packet = *in;
if (!s_check_rem(in, 4))
{
rdp_protocol_error("rdpsnd_process_training(), consume of training data from stream would overrun", &packet);
}
in_uint16_le(in, tick); in_uint16_le(in, tick);
in_uint16_le(in, packsize); in_uint16_le(in, packsize);
@ -445,6 +451,11 @@ rdpsnddbg_process(STREAM s)
static char *rest = NULL; static char *rest = NULL;
char *buf; char *buf;
if (!s_check(s))
{
rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
}
pkglen = s->end - s->p; pkglen = s->end - s->p;
/* str_handle_lines requires null terminated strings */ /* str_handle_lines requires null terminated strings */
buf = (char *) xmalloc(pkglen + 1); buf = (char *) xmalloc(pkglen + 1);

View File

@ -168,6 +168,12 @@ seamless_process_line(const char *line, void *data)
icon_buf[len] = strtol(byte, NULL, 16); icon_buf[len] = strtol(byte, NULL, 16);
len++; len++;
if ((size_t)len >= sizeof(icon_buf))
{
logger(Protocol, Warning, "seamless_process_line(), icon data would overrun icon_buf");
break;
}
} }
ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len); ui_seamless_seticon(id, tok5, width, height, chunk, icon_buf, len);
@ -370,6 +376,12 @@ seamless_process(STREAM s)
{ {
unsigned int pkglen; unsigned int pkglen;
char *buf; char *buf;
struct stream packet = *s;
if (!s_check(s))
{
rdp_protocol_error("seamless_process(), stream is in unstable state", &packet);
}
pkglen = s->end - s->p; pkglen = s->end - s->p;
/* str_handle_lines requires null terminated strings */ /* str_handle_lines requires null terminated strings */

View File

@ -296,6 +296,9 @@ sec_encrypt(uint8 * data, int length)
void void
sec_decrypt(uint8 * data, int length) sec_decrypt(uint8 * data, int length)
{ {
if (length <= 0)
return;
if (g_sec_decrypt_use_count == 4096) if (g_sec_decrypt_use_count == 4096)
{ {
sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key); sec_update(g_sec_decrypt_key, g_sec_decrypt_update_key);
@ -848,9 +851,11 @@ sec_recv(RD_BOOL * is_fastpath)
uint16 sec_flags; uint16 sec_flags;
uint16 channel; uint16 channel;
STREAM s; STREAM s;
struct stream packet;
while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL) while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
{ {
packet = *s;
if (*is_fastpath == True) if (*is_fastpath == True)
{ {
/* If fastpath packet is encrypted, read data /* If fastpath packet is encrypted, read data
@ -859,6 +864,10 @@ sec_recv(RD_BOOL * is_fastpath)
fastpath_flags = (fastpath_hdr & 0xC0) >> 6; fastpath_flags = (fastpath_hdr & 0xC0) >> 6;
if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED) if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
{ {
if (!s_check_rem(s, 8)) {
rdp_protocol_error("sec_recv(), consume fastpath signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */ in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p); sec_decrypt(s->p, s->end - s->p);
} }
@ -875,6 +884,10 @@ sec_recv(RD_BOOL * is_fastpath)
{ {
if (sec_flags & SEC_ENCRYPT) if (sec_flags & SEC_ENCRYPT)
{ {
if (!s_check_rem(s, 8)) {
rdp_protocol_error("sec_recv(), consume encrypt signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */ in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p); sec_decrypt(s->p, s->end - s->p);
} }
@ -889,6 +902,10 @@ sec_recv(RD_BOOL * is_fastpath)
{ {
uint8 swapbyte; uint8 swapbyte;
if (!s_check_rem(s, 8)) {
rdp_protocol_error("sec_recv(), consume redirect signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */ in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p); sec_decrypt(s->p, s->end - s->p);

View File

@ -54,7 +54,7 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
#define s_pop_layer(s,h) (s)->p = (s)->h; #define s_pop_layer(s,h) (s)->p = (s)->h;
#define s_mark_end(s) (s)->end = (s)->p; #define s_mark_end(s) (s)->end = (s)->p;
#define s_check(s) ((s)->p <= (s)->end) #define s_check(s) ((s)->p <= (s)->end)
#define s_check_rem(s,n) ((s)->p + n <= (s)->end) #define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
#define s_check_end(s) ((s)->p == (s)->end) #define s_check_end(s) ((s)->p == (s)->end)
#define s_length(s) ((s)->end - (s)->data) #define s_length(s) ((s)->end - (s)->data)
#define s_left(s) ((s)->size - ((s)->p - (s)->data)) #define s_left(s) ((s)->size - ((s)->p - (s)->data))

View File

@ -43,6 +43,8 @@ typedef signed short sint16;
typedef unsigned int uint32; typedef unsigned int uint32;
typedef signed int sint32; typedef signed int sint32;
#define RD_UINT32_MAX (uint32)(-1)
typedef void *RD_HBITMAP; typedef void *RD_HBITMAP;
typedef void *RD_HGLYPH; typedef void *RD_HGLYPH;
typedef void *RD_HCOLOURMAP; typedef void *RD_HCOLOURMAP;