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

View File

@ -119,21 +119,14 @@ 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);
in_uint32_le(s, length); in_uint32_le(s, length);
data = s->p;
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("consume of packet from stream would overrun", &packet);
}
if (status == CLIPRDR_ERROR) if (status == CLIPRDR_ERROR)
{ {
switch (type) switch (type)
@ -161,6 +154,7 @@ cliprdr_process(STREAM s)
ui_clip_sync(); ui_clip_sync();
break; break;
case CLIPRDR_FORMAT_ANNOUNCE: case CLIPRDR_FORMAT_ANNOUNCE:
in_uint8p(s, data, length);
ui_clip_format_announce(data, length); ui_clip_format_announce(data, length);
cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0); cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
return; return;
@ -171,6 +165,7 @@ cliprdr_process(STREAM s)
ui_clip_request_data(format); ui_clip_request_data(format);
break; break;
case CLIPRDR_DATA_RESPONSE: case CLIPRDR_DATA_RESPONSE:
in_uint8p(s, data, length);
ui_clip_handle_data(data, length); ui_clip_handle_data(data, length);
break; break;
case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */ 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); out = s_alloc(size);
ber_out_header(out, tagval, s_length(in)); ber_out_header(out, tagval, s_length(in));
out_uint8a(out, in->data, s_length(in)); out_stream(out, in);
s_mark_end(out); s_mark_end(out);
return out; return out;
@ -148,8 +148,10 @@ cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in)
gss_buffer_desc inbuf, outbuf; gss_buffer_desc inbuf, outbuf;
STREAM out; STREAM out;
inbuf.value = in->data; s_seek(in, 0);
inbuf.length = s_length(in); 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, major_status = gss_wrap(&minor_status, ctx, True,
GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf); 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; int conf_state;
STREAM out; STREAM out;
inbuf.value = in->data; s_seek(in, 0);
inbuf.length = s_length(in); 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); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); s_free(h1);
@ -394,7 +398,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
g_sc_container_name, g_sc_csp_name); g_sc_container_name, g_sc_csp_name);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h3); s_free(h3);
s_free(h2); 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); h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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); 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); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h5); s_free(h5);
s_free(h4); 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); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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(h2);
s_free(h1); 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); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
s_realloc(&message, s_length(&message) + s_length(h1)); 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_mark_end(&message);
s_free(h2); s_free(h2);
s_free(h1); 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 // Todo: can h1 be send directly instead of tcp_init() approach
h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message); h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
s = tcp_init(s_length(h1)); s = tcp_init(s_length(h1));
out_uint8a(s, h1->data, s_length(h1)); out_stream(s, h1);
s_mark_end(s); s_mark_end(s);
s_free(h1); s_free(h1);
@ -600,34 +604,21 @@ cssp_read_tsrequest(RD_BOOL pubkey)
if (s == NULL) if (s == NULL)
return NULL; return NULL;
// verify ASN.1 header // get and verify the 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
if (!ber_in_header(s, &tagval, &length) || if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED)) tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return NULL; 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] // version [0]
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))
@ -666,7 +657,7 @@ cssp_read_tsrequest(RD_BOOL pubkey)
} }
out = s_alloc(length); out = s_alloc(length);
out_uint8a(out, s->p, length); out_uint8stream(out, s, length);
s_mark_end(out); s_mark_end(out);
s_seek(out, 0); s_seek(out, 0);
} }
@ -681,7 +672,7 @@ cssp_read_tsrequest(RD_BOOL pubkey)
return NULL; return NULL;
out = s_alloc(length); out = s_alloc(length);
out_uint8a(out, s->p, length); out_uint8stream(out, s, length);
s_mark_end(out); s_mark_end(out);
s_seek(out, 0); s_seek(out, 0);
} }

View File

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

View File

@ -139,7 +139,8 @@ lspci_process(STREAM s)
pkglen = s_remaining(s); pkglen = s_remaining(s);
/* str_handle_lines requires null terminated strings */ /* str_handle_lines requires null terminated strings */
buf = xmalloc(pkglen + 1); 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); str_handle_lines(buf, &rest, lspci_process_line, NULL);
xfree(buf); xfree(buf);
} }

