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:
parent
489c43f382
commit
25b8412333
17
channels.c
17
channels.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
87
cssp.c
@ -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);
|
||||
}
|
||||
|
10
licence.c
10
licence.c
@ -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 */
|
||||
|
3
lspci.c
3
lspci.c
@ -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
9
mcs.c
@ -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);
|
||||
}
|
||||
|
12
orders.c
12
orders.c
@ -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
|
||||
|
||||
}
|
||||
|
@ -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
73
rdp.c
@ -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
30
rdp5.c
@ -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
119
rdpdr.c
@ -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
|
||||
|
58
rdpsnd.c
58
rdpsnd.c
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
14
rdpsnd_oss.c
14
rdpsnd_oss.c
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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))
|
||||
|
16
rdpsnd_sun.c
16
rdpsnd_sun.c
@ -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
162
scard.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
91
secure.c
91
secure.c
@ -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)
|
||||
|
3
stream.h
3
stream.h
@ -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
55
tcp.c
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user