Avoid poking around in STREAM internals

It's easy to make mistakes this way, and bypassed the normal bounds
checking. So make sure we always use macros or functions.
This commit is contained in:
Pierre Ossman 2019-04-09 13:35:46 +02:00
parent 489c43f382
commit 25b8412333
23 changed files with 469 additions and 359 deletions

View File

@ -186,7 +186,6 @@ void
channel_process(STREAM s, uint16 mcs_channel)
{
uint32 length, flags;
uint32 thislength;
VCHANNEL *channel = NULL;
unsigned int i;
STREAM in;
@ -214,22 +213,16 @@ channel_process(STREAM s, uint16 mcs_channel)
in = &channel->in;
if (flags & CHANNEL_FLAG_FIRST)
{
if (length > in->size)
{
in->data = (uint8 *) xrealloc(in->data, length);
in->size = length;
}
in->p = in->data;
s_realloc(in, length);
s_reset(in);
}
thislength = MIN(s_remaining(s), in->data + in->size - in->p);
memcpy(in->p, s->p, thislength);
in->p += thislength;
out_uint8stream(in, s, s_remaining(s));
if (flags & CHANNEL_FLAG_LAST)
{
in->end = in->p;
in->p = in->data;
s_mark_end(in);
s_seek(in, 0);
channel->process(in);
}
}

View File

@ -119,21 +119,14 @@ cliprdr_process(STREAM s)
uint16 type, status;
uint32 length, format;
uint8 *data;
struct stream packet = *s;
in_uint16_le(s, type);
in_uint16_le(s, status);
in_uint32_le(s, length);
data = s->p;
logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
length);
if (!s_check_rem(s, length))
{
rdp_protocol_error("consume of packet from stream would overrun", &packet);
}
if (status == CLIPRDR_ERROR)
{
switch (type)
@ -161,6 +154,7 @@ cliprdr_process(STREAM s)
ui_clip_sync();
break;
case CLIPRDR_FORMAT_ANNOUNCE:
in_uint8p(s, data, length);
ui_clip_format_announce(data, length);
cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
return;
@ -171,6 +165,7 @@ cliprdr_process(STREAM s)
ui_clip_request_data(format);
break;
case CLIPRDR_DATA_RESPONSE:
in_uint8p(s, data, length);
ui_clip_handle_data(data, length);
break;
case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */

87
cssp.c
View File

@ -38,7 +38,7 @@ ber_wrap_hdr_data(int tagval, STREAM in)
out = s_alloc(size);
ber_out_header(out, tagval, s_length(in));
out_uint8a(out, in->data, s_length(in));
out_stream(out, in);
s_mark_end(out);
return out;
@ -148,8 +148,10 @@ cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in)
gss_buffer_desc inbuf, outbuf;
STREAM out;
inbuf.value = in->data;
s_seek(in, 0);
inbuf.length = s_length(in);
in_uint8p(in, inbuf.value, s_length(in));
s_seek(in, 0);
major_status = gss_wrap(&minor_status, ctx, True,
GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf);
@ -189,8 +191,10 @@ cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in)
int conf_state;
STREAM out;
inbuf.value = in->data;
s_seek(in, 0);
inbuf.length = s_length(in);
in_uint8p(in, inbuf.value, s_length(in));
s_seek(in, 0);
major_status = gss_unwrap(&minor_status, ctx, &inbuf, &outbuf, &conf_state, &qop_state);
@ -231,7 +235,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -244,7 +248,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -256,7 +260,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -292,7 +296,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -306,7 +310,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -321,7 +325,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -336,7 +340,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -351,7 +355,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -384,7 +388,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -394,7 +398,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
g_sc_container_name, g_sc_csp_name);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -408,7 +412,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -423,7 +427,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -464,7 +468,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -482,7 +486,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain)
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h3);
s_free(h2);
@ -518,7 +522,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -532,7 +536,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
h2 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, h3);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h5);
s_free(h4);
@ -548,7 +552,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_free(h2);
s_free(h1);
@ -561,7 +565,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1));
out_uint8a(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -572,7 +576,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
// Todo: can h1 be send directly instead of tcp_init() approach
h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
s = tcp_init(s_length(h1));
out_uint8a(s, h1->data, s_length(h1));
out_stream(s, h1);
s_mark_end(s);
s_free(h1);
@ -600,34 +604,21 @@ cssp_read_tsrequest(RD_BOOL pubkey)
if (s == NULL)
return NULL;
// verify ASN.1 header
if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
{
logger(Protocol, Error,
"cssp_read_tsrequest(), expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x",
s->p[0]);
return NULL;
}
// peek at first 4 bytes to get full message length
if (s->p[1] < 0x80)
length = s->p[1] - 2;
else if (s->p[1] == 0x81)
length = s->p[2] - 1;
else if (s->p[1] == 0x82)
length = (s->p[2] << 8) | s->p[3];
else
return NULL;
// receive the remainings of message
s = tcp_recv(s, length);
packet = *s;
// parse the response and into nego token
// get and verify the header
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return NULL;
// We've already read 4 bytes, but the header might have been
// less than that, so we need to adjust the length
length -= s_remaining(s);
// receive the remainings of message
s = tcp_recv(s, length);
if (s == NULL)
return NULL;
packet = *s;
// version [0]
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
@ -666,7 +657,7 @@ cssp_read_tsrequest(RD_BOOL pubkey)
}
out = s_alloc(length);
out_uint8a(out, s->p, length);
out_uint8stream(out, s, length);
s_mark_end(out);
s_seek(out, 0);
}
@ -681,7 +672,7 @@ cssp_read_tsrequest(RD_BOOL pubkey)
return NULL;
out = s_alloc(length);
out_uint8a(out, s->p, length);
out_uint8stream(out, s, length);
s_mark_end(out);
s_seek(out, 0);
}

View File

@ -277,6 +277,7 @@ licence_process_platform_challenge(STREAM s)
static void
licence_process_new_license(STREAM s)
{
unsigned char *data;
RDSSL_RC4 crypt_key;
uint32 length;
int i;
@ -286,8 +287,12 @@ licence_process_new_license(STREAM s)
if (!s_check_rem(s, length))
return;
inout_uint8p(s, data, length);
rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
rdssl_rc4_crypt(&crypt_key, s->p, s->p, length);
rdssl_rc4_crypt(&crypt_key, data, data, length);
s_seek(s, s_tell(s) - length);
/* Parse NEW_LICENSE_INFO block */
in_uint8s(s, 4); // skip dwVersion
@ -304,7 +309,8 @@ licence_process_new_license(STREAM s)
}
g_licence_issued = True;
save_licence(s->p, length);
in_uint8p(s, data, length);
save_licence(data, length);
}
/* process a licence error alert packet */

View File

@ -139,7 +139,8 @@ lspci_process(STREAM s)
pkglen = s_remaining(s);
/* str_handle_lines requires null terminated strings */
buf = xmalloc(pkglen + 1);
STRNCPY(buf, (char *) s->p, pkglen + 1);
in_uint8a(s, buf, pkglen);
buf[pkglen] = '\0';
str_handle_lines(buf, &rest, lspci_process_line, NULL);
xfree(buf);
}

9
mcs.c
View File