9
mcs.c
View File

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

View File

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

View File

@ -238,6 +238,8 @@ printercache_process(STREAM s)
{ {
uint32 type, printer_length, driver_length, printer_unicode_length, blob_length; uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
char device_name[9], *printer, *driver; char device_name[9], *printer, *driver;
size_t blob_start;
unsigned char *blob;
printer = driver = NULL; printer = driver = NULL;
@ -279,8 +281,10 @@ printercache_process(STREAM s)
{ {
rdp_in_unistr(s, printer_unicode_length, &printer, rdp_in_unistr(s, printer_unicode_length, &printer,
&printer_unicode_length); &printer_unicode_length);
if (printer) if (printer) {
printercache_save_blob(printer, s->p, blob_length); in_uint8p(s, blob, blob_length);
printercache_save_blob(printer, blob, blob_length);
}
free(printer); free(printer);
} }
break; break;
@ -289,6 +293,7 @@ printercache_process(STREAM s)
in_uint8a(s, device_name, 5); /* get LPTx/COMx name */ 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. */ /* 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); /* ??? */
in_uint8s(s, 0x2) /* pad?? */ in_uint8s(s, 0x2) /* pad?? */
in_uint32_be(s, driver_length); in_uint32_be(s, driver_length);
@ -302,10 +307,11 @@ printercache_process(STREAM s)
/* rewind stream so that we can save this blob */ /* rewind stream so that we can save this blob */
/* length is driver_length + printer_length + 19 */ /* length is driver_length + printer_length + 19 */
/* rewind stream */ /* rewind stream */
s->p = s->p - 19; s_seek(s, blob_start);
printercache_save_blob(device_name, s->p, blob_length = driver_length + printer_length + 19;
driver_length + printer_length + 19); in_uint8p(s, blob, blob_length);
printercache_save_blob(device_name, blob, blob_length);
break; break;
default: default:
logger(Protocol, Warning, 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; RD_BOOL g_exit_mainloop = False;
uint8 *g_next_packet; size_t g_next_packet;
uint32 g_rdp_shareid; uint32 g_rdp_shareid;
extern RDPCOMP g_mppc_dict; 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; *type = pdu_type & 0xf;
/* Give just the size of the data */
*length -= 6;
return True; return True;
} }
@ -142,7 +145,7 @@ rdp_recv(uint8 * type)
while (1) while (1)
{ {
/* fill stream with data if needed for parsing a new packet */ /* 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); rdp_s = sec_recv(&is_fastpath);
if (rdp_s == NULL) if (rdp_s == NULL)
@ -155,11 +158,16 @@ rdp_recv(uint8 * type)
continue; continue;
} }
g_next_packet = rdp_s->p; g_next_packet = s_tell(rdp_s);
} }
else 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 */ /* 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); 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; return rdp_s;
} }
@ -241,7 +255,8 @@ rdp_out_unistr(STREAM s, char *string, int len)
*/ */
static iconv_t icv_local_to_utf16; static iconv_t icv_local_to_utf16;
size_t ibl, obl; size_t ibl, obl;
char *pin, *pout; char *pin;
unsigned char *pout;
if (string == NULL || len == 0) if (string == NULL || len == 0)
@ -263,18 +278,16 @@ rdp_out_unistr(STREAM s, char *string, int len)
ibl = strlen(string); ibl = strlen(string);
obl = len + 2; obl = len + 2;
pin = string; 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); logger(Protocol, Error, "rdp_out_unistr(), iconv(2) fail, errno %d", errno);
abort(); abort();
} }
s->p += len + 2;
} }
/* Input a string in Unicode /* 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; static iconv_t icv_utf16_to_local;
size_t ibl, obl; size_t ibl, obl;
char *pin, *pout; unsigned char *pin;
char *pout;
struct stream packet = *s; struct stream packet = *s;
@ -323,7 +337,7 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
ibl = in_len; ibl = in_len;
obl = *str_size - 1; obl = *str_size - 1;
pin = (char *) s->p; in_uint8p(s, pin, in_len);
pout = *string; pout = *string;
if (iconv(icv_utf16_to_local, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1) 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(); abort();
} }
/* we must update the location of the current STREAM for future reads of s->p */
s->p += in_len;
*pout = 0; *pout = 0;
if (*string) if (*string)
@ -1219,25 +1230,25 @@ static void
rdp_process_server_caps(STREAM s, uint16 length) rdp_process_server_caps(STREAM s, uint16 length)
{ {
int n; int n;
uint8 *next, *start; size_t next, start;
uint16 ncapsets, capset_type, capset_length; uint16 ncapsets, capset_type, capset_length;
logger(Protocol, Debug, "%s()", __func__); logger(Protocol, Debug, "%s()", __func__);
start = s->p; start = s_tell(s);
in_uint16_le(s, ncapsets); in_uint16_le(s, ncapsets);
in_uint8s(s, 2); /* pad */ in_uint8s(s, 2); /* pad */
for (n = 0; n < ncapsets; n++) for (n = 0; n < ncapsets; n++)
{ {
if (s->p > start + length) if (s_tell(s) > start + length)
return; return;
in_uint16_le(s, capset_type); in_uint16_le(s, capset_type);
in_uint16_le(s, capset_length); in_uint16_le(s, capset_length);
next = s->p + capset_length - 4; next = s_tell(s) + capset_length - 4;
switch (capset_type) switch (capset_type)
{ {
@ -1256,7 +1267,7 @@ rdp_process_server_caps(STREAM s, uint16 length)
break; break;
} }
s->p = next; s_seek(s, next);
} }
} }
@ -1726,6 +1737,7 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
uint16 clen; uint16 clen;
uint32 len; uint32 len;
uint8 *buf;
uint32 roff, rlen; uint32 roff, rlen;
struct stream *ns = &(g_mppc_dict.ns); 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) if (len > RDP_MPPC_DICT_SIZE)
logger(Protocol, Error, logger(Protocol, Error,
"process_data_pdu(), error decompressed packet size exceeds max"); "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, logger(Protocol, Error,
"process_data_pdu(), error while decompressing packet"); "process_data_pdu(), error while decompressing packet");
/* len -= 18; */ /* len -= 18; */
/* allocate memory and copy the uncompressed data into the temporary stream */ /* 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; s_mark_end(ns);
ns->end = (ns->data + ns->size); s_seek(ns, 0);
ns->p = ns->data; s_push_layer(ns, rdp_hdr, 0);
ns->rdp_hdr = ns->p;
s = ns; s = ns;
} }
@ -2056,7 +2069,7 @@ rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
logger(Protocol, Warning, logger(Protocol, Warning,
"rdp_loop(), unhandled PDU type %d received", type); "rdp_loop(), unhandled PDU type %d received", type);
} }
cont = g_next_packet < s->end; cont = g_next_packet < s_length(s);
} }
return True; return True;
} }
@ -2094,7 +2107,7 @@ void
rdp_reset_state(void) rdp_reset_state(void)
{ {
logger(Protocol, Debug, "%s()", __func__); 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_rdp_shareid = 0;
g_exit_mainloop = False; g_exit_mainloop = False;
g_first_bitmap_caps = True; g_first_bitmap_caps = True;

30
rdp5.c
View File

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

119
rdpdr.c
View File

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

View File

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

View File

@ -358,6 +358,8 @@ alsa_play(void)
struct audio_packet *packet; struct audio_packet *packet;
STREAM out; STREAM out;
int len; int len;
const unsigned char *data;
size_t before;
static long prev_s, prev_us; static long prev_s, prev_us;
int duration; int duration;
struct timeval tv; struct timeval tv;
@ -380,13 +382,21 @@ alsa_play(void)
next_tick = rdpsnd_queue_next_tick(); next_tick = rdpsnd_queue_next_tick();
before = s_tell(out);
len = s_remaining(out) / (samplewidth_out * audiochannels_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); snd_pcm_prepare(out_handle);
len = 0; 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); gettimeofday(&tv, NULL);
@ -395,7 +405,7 @@ alsa_play(void)
if (packet->tick > next_tick) if (packet->tick > next_tick)
next_tick += 65536; 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; snd_pcm_sframes_t delay_frames;
unsigned long delay_us; unsigned long delay_us;

View File

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

View File

@ -402,6 +402,8 @@ oss_play(void)
struct audio_packet *packet; struct audio_packet *packet;
ssize_t len; ssize_t len;
STREAM out; STREAM out;
size_t before;
const unsigned char *data;
assert(dsp_fd != -1); assert(dsp_fd != -1);
@ -412,9 +414,12 @@ oss_play(void)
packet = rdpsnd_queue_current_packet(); 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 (len == -1)
{ {
if (errno != EWOULDBLOCK) if (errno != EWOULDBLOCK)
@ -429,9 +434,10 @@ oss_play(void)
dsp_broken = False; 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; int delay_bytes;
unsigned long delay_us; unsigned long delay_us;

View File

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

View File

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

View File

@ -411,17 +411,22 @@ sun_play(void)
struct audio_packet *packet; struct audio_packet *packet;
ssize_t len; ssize_t len;
STREAM out; STREAM out;
size_t before;
const unsigned char *data;
/* We shouldn't be called if the queue is empty, but still */ /* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty()) if (rdpsnd_queue_empty())
return; return;
packet = rdpsnd_queue_current_packet(); 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 (len == -1)
{ {
if (errno != EWOULDBLOCK) if (errno != EWOULDBLOCK)
@ -439,9 +444,10 @@ sun_play(void)
dsp_broken = False; 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; audio_info_t info;
uint_t delay_samples; uint_t delay_samples;

162
scard.c
View File

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

View File

@ -380,7 +380,8 @@ seamless_process(STREAM s)
pkglen = s_remaining(s); pkglen = s_remaining(s);
/* str_handle_lines requires null terminated strings */ /* str_handle_lines requires null terminated strings */
buf = xmalloc(pkglen + 1); 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); str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
xfree(buf); xfree(buf);

View File

@ -351,10 +351,12 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
if (flags & SEC_ENCRYPT) if (flags & SEC_ENCRYPT)
{ {
unsigned char *data;
flags &= ~SEC_ENCRYPT; flags &= ~SEC_ENCRYPT;
datalen = s_remaining(s) - 8; datalen = s_remaining(s) - 8;
sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen); inout_uint8p(s, data, datalen + 8);
sec_encrypt(s->p + 8, datalen); 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); 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_CERT *cacert, *server_cert;
RDSSL_RKEY *server_public_key; RDSSL_RKEY *server_public_key;
uint16 tag, length; uint16 tag, length;
uint8 *next_tag, *end; size_t next_tag;
logger(Protocol, Debug, "%s()", __func__); 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); in_uint8p(s, *server_random, random_len);
/* RSA info */ /* RSA info */
end = s->p + rsa_info_len; if (!s_check_rem(s, rsa_info_len))
if (end > s->end)
{ {
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; 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"); "sec_parse_crypt_info(), We're going for the RDP4-style encryption");
in_uint8s(s, 8); /* unknown */ in_uint8s(s, 8); /* unknown */
while (s->p < end) while (!s_check_end(s))
{ {
in_uint16_le(s, tag); in_uint16_le(s, tag);
in_uint16_le(s, length); in_uint16_le(s, length);
next_tag = s->p + length; next_tag = s_tell(s) + length;
switch (tag) switch (tag)
{ {
@ -663,12 +664,13 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
tag); tag);
} }
s->p = next_tag; s_seek(s, next_tag);
} }
} }
else else
{ {
uint32 certcount; uint32 certcount;
unsigned char *certdata;
logger(Protocol, Debug, logger(Protocol, Debug,
"sec_parse_crypt_info(), We're going for the RDP5-style encryption"); "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 */ { /* ignore all the certificates between the root and the signing CA */
uint32 ignorelen; uint32 ignorelen;
RDSSL_CERT *ignorecert; RDSSL_CERT *ignorecert;
unsigned char *ignoredata;
in_uint32_le(s, ignorelen); in_uint32_le(s, ignorelen);
ignorecert = rdssl_cert_read(s->p, ignorelen); in_uint8p(s, ignoredata, ignorelen);
in_uint8s(s, ignorelen); ignorecert = rdssl_cert_read(ignoredata, ignorelen);
if (ignorecert == NULL) if (ignorecert == NULL)
{ /* XXX: error out? */ { /* XXX: error out? */
logger(Protocol, Error, 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 http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
*/ */
in_uint32_le(s, cacert_len); in_uint32_le(s, cacert_len);
in_uint8p(s, certdata, cacert_len);
logger(Protocol, Debug, logger(Protocol, Debug,
"sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len); "sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len);
cacert = rdssl_cert_read(s->p, cacert_len); cacert = rdssl_cert_read(certdata, cacert_len);
in_uint8s(s, cacert_len);
if (NULL == cacert) if (NULL == cacert)
{ {
logger(Protocol, Error, logger(Protocol, Error,
@ -717,10 +720,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
return False; return False;
} }
in_uint32_le(s, cert_len); in_uint32_le(s, cert_len);
in_uint8p(s, certdata, cert_len);
logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d", logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d",
cert_len); cert_len);
server_cert = rdssl_cert_read(s->p, cert_len); server_cert = rdssl_cert_read(certdata, cert_len);
in_uint8s(s, cert_len);
if (NULL == server_cert) if (NULL == server_cert)
{ {
rdssl_cert_free(cacert); rdssl_cert_free(cacert);
@ -814,7 +817,7 @@ void
sec_process_mcs_data(STREAM s) sec_process_mcs_data(STREAM s)
{ {
uint16 tag, length; uint16 tag, length;
uint8 *next_tag; size_t next_tag;
uint8 len; uint8 len;
in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */ in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
@ -823,7 +826,7 @@ sec_process_mcs_data(STREAM s)
in_uint8(s, len); in_uint8(s, len);
logger(Protocol, Debug, "%s()", __func__); logger(Protocol, Debug, "%s()", __func__);
while (s->p < s->end) while (!s_check_end(s))
{ {
in_uint16_le(s, tag); in_uint16_le(s, tag);
in_uint16_le(s, length); in_uint16_le(s, length);
@ -831,7 +834,7 @@ sec_process_mcs_data(STREAM s)
if (length <= 4) if (length <= 4)
return; return;
next_tag = s->p + length - 4; next_tag = s_tell(s) + length - 4;
switch (tag) switch (tag)
{ {
@ -856,7 +859,7 @@ sec_process_mcs_data(STREAM s)
logger(Protocol, Warning, "Unhandled response tag 0x%x", tag); 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; uint16 channel;
STREAM s; STREAM s;
struct stream packet; struct stream packet;
size_t data_offset;
unsigned char *data;
while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL) 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 */ 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; return s;
} }
if (g_encryption || (!g_licence_issued && !g_licence_error_result)) if (g_encryption || (!g_licence_issued && !g_licence_error_result))
{ {
data_offset = s_tell(s);
/* TS_SECURITY_HEADER */ /* TS_SECURITY_HEADER */
in_uint16_le(s, sec_flags); in_uint16_le(s, sec_flags);
in_uint8s(s, 2); /* skip sec_flags_hi */ in_uint8s(s, 2); /* skip sec_flags_hi */
if (g_encryption) if (g_encryption)
{ {
data_offset = s_tell(s);
if (sec_flags & SEC_ENCRYPT) if (sec_flags & SEC_ENCRYPT)
{ {
if (!s_check_rem(s, 8)) { if (!s_check_rem(s, 8)) {
@ -906,11 +921,16 @@ sec_recv(RD_BOOL * is_fastpath)
} }
in_uint8s(s, 8); /* signature */ 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) if (sec_flags & SEC_LICENSE_PKT)
{ {
s_seek(s, data_offset);
licence_process(s); licence_process(s);
continue; continue;
} }
@ -924,10 +944,14 @@ sec_recv(RD_BOOL * is_fastpath)
} }
in_uint8s(s, 8); /* signature */ 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 */ /* 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. /* 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 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 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 use 04 00 as the PDU type, so after our swap this will look
like: XX YY 04 00 */ like: XX YY 04 00 */
swapbyte = s->p[0]; swapbyte = data[0];
s->p[0] = s->p[2]; data[0] = data[2];
s->p[2] = swapbyte; data[2] = swapbyte;
swapbyte = s->p[1]; swapbyte = data[1];
s->p[1] = s->p[3]; data[1] = data[3];
s->p[3] = swapbyte; data[3] = swapbyte;
swapbyte = s->p[2]; swapbyte = data[2];
s->p[2] = s->p[3]; data[2] = data[3];
s->p[3] = swapbyte; data[3] = swapbyte;
} }
} }
} }
@ -956,8 +980,9 @@ sec_recv(RD_BOOL * is_fastpath)
licence_process(s); licence_process(s);
continue; continue;
} }
s->p -= 4;
} }
s_seek(s, data_offset);
} }
if (channel != MCS_GLOBAL_CHANNEL) 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 */ /* Copy the entire STREAM v (ignoring offsets) in to STREAM s */
#define out_stream(s, v) out_uint8a(s, (v)->data, s_length((v))) #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++); } #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 void
tcp_send(STREAM s) tcp_send(STREAM s)
{ {
int length = s->end - s->data; size_t before;
int sent, total = 0; int length, sent;
unsigned char *data;
if (g_network_error == True) if (g_network_error == True)
return; return;
@ -119,10 +120,16 @@ tcp_send(STREAM s)
scard_lock(SCARD_LOCK_TCP); scard_lock(SCARD_LOCK_TCP);
#endif #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) { 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 (sent <= 0) {
if (gnutls_error_is_fatal(sent)) { if (gnutls_error_is_fatal(sent)) {
#ifdef WITH_SCARD #ifdef WITH_SCARD
@ -139,7 +146,7 @@ tcp_send(STREAM s)
} }
else else
{ {
sent = send(g_sock, s->data + total, length - total, 0); sent = send(g_sock, data, length, 0);
if (sent <= 0) if (sent <= 0)
{ {
if (sent == -1 && TCP_BLOCKS) 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 #ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP); scard_unlock(SCARD_LOCK_TCP);
@ -170,7 +179,8 @@ tcp_send(STREAM s)
STREAM STREAM
tcp_recv(STREAM s, uint32 length) tcp_recv(STREAM s, uint32 length)
{ {
uint32 new_length, end_offset, p_offset; size_t before;
unsigned char *data;
int rcvd = 0; int rcvd = 0;
if (g_network_error == True) if (g_network_error == True)
@ -179,27 +189,14 @@ tcp_recv(STREAM s, uint32 length)
if (s == NULL) if (s == NULL)
{ {
/* read into "new" stream */ /* read into "new" stream */
if (length > g_in.size) s_realloc(&g_in, length);
{ s_reset(&g_in);
g_in.data = (uint8 *) xrealloc(g_in.data, length);
g_in.size = length;
}
g_in.end = g_in.p = g_in.data;
s = &g_in; s = &g_in;
} }
else else
{ {
/* append to existing stream */ /* append to existing stream */
new_length = (s->end - s->data) + length; s_realloc(s, s_length(s) + 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;
}
} }
while (length > 0) while (length > 0)
@ -215,8 +212,15 @@ tcp_recv(STREAM s, uint32 length)
return NULL; 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) { 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 (rcvd < 0) {
if (gnutls_error_is_fatal(rcvd)) { if (gnutls_error_is_fatal(rcvd)) {
@ -231,7 +235,7 @@ tcp_recv(STREAM s, uint32 length)
} }
else else
{ {
rcvd = recv(g_sock, s->end, length, 0); rcvd = recv(g_sock, data, length, 0);
if (rcvd < 0) if (rcvd < 0)
{ {
if (rcvd == -1 && TCP_BLOCKS) 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; s->end += rcvd;
length -= rcvd; length -= rcvd;
} }