@ -62,7 +62,7 @@ mcs_parse_domain_params(STREAM s)
static void
mcs_send_connect_initial(STREAM mcs_data)
{
int datalen = mcs_data->end - mcs_data->data;
int datalen = s_length(mcs_data);
int length = 9 + 3 * 34 + 4 + datalen;
STREAM s;
logger(Protocol, Debug, "%s()", __func__);
@ -139,9 +139,10 @@ mcs_recv_connect_response(STREAM mcs_data)
length = mcs_data->size;
}
in_uint8a(s, mcs_data->data, length);
mcs_data->p = mcs_data->data;
mcs_data->end = mcs_data->data + length;
s_reset(mcs_data);
in_uint8stream(s, mcs_data, length);
s_mark_end(mcs_data);
s_seek(mcs_data, 0);
*/
return s_check_end(s);
}

View File

@ -20,7 +20,7 @@
#include "rdesktop.h"
#include "orders.h"
extern uint8 *g_next_packet;
extern size_t g_next_packet;
static RDP_ORDER_STATE g_order_state;
extern RDP_VERSION g_rdp_version;
@ -1252,7 +1252,7 @@ process_secondary_order(STREAM s)
sint16 length;
uint16 flags;
uint8 type;
uint8 *next_order;
size_t next_order;
struct stream packet = *s;
in_uint16_le(s, length);
@ -1269,7 +1269,7 @@ process_secondary_order(STREAM s)
rdp_protocol_error("next order pointer would overrun stream", &packet);
}
next_order = s->p + length;
next_order = s_tell(s) + length;
switch (type)
{
@ -1306,7 +1306,7 @@ process_secondary_order(STREAM s)
"process_secondary_order(), unhandled secondary order %d", type);
}
s->p = next_order;
s_seek(s, next_order);
}
/* Process an order PDU */
@ -1448,9 +1448,9 @@ process_orders(STREAM s, uint16 num_orders)
}
#if 0
/* not true when RDP_COMPRESSION is set */
if (s->p != g_next_packet)
if (s_tell(s) != g_next_packet)
logger(Graphics, Error, "process_orders(), %d bytes remaining",
(int) (g_next_packet - s->p));
(int) (g_next_packet - s_tell(s)));
#endif
}

View File

@ -238,6 +238,8 @@ printercache_process(STREAM s)
{
uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
char device_name[9], *printer, *driver;
size_t blob_start;
unsigned char *blob;
printer = driver = NULL;
@ -279,8 +281,10 @@ printercache_process(STREAM s)
{
rdp_in_unistr(s, printer_unicode_length, &printer,
&printer_unicode_length);
if (printer)
printercache_save_blob(printer, s->p, blob_length);
if (printer) {
in_uint8p(s, blob, blob_length);
printercache_save_blob(printer, blob, blob_length);
}
free(printer);
}
break;
@ -289,6 +293,7 @@ printercache_process(STREAM s)
in_uint8a(s, device_name, 5); /* get LPTx/COMx name */
/* need to fetch this data so that we can get the length of the packet to store. */
blob_start = s_tell(s);
in_uint8s(s, 0x2); /* ??? */
in_uint8s(s, 0x2) /* pad?? */
in_uint32_be(s, driver_length);
@ -302,10 +307,11 @@ printercache_process(STREAM s)
/* rewind stream so that we can save this blob */
/* length is driver_length + printer_length + 19 */
/* rewind stream */
s->p = s->p - 19;
s_seek(s, blob_start);
printercache_save_blob(device_name, s->p,
driver_length + printer_length + 19);
blob_length = driver_length + printer_length + 19;
in_uint8p(s, blob, blob_length);
printercache_save_blob(device_name, blob, blob_length);
break;
default:
logger(Protocol, Warning,

73
rdp.c
View File

@ -59,7 +59,7 @@ extern RD_BOOL g_dynamic_session_resize;
RD_BOOL g_exit_mainloop = False;
uint8 *g_next_packet;
size_t g_next_packet;
uint32 g_rdp_shareid;
extern RDPCOMP g_mppc_dict;
@ -128,6 +128,9 @@ rdp_ts_in_share_control_header(STREAM s, uint8 * type, uint16 * length)
*type = pdu_type & 0xf;
/* Give just the size of the data */
*length -= 6;
return True;
}
@ -142,7 +145,7 @@ rdp_recv(uint8 * type)
while (1)
{
/* fill stream with data if needed for parsing a new packet */
if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
if (g_next_packet == 0)
{
rdp_s = sec_recv(&is_fastpath);
if (rdp_s == NULL)
@ -155,11 +158,16 @@ rdp_recv(uint8 * type)
continue;
}
g_next_packet = rdp_s->p;
g_next_packet = s_tell(rdp_s);
}
else
{
rdp_s->p = g_next_packet;
s_seek(rdp_s, g_next_packet);
if (s_check_end(rdp_s))
{
g_next_packet = 0;
continue;
}
}
/* parse a TS_SHARECONTROLHEADER */
@ -171,7 +179,13 @@ rdp_recv(uint8 * type)
logger(Protocol, Debug, "rdp_recv(), RDP packet #%d, type 0x%x", ++g_packetno, *type);
g_next_packet += length;
if (!s_check_rem(rdp_s, length))
{
rdp_protocol_error("not enough data for PDU", rdp_s);
}
g_next_packet = s_tell(rdp_s) + length;
return rdp_s;
}
@ -241,7 +255,8 @@ rdp_out_unistr(STREAM s, char *string, int len)
*/
static iconv_t icv_local_to_utf16;
size_t ibl, obl;
char *pin, *pout;
char *pin;
unsigned char *pout;
if (string == NULL || len == 0)
@ -263,18 +278,16 @@ rdp_out_unistr(STREAM s, char *string, int len)
ibl = strlen(string);
obl = len + 2;
pin = string;
pout = (char *) s->p;
out_uint8p(s, pout, len + 2);
memset(pout, 0, len + 4);
memset(pout, 0, len + 2);
if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, (char **)&pout, &obl) == (size_t) - 1)
{
logger(Protocol, Error, "rdp_out_unistr(), iconv(2) fail, errno %d", errno);
abort();
}
s->p += len + 2;
}
/* Input a string in Unicode
@ -286,7 +299,8 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
{
static iconv_t icv_utf16_to_local;
size_t ibl, obl;
char *pin, *pout;
unsigned char *pin;
char *pout;
struct stream packet = *s;
@ -323,7 +337,7 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
ibl = in_len;
obl = *str_size - 1;
pin = (char *) s->p;
in_uint8p(s, pin, in_len);
pout = *string;
if (iconv(icv_utf16_to_local, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
@ -344,9 +358,6 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
abort();
}
/* we must update the location of the current STREAM for future reads of s->p */
s->p += in_len;
*pout = 0;
if (*string)
@ -1219,25 +1230,25 @@ static void
rdp_process_server_caps(STREAM s, uint16 length)
{
int n;
uint8 *next, *start;
size_t next, start;
uint16 ncapsets, capset_type, capset_length;
logger(Protocol, Debug, "%s()", __func__);
start = s->p;
start = s_tell(s);
in_uint16_le(s, ncapsets);
in_uint8s(s, 2); /* pad */
for (n = 0; n < ncapsets; n++)
{
if (s->p > start + length)
if (s_tell(s) > start + length)
return;
in_uint16_le(s, capset_type);
in_uint16_le(s, capset_length);
next = s->p + capset_length - 4;
next = s_tell(s) + capset_length - 4;
switch (capset_type)
{
@ -1256,7 +1267,7 @@ rdp_process_server_caps(STREAM s, uint16 length)
break;
}
s->p = next;
s_seek(s, next);
}
}
@ -1726,6 +1737,7 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
uint16 clen;
uint32 len;
uint8 *buf;
uint32 roff, rlen;
struct stream *ns = &(g_mppc_dict.ns);
@ -1742,21 +1754,22 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
if (len > RDP_MPPC_DICT_SIZE)
logger(Protocol, Error,
"process_data_pdu(), error decompressed packet size exceeds max");
if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
in_uint8p(s, buf, clen);
if (mppc_expand(buf, clen, ctype, &roff, &rlen) == -1)
logger(Protocol, Error,
"process_data_pdu(), error while decompressing packet");
/* len -= 18; */
/* allocate memory and copy the uncompressed data into the temporary stream */
ns->data = (uint8 *) xrealloc(ns->data, rlen);
s_realloc(ns, rlen);
s_reset(ns);
memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen);
ns->size = rlen;
ns->end = (ns->data + ns->size);
ns->p = ns->data;
ns->rdp_hdr = ns->p;
s_mark_end(ns);
s_seek(ns, 0);
s_push_layer(ns, rdp_hdr, 0);
s = ns;
}
@ -2056,7 +2069,7 @@ rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
logger(Protocol, Warning,
"rdp_loop(), unhandled PDU type %d received", type);
}
cont = g_next_packet < s->end;
cont = g_next_packet < s_length(s);
}
return True;
}
@ -2094,7 +2107,7 @@ void
rdp_reset_state(void)
{
logger(Protocol, Debug, "%s()", __func__);
g_next_packet = NULL; /* reset the packet information */
g_next_packet = 0; /* reset the packet information */
g_rdp_shareid = 0;
g_exit_mainloop = False;
g_first_bitmap_caps = True;

30
rdp5.c
View File

@ -21,7 +21,7 @@
#include "rdesktop.h"
extern uint8 *g_next_packet;
extern size_t g_next_packet;
extern RDPCOMP g_mppc_dict;
@ -78,8 +78,9 @@ process_ts_fp_updates(STREAM s)
{
uint16 length;
uint8 hdr, code, frag, comp, ctype = 0;
uint8 *next;
size_t next;
uint8 *buf;
uint32 roff, rlen;
struct stream *ns = &(g_mppc_dict.ns);
struct stream *ts;
@ -87,7 +88,7 @@ process_ts_fp_updates(STREAM s)
static STREAM assembled[16] = { 0 };
ui_begin_update();
while (s->p < s->end)
while (!s_check_end(s))
{
/* Reading a number of TS_FP_UPDATE structures from the stream here.. */
in_uint8(s, hdr); /* updateHeader */
@ -100,23 +101,24 @@ process_ts_fp_updates(STREAM s)
in_uint16_le(s, length); /* length */
g_next_packet = next = s->p + length;
g_next_packet = next = s_tell(s) + length;
if (ctype & RDP_MPPC_COMPRESSED)
{
if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1)
in_uint8p(s, buf, length);
if (mppc_expand(buf, length, ctype, &roff, &rlen) == -1)
logger(Protocol, Error,
"process_ts_fp_update_pdu(), error while decompressing packet");
/* allocate memory and copy the uncompressed data into the temporary stream */
ns->data = (uint8 *) xrealloc(ns->data, rlen);
s_realloc(ns, rlen);
s_reset(ns);
memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen);
ns->size = rlen;
ns->end = (ns->data + ns->size);
ns->p = ns->data;
ns->rdp_hdr = ns->p;
s_mark_end(ns);
s_seek(ns, 0);
s_push_layer(ns, rdp_hdr, 0);
length = rlen;
ts = ns;
@ -140,17 +142,17 @@ process_ts_fp_updates(STREAM s)
s_reset(assembled[code]);
}
out_uint8a(assembled[code], ts->p, length);
out_uint8stream(assembled[code], ts, length);
if (frag == FASTPATH_FRAGMENT_LAST)
{
s_mark_end(assembled[code]);
assembled[code]->p = assembled[code]->data;
s_seek(assembled[code], 0);
process_ts_fp_update_by_code(assembled[code], code);
}
}
s->p = next;
s_seek(s, next);
}
ui_end_update();
}

119
rdpdr.c
View File

@ -411,7 +411,6 @@ rdpdr_process_irp(STREAM s)
request,
file,
info_level,
buffer_len,
id,
major,
minor,
@ -424,8 +423,8 @@ rdpdr_process_irp(STREAM s)
char *filename;
uint32 filename_len;
uint8 *buffer, *pst_buf;
struct stream out;
uint8 *pst_buf;
STREAM out;
DEVICE_FNS *fns;
RD_BOOL rw_blocking = True;
RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST;
@ -438,16 +437,13 @@ rdpdr_process_irp(STREAM s)
filename = NULL;
buffer_len = 0;
buffer = (uint8 *) xmalloc(1024);
buffer[0] = 0;
out = NULL;
if (device >= RDPDR_MAX_DEVICES)
{
logger(Protocol, Error,
"rdpdr_process_irp(), invalid irp device=0x%lx, file=0x%lx, id=0x%lx, major=0x%lx, minor=0x%lx",
device, file, id, major, minor);
xfree(buffer);
return;
}
@ -486,7 +482,6 @@ rdpdr_process_irp(STREAM s)
logger(Protocol, Error,
"rdpdr_process_irp(), received IRP for unknown device type %ld",
device);
xfree(buffer);
return;
}
@ -520,7 +515,9 @@ rdpdr_process_irp(STREAM s)
flags_and_attributes, filename, &result);
free(filename);
buffer_len = 1;
out = s_alloc(1);
out_uint8(out, 0);
s_mark_end(out);
break;
case IRP_MJ_CLOSE:
@ -557,14 +554,14 @@ rdpdr_process_irp(STREAM s)
if (rw_blocking) /* Complete read immediately */
{
buffer = (uint8 *) xrealloc((void *) buffer, length);
if (!buffer)
{
status = RD_STATUS_CANCELLED;
break;
}
uint8* buffer;
out = s_alloc(length);
out_uint8p(out, buffer, length);
status = fns->read(file, buffer, length, offset, &result);
buffer_len = result;
/* Might have read less */
s_mark_end(out);
s_seek(out, result);
s_mark_end(out);
break;
}
@ -588,7 +585,9 @@ rdpdr_process_irp(STREAM s)
break;
case IRP_MJ_WRITE:
buffer_len = 1;
out = s_alloc(1);
out_uint8(out, 0);
s_mark_end(out);
if (!fns->write)
{
@ -612,7 +611,9 @@ rdpdr_process_irp(STREAM s)
if (rw_blocking) /* Complete immediately */
{
status = fns->write(file, s->p, length, offset, &result);
unsigned char *data;
in_uint8p(s, data, length);
status = fns->write(file, data, length, offset, &result);
break;
}
@ -645,10 +646,10 @@ rdpdr_process_irp(STREAM s)
}
in_uint32_le(s, info_level);
out.data = out.p = buffer;
out.size = sizeof(buffer);
status = disk_query_information(file, info_level, &out);
result = buffer_len = out.p - out.data;
out = s_alloc(1024);
status = disk_query_information(file, info_level, out);
s_mark_end(out);
result = s_length(out);
break;
@ -662,10 +663,10 @@ rdpdr_process_irp(STREAM s)
in_uint32_le(s, info_level);
out.data = out.p = buffer;
out.size = sizeof(buffer);
status = disk_set_information(file, info_level, s, &out);
result = buffer_len = out.p - out.data;
out = s_alloc(1024);
status = disk_set_information(file, info_level, s, out);
s_mark_end(out);
result = s_length(out);
break;
case IRP_MJ_QUERY_VOLUME_INFORMATION:
@ -678,10 +679,10 @@ rdpdr_process_irp(STREAM s)
in_uint32_le(s, info_level);
out.data = out.p = buffer;
out.size = sizeof(buffer);
status = disk_query_volume_information(file, info_level, &out);
result = buffer_len = out.p - out.data;
out = s_alloc(1024);
status = disk_query_volume_information(file, info_level, out);
s_mark_end(out);
result = s_length(out);
break;
case IRP_MJ_DIRECTORY_CONTROL:
@ -707,13 +708,16 @@ rdpdr_process_irp(STREAM s)
convert_to_unix_filename(filename);
}
out.data = out.p = buffer;
out.size = sizeof(buffer);
out = s_alloc(1024);
status = disk_query_directory(file, info_level, filename,
&out);
result = buffer_len = out.p - out.data;
if (!buffer_len)
buffer_len++;
out);
s_mark_end(out);
if (!s_length(out))
{
out_uint8(out, 0);
s_mark_end(out);
}
result = s_length(out);
free(filename);
break;
@ -760,23 +764,14 @@ rdpdr_process_irp(STREAM s)
in_uint8s(s, 0x14);
/* TODO: Why do we need to increase length by padlen? Or is it hdr len? */
buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
if (!buffer)
{
status = RD_STATUS_CANCELLED;
break;
}
out.data = out.p = buffer;
/* Guess, just a simple mistype. Check others */
//out.size = sizeof(buffer);
out.size = bytes_out + 0x14;
out = s_alloc(bytes_out + 0x14);
#ifdef WITH_SCARD
scardSetInfo(g_epoch, device, id, bytes_out + 0x14);
#endif
status = fns->device_control(file, request, s, &out);
result = buffer_len = out.p - out.data;
status = fns->device_control(file, request, s, out);
s_mark_end(out);
result = s_length(out);
/* Serial SERIAL_WAIT_ON_MASK */
if (status == RD_STATUS_PENDING)
@ -805,12 +800,12 @@ rdpdr_process_irp(STREAM s)
in_uint32_le(s, info_level);
out.data = out.p = buffer;
out.size = sizeof(buffer);
out = s_alloc(1024);
/* FIXME: Perhaps consider actually *do*
something here :-) */
status = RD_STATUS_SUCCESS;
result = buffer_len = out.p - out.data;
s_mark_end(out);
result = s_length(out);
break;
default:
@ -822,11 +817,25 @@ rdpdr_process_irp(STREAM s)
if (status != RD_STATUS_PENDING)
{
size_t buffer_len;
uint8 *buffer;
if (out != NULL)
{
buffer_len = s_length(out);
s_seek(out, 0);
in_uint8p(out, buffer, buffer_len);
}
else
{
buffer_len = 0;
buffer = NULL;
}
rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
}
if (buffer)
xfree(buffer);
buffer = NULL;
if (out)
s_free(out);
}
static void

View File

@ -64,6 +64,7 @@ unsigned int queue_hi, queue_lo, queue_pending;
struct audio_packet packet_queue[MAX_QUEUE];
static uint8 packet_opcode;
static size_t packet_len;
static struct stream packet;
void (*wave_out_play) (void);
@ -295,8 +296,11 @@ static void
rdpsnd_process_packet(uint8 opcode, STREAM s)
{
uint16 vol_left, vol_right;
static uint16 tick, format;
static uint8 packet_index;
uint16 tick, format;
uint8 packet_index;
unsigned int size;
unsigned char *data;
switch (opcode)
{
@ -345,9 +349,12 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
current_format = format;
}
rdpsnd_queue_write(rdpsnd_dsp_process
(s->p, s_remaining(s), current_driver,
&formats[current_format]), tick, packet_index);
size = s_remaining(s);
in_uint8p(s, data, size);
rdpsnd_queue_write(rdpsnd_dsp_process(data, size,
current_driver,
&formats[current_format]),
tick, packet_index);
return;
break;
case SNDC_CLOSE:
@ -382,12 +389,10 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
static void
rdpsnd_process(STREAM s)
{
uint16 len;
while (!s_check_end(s))
{
/* New packet */
if (packet.size == 0)
if (packet_len == 0)
{
if (!s_check_rem(s, 4))
{
@ -397,25 +402,23 @@ rdpsnd_process(STREAM s)
}
in_uint8(s, packet_opcode);
in_uint8s(s, 1); /* Padding */
in_uint16_le(s, len);
in_uint16_le(s, packet_len);
logger(Sound, Debug, "rdpsnd_process(), Opcode = 0x%x Length= %d",
(int) packet_opcode, (int) len);
packet.p = packet.data;
packet.end = packet.data + len;
packet.size = len;
(int) packet_opcode, (int) packet_len);
}
else
{
len = MIN(s_remaining(s), s_remaining(&packet));
uint16 len;
len = MIN(s_remaining(s), packet_len - s_length(&packet));
/* Microsoft's server is so broken it's not even funny... */
if (packet_opcode == SNDC_WAVE)
{
if ((packet.p - packet.data) < 12)
len = MIN(len, 12 - (packet.p - packet.data));
else if ((packet.p - packet.data) == 12)
if (s_length(&packet) < 12)
len = MIN(len, 12 - s_length(&packet));
else if (s_length(&packet) == 12)
{
logger(Sound, Debug,
"rdpsnd_process(), eating 4 bytes of %d bytes...",
@ -425,16 +428,18 @@ rdpsnd_process(STREAM s)
}
}
in_uint8a(s, packet.p, len);
packet.p += len;
in_uint8stream(s, &packet, len);
/* Always end it so s_length() works */
s_mark_end(&packet);
}
/* Packet fully assembled */
if (packet.p == packet.end)
if (s_length(&packet) == packet_len)
{
packet.p = packet.data;
s_seek(&packet, 0);
rdpsnd_process_packet(packet_opcode, &packet);
packet.size = 0;
packet_len = 0;
s_reset(&packet);
}
}
}
@ -457,7 +462,8 @@ rdpsnddbg_process(STREAM s)
pkglen = s_remaining(s);
/* str_handle_lines requires null terminated strings */
buf = (char *) xmalloc(pkglen + 1);
STRNCPY(buf, (char *) s->p, pkglen + 1);
in_uint8a(s, buf, pkglen);
buf[pkglen] = '\0';
str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
@ -513,9 +519,7 @@ rdpsnd_init(char *optarg)
drivers = NULL;
packet.data = (uint8 *) xmalloc(65536);
packet.p = packet.end = packet.data;
packet.size = 0;
s_realloc(&packet, 65536);
rdpsnd_channel =
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,

View File

@ -358,6 +358,8 @@ alsa_play(void)
struct audio_packet *packet;
STREAM out;
int len;
const unsigned char *data;
size_t before;
static long prev_s, prev_us;
int duration;
struct timeval tv;
@ -380,13 +382,21 @@ alsa_play(void)
next_tick = rdpsnd_queue_next_tick();
before = s_tell(out);
len = s_remaining(out) / (samplewidth_out * audiochannels_out);
if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
len = MIN(len, MAX_FRAMES);
in_uint8p(out, data, len);
len = snd_pcm_writei(out_handle, data, len);
if (len < 0)
{
snd_pcm_prepare(out_handle);
len = 0;
}
out->p += (len * samplewidth_out * audiochannels_out);
/* We might not have written everything */
s_seek(out, before + len * samplewidth_out * audiochannels_out);
gettimeofday(&tv, NULL);
@ -395,7 +405,7 @@ alsa_play(void)
if (packet->tick > next_tick)
next_tick += 65536;
if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
if (s_check_end(out) || duration > next_tick - packet->tick + 500)
{
snd_pcm_sframes_t delay_frames;
unsigned long delay_us;

View File

@ -148,6 +148,7 @@ libao_play(void)
{
struct audio_packet *packet;
STREAM out;
unsigned char *data;
int len;
static long prev_s, prev_us;
int duration;
@ -172,8 +173,8 @@ libao_play(void)
next_tick = rdpsnd_queue_next_tick();
len = MIN(WAVEOUTLEN, s_remaining(out));
ao_play(o_device, (char *) out->p, len);
out->p += len;
in_uint8p(out, data, len);
ao_play(o_device, (char *) data, len);
gettimeofday(&tv, NULL);
@ -182,7 +183,7 @@ libao_play(void)
if (packet->tick > next_tick)
next_tick += 65536;
if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
if (s_check_end(out) || duration > next_tick - packet->tick + 500)
{
unsigned int delay_us;

View File

@ -402,6 +402,8 @@ oss_play(void)
struct audio_packet *packet;
ssize_t len;
STREAM out;
size_t before;
const unsigned char *data;
assert(dsp_fd != -1);
@ -412,9 +414,12 @@ oss_play(void)
packet = rdpsnd_queue_current_packet();
out = packet->s;
len = s_remaining(out);
before = s_tell(out);
len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
len = MIN(s_remaining(out), MAX_LEN);
in_uint8p(out, data, len);
len = write(dsp_fd, data, len);
if (len == -1)
{
if (errno != EWOULDBLOCK)
@ -429,9 +434,10 @@ oss_play(void)
dsp_broken = False;
out->p += len;
/* We might not have written everything */
s_seek(out, before + len);
if (out->p == out->end)
if (s_check_end(out))
{
int delay_bytes;
unsigned long delay_us;

View File

@ -1195,8 +1195,11 @@ pulse_play(void)
audio_size = MIN(s_remaining(out), avail_space);
if (audio_size)
{
unsigned char *data;
in_uint8p(out, data, audio_size);
if (pa_stream_write
(playback_stream, out->p, audio_size, NULL, 0, playback_seek) != 0)
(playback_stream, data, audio_size, NULL, 0, playback_seek) != 0)
{
err = pa_context_errno(context);
logger(Sound, Error, "pulse_play(), pa_stream_write: %s",
@ -1207,9 +1210,7 @@ pulse_play(void)
playback_seek = PA_SEEK_RELATIVE;
}
out->p += audio_size;
if (out->p == out->end)
if (s_check_end(out))
{
ret = pa_stream_get_latency(playback_stream, &delay, NULL);
if (ret != 0 && (err = pa_context_errno(context)) == PA_ERR_NODATA)
@ -1251,7 +1252,7 @@ pulse_play(void)
pa_threaded_mainloop_unlock(mainloop);
if (out->p == out->end)
if (s_check_end(out))
rdpsnd_queue_next(delay);
return result;

View File

@ -246,6 +246,7 @@ sgi_play(void)
struct audio_packet *packet;
ssize_t len;
STREAM out;
unsigned char *data;
int gf;
while (1)
@ -257,11 +258,11 @@ sgi_play(void)
out = packet->s;
len = s_remaining(out);
in_uint8p(out, data, len);
alWriteFrames(output_port, out->p, len / combinedFrameSize);
alWriteFrames(output_port, data, len / combinedFrameSize);
out->p += len;
if (out->p == out->end)
if (s_check_end(out))
{
gf = alGetFilled(output_port);
if (gf < (4 * maxFillable / 10))

View File

@ -411,17 +411,22 @@ sun_play(void)
struct audio_packet *packet;
ssize_t len;
STREAM out;
size_t before;
const unsigned char *data;
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
return;
packet = rdpsnd_queue_current_packet();
out = &packet->s;
out = packet->s;
len = s_remaining(out);
before = s_tell(out);
len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
len = MIN(s_remaining(out), MAX_LEN);
in_uint8p(out, data, len);
len = write(dsp_fd, data, len);
if (len == -1)
{
if (errno != EWOULDBLOCK)
@ -439,9 +444,10 @@ sun_play(void)
dsp_broken = False;
out->p += len;
/* We might not have written everything */
s_seek(out, before + len);
if (out->p == out->end)
if (s_check_end(out))
{
audio_info_t info;
uint_t delay_samples;

162
scard.c
View File

@ -562,7 +562,7 @@ outBufferFinish(STREAM out, char *buffer, unsigned int length)
static void
outForceAlignment(STREAM out, unsigned int seed)
{
SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
SERVER_DWORD add = (seed - s_tell(out) % seed) % seed;
if (add > 0)
out_uint8s(out, add);
}
@ -639,7 +639,7 @@ static void
inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
{
SERVER_DWORD dataLength;
in->p += 0x08;
in_uint8s(in, 0x08);
in_uint32_le(in, dataLength);
inRepos(in, inString(handle, in, destination, dataLength, wide));
}
@ -717,6 +717,7 @@ TS_SCardEstablishContext(STREAM in, STREAM out)
out_uint32_le(out, 0x00000004);
out_uint32_le(out, hContext);
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -727,7 +728,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out)
MYPCSC_SCARDCONTEXT myHContext;
SERVER_SCARDCONTEXT hContext;
in->p += 0x1C;
in_uint8s(in, 0x1C);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -752,6 +753,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -762,7 +764,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out)
SERVER_SCARDCONTEXT hContext;
MYPCSC_SCARDCONTEXT myHContext;
in->p += 0x1C;
in_uint8s(in, 0x1C);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -786,6 +788,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -799,21 +802,21 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
MYPCSC_SCARDCONTEXT myHContext;
SERVER_DWORD dataLength;
MYPCSC_DWORD cchReaders = readerArraySize;
unsigned char *plen1, *plen2, *pend;
size_t plen1, plen2, pend;
char *readers, *cur;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x2C;
in_uint8s(in, 0x2C);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
logger(SmartCard, Debug, "TS_SCardListReaders(), context: 0x%08x [0x%lx])",
(unsigned) hContext, myHContext);
plen1 = out->p;
plen1 = s_tell(out);
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
out_uint32_le(out, 0x01760650);
plen2 = out->p;
plen2 = s_tell(out);
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
dataLength = 0;
@ -863,14 +866,17 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
dataLength += outString(out, "\0", wide);
outRepos(out, dataLength);
pend = out->p;
out->p = plen1;
s_mark_end(out);
pend = s_tell(out);
s_seek(out, plen1);
out_uint32_le(out, dataLength);
out->p = plen2;
s_seek(out, plen2);
out_uint32_le(out, dataLength);
out->p = pend;
s_seek(out, pend);
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -891,11 +897,11 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
MYPCSC_DWORD dwActiveProtocol;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x1C;
in_uint8s(in, 0x1C);
in_uint32_le(in, dwShareMode);
in_uint32_le(in, dwPreferredProtocol);
inReaderName(&lcHandle, in, &szReader, wide);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -966,6 +972,7 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
out_uint32_le(out, hCard);
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -982,13 +989,13 @@ TS_SCardReconnect(STREAM in, STREAM out)
SERVER_DWORD dwInitialization;
MYPCSC_DWORD dwActiveProtocol;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwShareMode);
in_uint32_le(in, dwPreferredProtocol);
in_uint32_le(in, dwInitialization);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hContext);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hCard);
@ -1014,6 +1021,7 @@ TS_SCardReconnect(STREAM in, STREAM out)
out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1027,11 +1035,11 @@ TS_SCardDisconnect(STREAM in, STREAM out)
MYPCSC_SCARDHANDLE myHCard;
SERVER_DWORD dwDisposition;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwDisposition);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hContext);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hCard);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -1076,6 +1084,7 @@ TS_SCardDisconnect(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1162,12 +1171,12 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
long i;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x18;
in_uint8s(in, 0x18);
in_uint32_le(in, dwTimeout);
in_uint32_le(in, dwCount);
in->p += 0x08;
in_uint8s(in, 0x08);
in_uint32_le(in, hContext);
in->p += 0x04;
in_uint8s(in, 0x04);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -1197,7 +1206,7 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
{
SERVER_DWORD dataLength;
in->p += 0x08;
in_uint8s(in, 0x08);
in_uint32_le(in, dataLength);
inRepos(in,
inString(&lcHandle, in, (char **) &(cur->szReader),
@ -1259,6 +1268,7 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1270,7 +1280,7 @@ TS_SCardCancel(STREAM in, STREAM out)
SERVER_SCARDCONTEXT hContext;
MYPCSC_SCARDCONTEXT myHContext;
in->p += 0x1C;
in_uint8s(in, 0x1C);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -1289,6 +1299,7 @@ TS_SCardCancel(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardCancel(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1309,7 +1320,7 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
MYPCSC_LPSCARD_READERSTATE_A myRsArray;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x2C;
in_uint8s(in, 0x2C);
in_uint32_le(in, hContext);
in_uint32_le(in, atrMaskCount);
pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
@ -1424,6 +1435,7 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1435,7 +1447,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out)
SERVER_SCARDCONTEXT hCard;
MYPCSC_SCARDCONTEXT myHCard;
in->p += 0x30;
in_uint8s(in, 0x30);
in_uint32_le(in, hCard);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), hcard: 0x%08x [0x%lx])",
@ -1451,6 +1463,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1462,9 +1475,9 @@ TS_SCardEndTransaction(STREAM in, STREAM out)
MYPCSC_SCARDCONTEXT myHCard;
SERVER_DWORD dwDisposition = 0;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwDisposition);
in->p += 0x0C;
in_uint8s(in, 0x0C);
in_uint32_le(in, hCard);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
@ -1483,6 +1496,7 @@ TS_SCardEndTransaction(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardEndTransaction(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1531,9 +1545,9 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
PMEM_HANDLE lcHandle = NULL;
in->p += 0x14;
in_uint8s(in, 0x14);
in_uint32_le(in, map[0]);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, map[1]);
pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
if (!pioSendPci)
@ -1551,7 +1565,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
if (srv_buf_len <= cbRecvLength)
cbRecvLength = srv_buf_len;
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hCard);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
@ -1695,6 +1709,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
outBufferFinish(out, (char *) recvBuf, cbRecvLength);
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1712,12 +1727,12 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
char *readerName;
unsigned char *atr;
in->p += 0x24;
in_uint8s(in, 0x24);
in_uint32_le(in, dwReaderLen);
in_uint32_le(in, dwAtrLen);
in->p += 0x0C;
in_uint8s(in, 0x0C);
in_uint32_le(in, hCard);
in->p += 0x04;
in_uint8s(in, 0x04);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
logger(SmartCard, Debug,
"TS_SCardStatus(), hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes",
@ -1790,7 +1805,7 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
else
dwState = 0x00000000;
void *p_len1 = out->p;
size_t p_len1 = s_tell(out);
out_uint32_le(out, dwReaderLen);
out_uint32_le(out, 0x00020000);
out_uint32_le(out, dwState);
@ -1802,19 +1817,21 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
}
out_uint32_le(out, dwAtrLen);
void *p_len2 = out->p;
size_t p_len2 = s_tell(out);
out_uint32_le(out, dwReaderLen);
dataLength = outString(out, readerName, wide);
dataLength += outString(out, "\0", wide);
outRepos(out, dataLength);
void *psave = out->p;
out->p = p_len1;
s_mark_end(out);
size_t psave = s_tell(out);
s_seek(out, p_len1);
out_uint32_le(out, dataLength);
out->p = p_len2;
s_seek(out, p_len2);
out_uint32_le(out, dataLength);
out->p = psave;
s_seek(out, psave);
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1831,11 +1848,11 @@ TS_SCardState(STREAM in, STREAM out)
char *readerName;
unsigned char *atr;
in->p += 0x24;
in_uint8s(in, 0x24);
in_uint32_le(in, dwAtrLen);
in->p += 0x0C;
in_uint8s(in, 0x0C);
in_uint32_le(in, hCard);
in->p += 0x04;
in_uint8s(in, 0x04);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
logger(SmartCard, Debug, "TS_SCardState(), hcard: 0x%08x [0x%08lx], atrlen: %d bytes",
@ -1905,6 +1922,7 @@ TS_SCardState(STREAM in, STREAM out)
outRepos(out, dwAtrLen);
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1926,9 +1944,9 @@ TS_SCardListReaderGroups(STREAM in, STREAM out)
char *szGroups;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwGroups);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hContext);
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
@ -1974,6 +1992,7 @@ TS_SCardListReaderGroups(STREAM in, STREAM out)
out_uint32_le(out, 0x00000000);
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1990,11 +2009,11 @@ TS_SCardGetAttrib(STREAM in, STREAM out)
unsigned char *pbAttr;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwAttrId);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, dwAttrLen);
in->p += 0x0C;
in_uint8s(in, 0x0C);
in_uint32_le(in, hCard);
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
@ -2044,6 +2063,7 @@ TS_SCardGetAttrib(STREAM in, STREAM out)
out_uint32_le(out, 0x00000000);
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -2060,11 +2080,11 @@ TS_SCardSetAttrib(STREAM in, STREAM out)
unsigned char *pbAttr;
PMEM_HANDLE lcHandle = NULL;
in->p += 0x20;
in_uint8s(in, 0x20);
in_uint32_le(in, dwAttrId);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, dwAttrLen);
in->p += 0x0C;
in_uint8s(in, 0x0C);
in_uint32_le(in, hCard);
myHCard = scHandleToMyPCSC(hCard);
@ -2098,6 +2118,7 @@ TS_SCardSetAttrib(STREAM in, STREAM out)
out_uint32_le(out, 0x00000000);
out_uint32_le(out, 0x00000000);
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -2123,18 +2144,18 @@ TS_SCardControl(STREAM in, STREAM out)
pInBuffer = NULL;
pOutBuffer = NULL;
in->p += 0x14;
in_uint8s(in, 0x14);
in_uint32_le(in, map[0]);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, map[1]);
in_uint32_le(in, dwControlCode);
in_uint32_le(in, nInBufferSize);
in_uint32_le(in, map[2]);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, nOutBufferSize);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hContext);
in->p += 0x04;
in_uint8s(in, 0x04);
in_uint32_le(in, hCard);
if (map[2] & INPUT_LINKED)
{
@ -2241,6 +2262,7 @@ TS_SCardControl(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -2260,7 +2282,7 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
{
UNUSED(handle);
SERVER_DWORD Result = 0x00000000;
unsigned char *psize, *pend, *pStatusCode;
size_t psize, pend, pStatusCode;
SERVER_DWORD addToEnd = 0;
/* Processing request */
@ -2270,11 +2292,11 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
/* Set CommonTypeHeader (MS-RPCE 2.2.6.1) */
out_uint32_le(out, 0x00081001); /* Header lines */
out_uint32_le(out, 0xCCCCCCCC);
psize = out->p;
psize = s_tell(out);
/* Set PrivateTypeHeader (MS-RPCE 2.2.6.2) */
out_uint32_le(out, 0x00000000); /* Size of data portion */
out_uint32_le(out, 0x00000000); /* Zero bytes (may be useful) */
pStatusCode = out->p;
pStatusCode = s_tell(out);
out_uint32_le(out, 0x00000000); /* Status Code */
switch (request)
@ -2410,22 +2432,25 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
#if 0
out_uint32_le(out, 0x00000000);
#endif
s_mark_end(out);
/* Setting modified variables */
pend = out->p;
pend = s_tell(out);
/* setting data size */
out->p = psize;
s_seek(out, psize);
out_uint32_le(out, pend - psize - 16);
/* setting status code */
out->p = pStatusCode;
s_seek(out, pStatusCode);
out_uint32_le(out, Result);
/* finish */
out->p = pend;
s_seek(out, pend);
/* TODO: Check MS-RPCE 2.2.6.2 for alignment requirements (IIRC length must be integral multiple of 8) */
addToEnd = (pend - pStatusCode) % 16;
if (addToEnd < 16 && addToEnd > 0)
{
out_uint8s(out, addToEnd);
s_mark_end(out);
}
if (Result == SCARD_E_INSUFFICIENT_BUFFER) return RD_STATUS_BUFFER_TOO_SMALL;
@ -2574,13 +2599,18 @@ SC_deviceControl(PSCThreadData data)
RD_NTSTATUS status;
size_t buffer_len = 0;
status = scard_device_control(data->handle, data->request, data->in, data->out, data->srv_buf_len);
buffer_len = (size_t) data->out->p - (size_t) data->out->data;
buffer_len = s_tell(data->out);
/* if iorequest belongs to another epoch, don't send response
back to server due to it's considered as abandoned.
*/
if (data->epoch == curEpoch)
rdpdr_send_completion(data->device, data->id, status, buffer_len, data->out->data, buffer_len);
{
uint8 *buf;
s_seek(data->out, 0);
in_uint8p(data->out, buf, buffer_len);
rdpdr_send_completion(data->device, data->id, status, buffer_len, buf, buffer_len);
}
SC_destroyThreadData(data);
}

View File

@ -380,7 +380,8 @@ seamless_process(STREAM s)
pkglen = s_remaining(s);
/* str_handle_lines requires null terminated strings */
buf = xmalloc(pkglen + 1);
STRNCPY(buf, (char *) s->p, pkglen + 1);
in_uint8a(s, buf, pkglen);
buf[pkglen] = '\0';
str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
xfree(buf);

View File

@ -351,10 +351,12 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
if (flags & SEC_ENCRYPT)
{
unsigned char *data;
flags &= ~SEC_ENCRYPT;
datalen = s_remaining(s) - 8;
sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
sec_encrypt(s->p + 8, datalen);
inout_uint8p(s, data, datalen + 8);
sec_sign(data, 8, g_sec_sign_key, g_rc4_key_len, data + 8, datalen);
sec_encrypt(data + 8, datalen);
}
mcs_send_to_channel(s, channel);
@ -587,7 +589,7 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
RDSSL_CERT *cacert, *server_cert;
RDSSL_RKEY *server_public_key;
uint16 tag, length;
uint8 *next_tag, *end;
size_t next_tag;
logger(Protocol, Debug, "%s()", __func__);
@ -613,10 +615,9 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
in_uint8p(s, *server_random, random_len);
/* RSA info */
end = s->p + rsa_info_len;
if (end > s->end)
if (!s_check_rem(s, rsa_info_len))
{
logger(Protocol, Error, "sec_parse_crypt_info(), end > s->end");
logger(Protocol, Error, "sec_parse_crypt_info(), !s_check_rem(s, rsa_info_len)");
return False;
}
@ -627,12 +628,12 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
"sec_parse_crypt_info(), We're going for the RDP4-style encryption");
in_uint8s(s, 8); /* unknown */
while (s->p < end)
while (!s_check_end(s))
{
in_uint16_le(s, tag);
in_uint16_le(s, length);
next_tag = s->p + length;
next_tag = s_tell(s) + length;
switch (tag)
{
@ -663,12 +664,13 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
tag);
}
s->p = next_tag;
s_seek(s, next_tag);
}
}
else
{
uint32 certcount;
unsigned char *certdata;
logger(Protocol, Debug,
"sec_parse_crypt_info(), We're going for the RDP5-style encryption");
@ -683,10 +685,11 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
{ /* ignore all the certificates between the root and the signing CA */
uint32 ignorelen;
RDSSL_CERT *ignorecert;
unsigned char *ignoredata;
in_uint32_le(s, ignorelen);
ignorecert = rdssl_cert_read(s->p, ignorelen);
in_uint8s(s, ignorelen);
in_uint8p(s, ignoredata, ignorelen);
ignorecert = rdssl_cert_read(ignoredata, ignorelen);
if (ignorecert == NULL)
{ /* XXX: error out? */
logger(Protocol, Error,
@ -706,10 +709,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
*/
in_uint32_le(s, cacert_len);
in_uint8p(s, certdata, cacert_len);
logger(Protocol, Debug,
"sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len);
cacert = rdssl_cert_read(s->p, cacert_len);
in_uint8s(s, cacert_len);
cacert = rdssl_cert_read(certdata, cacert_len);
if (NULL == cacert)
{
logger(Protocol, Error,
@ -717,10 +720,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
return False;
}
in_uint32_le(s, cert_len);
in_uint8p(s, certdata, cert_len);
logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d",
cert_len);
server_cert = rdssl_cert_read(s->p, cert_len);
in_uint8s(s, cert_len);
server_cert = rdssl_cert_read(certdata, cert_len);
if (NULL == server_cert)
{
rdssl_cert_free(cacert);
@ -814,7 +817,7 @@ void
sec_process_mcs_data(STREAM s)
{
uint16 tag, length;
uint8 *next_tag;
size_t next_tag;
uint8 len;
in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
@ -823,7 +826,7 @@ sec_process_mcs_data(STREAM s)
in_uint8(s, len);
logger(Protocol, Debug, "%s()", __func__);
while (s->p < s->end)
while (!s_check_end(s))
{
in_uint16_le(s, tag);
in_uint16_le(s, length);
@ -831,7 +834,7 @@ sec_process_mcs_data(STREAM s)
if (length <= 4)
return;
next_tag = s->p + length - 4;
next_tag = s_tell(s) + length - 4;
switch (tag)
{
@ -856,7 +859,7 @@ sec_process_mcs_data(STREAM s)
logger(Protocol, Warning, "Unhandled response tag 0x%x", tag);
}
s->p = next_tag;
s_seek(s, next_tag);
}
}
@ -869,6 +872,8 @@ sec_recv(RD_BOOL * is_fastpath)
uint16 channel;
STREAM s;
struct stream packet;
size_t data_offset;
unsigned char *data;
while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
{
@ -886,19 +891,29 @@ sec_recv(RD_BOOL * is_fastpath)
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s_remaining(s));
data_offset = s_tell(s);
inout_uint8p(s, data, s_remaining(s));
sec_decrypt(data, s_remaining(s));
s_seek(s, data_offset);
}
return s;
}
if (g_encryption || (!g_licence_issued && !g_licence_error_result))
{
data_offset = s_tell(s);
/* TS_SECURITY_HEADER */
in_uint16_le(s, sec_flags);
in_uint8s(s, 2); /* skip sec_flags_hi */
if (g_encryption)
{
data_offset = s_tell(s);
if (sec_flags & SEC_ENCRYPT)
{
if (!s_check_rem(s, 8)) {
@ -906,11 +921,16 @@ sec_recv(RD_BOOL * is_fastpath)
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s_remaining(s));
data_offset = s_tell(s);
inout_uint8p(s, data, s_remaining(s));
sec_decrypt(data, s_remaining(s));
}
if (sec_flags & SEC_LICENSE_PKT)
{
s_seek(s, data_offset);
licence_process(s);
continue;
}
@ -924,10 +944,14 @@ sec_recv(RD_BOOL * is_fastpath)
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s_remaining(s));
data_offset = s_tell(s);
inout_uint8p(s, data, s_remaining(s));
sec_decrypt(data, s_remaining(s));
/* Check for a redirect packet, starts with 00 04 */
if (s->p[0] == 0 && s->p[1] == 4)
if (data[0] == 0 && data[1] == 4)
{
/* for some reason the PDU and the length seem to be swapped.
This isn't good, but we're going to do a byte for byte
@ -935,17 +959,17 @@ sec_recv(RD_BOOL * is_fastpath)
where XX YY is the little endian length. We're going to
use 04 00 as the PDU type, so after our swap this will look
like: XX YY 04 00 */
swapbyte = s->p[0];
s->p[0] = s->p[2];
s->p[2] = swapbyte;
swapbyte = data[0];
data[0] = data[2];
data[2] = swapbyte;
swapbyte = s->p[1];
s->p[1] = s->p[3];
s->p[3] = swapbyte;
swapbyte = data[1];
data[1] = data[3];
data[3] = swapbyte;
swapbyte = s->p[2];
s->p[2] = s->p[3];
s->p[3] = swapbyte;
swapbyte = data[2];
data[2] = data[3];
data[3] = swapbyte;
}
}
}
@ -956,8 +980,9 @@ sec_recv(RD_BOOL * is_fastpath)
licence_process(s);
continue;
}
s->p -= 4;
}
s_seek(s, data_offset);
}
if (channel != MCS_GLOBAL_CHANNEL)

View File

@ -152,6 +152,9 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
/* Copy the entire STREAM v (ignoring offsets) in to STREAM s */
#define out_stream(s, v) out_uint8a(s, (v)->data, s_length((v)))
/* Return a pointer in v to manually modify n bytes of STREAM s in place */
#define inout_uint8p(s,v,n) { s_assert_r(s, n); s_assert_w(s, n); v = (s)->p; (s)->p += n; }
#define next_be(s,v) { s_assert_r(s, 1); v = ((v) << 8) + *((s)->p++); }

55
tcp.c
View File

@ -109,8 +109,9 @@ tcp_init(uint32 maxlen)
void
tcp_send(STREAM s)
{
int length = s->end - s->data;
int sent, total = 0;
size_t before;
int length, sent;
unsigned char *data;
if (g_network_error == True)
return;
@ -119,10 +120,16 @@ tcp_send(STREAM s)
scard_lock(SCARD_LOCK_TCP);
#endif
while (total < length)
s_seek(s, 0);
while (!s_check_end(s))
{
before = s_tell(s);
length = s_remaining(s);
in_uint8p(s, data, length);
if (g_ssl_initialized) {
sent = gnutls_record_send(g_tls_session, s->data + total, length - total);
sent = gnutls_record_send(g_tls_session, data, length);
if (sent <= 0) {
if (gnutls_error_is_fatal(sent)) {
#ifdef WITH_SCARD
@ -139,7 +146,7 @@ tcp_send(STREAM s)
}
else
{
sent = send(g_sock, s->data + total, length - total, 0);
sent = send(g_sock, data, length, 0);
if (sent <= 0)
{
if (sent == -1 && TCP_BLOCKS)
@ -159,7 +166,9 @@ tcp_send(STREAM s)
}
}
}
total += sent;
/* Everything might not have been sent */
s_seek(s, before + sent);
}
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
@ -170,7 +179,8 @@ tcp_send(STREAM s)
STREAM
tcp_recv(STREAM s, uint32 length)
{
uint32 new_length, end_offset, p_offset;
size_t before;
unsigned char *data;
int rcvd = 0;
if (g_network_error == True)
@ -179,27 +189,14 @@ tcp_recv(STREAM s, uint32 length)
if (s == NULL)
{
/* read into "new" stream */
if (length > g_in.size)
{
g_in.data = (uint8 *) xrealloc(g_in.data, length);
g_in.size = length;
}
g_in.end = g_in.p = g_in.data;
s_realloc(&g_in, length);
s_reset(&g_in);
s = &g_in;
}
else
{
/* append to existing stream */
new_length = (s->end - s->data) + length;
if (new_length > s->size)
{
p_offset = s->p - s->data;
end_offset = s->end - s->data;
s->data = (uint8 *) xrealloc(s->data, new_length);
s->size = new_length;
s->p = s->data + p_offset;
s->end = s->data + end_offset;
}
s_realloc(s, s_length(s) + length);
}
while (length > 0)
@ -215,8 +212,15 @@ tcp_recv(STREAM s, uint32 length)
return NULL;
}
before = s_tell(s);
s_seek(s, s_length(s));
out_uint8p(s, data, length);
s_seek(s, before);
if (g_ssl_initialized) {
rcvd = gnutls_record_recv(g_tls_session, s->end, length);
rcvd = gnutls_record_recv(g_tls_session, data, length);
if (rcvd < 0) {
if (gnutls_error_is_fatal(rcvd)) {
@ -231,7 +235,7 @@ tcp_recv(STREAM s, uint32 length)
}
else
{
rcvd = recv(g_sock, s->end, length, 0);
rcvd = recv(g_sock, data, length, 0);
if (rcvd < 0)
{
if (rcvd == -1 && TCP_BLOCKS)
@ -253,6 +257,7 @@ tcp_recv(STREAM s, uint32 length)
}
}
// FIXME: Should probably have a macro for this
s->end += rcvd;
length -= rcvd;
}