This commit is contained in:
Pierre Ossman 2019-05-08 13:55:46 +02:00
commit a88cd226bb
37 changed files with 1012 additions and 821 deletions

14
asn.c
View File

@ -41,10 +41,16 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
if (tagval > 0xff)
{
if (!s_check_rem(s, 2)) {
return False;
}
in_uint16_be(s, tag);
}
else
{
if (!s_check_rem(s, 1)) {
return False;
}
in_uint8(s, tag);
}
@ -54,11 +60,17 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
return False;
}
if (!s_check_rem(s, 1)) {
return False;
}
in_uint8(s, len);
if (len & 0x80)
{
len &= ~0x80;
if (!s_check_rem(s, len)) {
return False;
}
*length = 0;
while (len--)
next_be(s, *length);
@ -66,7 +78,7 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
else
*length = len;
return s_check(s);
return True;
}
void

View File

@ -80,65 +80,101 @@ channel_init(VCHANNEL * channel, uint32 length)
return s;
}
void
channel_send(STREAM s, VCHANNEL * channel)
static void
channel_send_chunk(STREAM s, VCHANNEL * channel, uint32 length)
{
uint32 length, flags;
uint32 thislength, remaining;
uint8 *data;
uint32 flags;
uint32 thislength;
RD_BOOL inplace;
STREAM chunk;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_CHANNEL);
#endif
/* first fragment sent in-place */
s_pop_layer(s, channel_hdr);
length = s->end - s->p - 8;
logger(Protocol, Debug, "channel_send(), channel = %d, length = %d", channel->mcs_id,
length);
thislength = MIN(length, vc_chunk_size);
/* Note: In the original clipboard implementation, this number was
1592, not 1600. However, I don't remember the reason and 1600 seems
to work so.. This applies only to *this* length, not the length of
continuation or ending packets. */
/* Note: In the original clipboard implementation, this number was
1592, not 1600. However, I don't remember the reason and 1600 seems
to work so.. This applies only to *this* length, not the length of
continuation or ending packets. */
/* Actually, CHANNEL_CHUNK_LENGTH (default value is 1600 bytes) is described
in MS-RDPBCGR (s. 2.2.6, s.3.1.5.2.1) and can be set by server only
in the optional field VCChunkSize of VC Caps) */
remaining = length - thislength;
flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST;
if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
thislength = MIN(s_remaining(s), vc_chunk_size);
out_uint32_le(s, length);
out_uint32_le(s, flags);
data = s->end = s->p + thislength;
logger(Protocol, Debug, "channel_send(), sending %d bytes with FLAG_FIRST set", thislength);
sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
/* subsequent segments copied (otherwise would have to generate headers backwards) */
while (remaining > 0)
flags = 0;
if (length == s_remaining(s))
{
thislength = MIN(remaining, vc_chunk_size);
remaining -= thislength;
flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0;
if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
flags |= CHANNEL_FLAG_FIRST;
}
if (s_remaining(s) == thislength)
{
flags |= CHANNEL_FLAG_LAST;
}
if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
{
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
}
logger(Protocol, Debug, "channel_send(), sending %d bytes with flags 0x%x",
thislength, flags);
logger(Protocol, Debug, "channel_send_chunk(), sending %d bytes with flags 0x%x",
thislength, flags);
s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8);
out_uint32_le(s, length);
out_uint32_le(s, flags);
out_uint8p(s, data, thislength);
s_mark_end(s);
sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
/* first fragment sent in-place */
inplace = False;
if ((flags & (CHANNEL_FLAG_FIRST|CHANNEL_FLAG_LAST)) ==
(CHANNEL_FLAG_FIRST|CHANNEL_FLAG_LAST))
{
inplace = True;
}
data += thislength;
if (inplace)
{
s_pop_layer(s, channel_hdr);
chunk = s;
}
else
{
chunk = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8);
}
out_uint32_le(chunk, length);
out_uint32_le(chunk, flags);
if (!inplace)
{
out_uint8stream(chunk, s, thislength);
s_mark_end(chunk);
}
sec_send_to_channel(chunk, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
/* Sending modifies the current offset, so make it is marked as
fully completed. */
if (inplace)
{
in_uint8s(s, s_remaining(s));
}
if (!inplace)
{
s_free(chunk);
}
}
void
channel_send(STREAM s, VCHANNEL * channel)
{
uint32 length;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_CHANNEL);
#endif
s_pop_layer(s, channel_hdr);
in_uint8s(s, 8);
length = s_remaining(s);
logger(Protocol, Debug, "channel_send(), channel = %d, length = %d", channel->mcs_id,
length);
while (!s_check_end(s))
{
channel_send_chunk(s, channel, length);
}
#ifdef WITH_SCARD
@ -150,7 +186,6 @@ void
channel_process(STREAM s, uint16 mcs_channel)
{
uint32 length, flags;
uint32 thislength;
VCHANNEL *channel = NULL;
unsigned int i;
STREAM in;
@ -178,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->end - s->p, in->data + in->size - in->p);
memcpy(in->p, s->p, thislength);
in->p += thislength;
out_uint8stream(in, s, s_remaining(s));
if (flags & CHANNEL_FLAG_LAST)
{
in->end = in->p;
in->p = in->data;
s_mark_end(in);
s_seek(in, 0);
channel->process(in);
}
}

View File

@ -48,10 +48,11 @@ cliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length)
out_uint16_le(s, type);
out_uint16_le(s, status);
out_uint32_le(s, length);
out_uint8p(s, data, length);
out_uint8a(s, data, length);
out_uint32(s, 0); /* pad? */
s_mark_end(s);
channel_send(s, cliprdr_channel);
s_free(s);
}
/* Helper which announces our readiness to supply clipboard data
@ -118,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("cliprdr_process(), consume of packet from stream would overrun", &packet);
}
if (status == CLIPRDR_ERROR)
{
switch (type)
@ -160,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;
@ -170,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 */

268
cssp.c
View File

@ -36,14 +36,9 @@ ber_wrap_hdr_data(int tagval, STREAM in)
STREAM out;
int size = s_length(in) + 16;
out = xmalloc(sizeof(struct stream));
memset(out, 0, sizeof(struct stream));
out->data = xmalloc(size);
out->size = size;
out->p = out->data;
out = s_alloc(size);
ber_out_header(out, tagval, s_length(in));
out_uint8p(out, in->data, s_length(in));
out_stream(out, in);
s_mark_end(out);
return out;
@ -144,16 +139,19 @@ cssp_gss_get_service_name(char *server, gss_name_t * name)
}
static RD_BOOL
cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
static STREAM
cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in)
{
int conf_state;
OM_uint32 major_status;
OM_uint32 minor_status;
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);
@ -162,38 +160,41 @@ cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
{
cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to encrypt and sign message",
major_status, minor_status);
return False;
return NULL;
}
if (!conf_state)
{
logger(Core, Error,
"cssp_gss_wrap(), GSS Confidentiality failed, no encryption of message performed.");
return False;
return NULL;
}
// write enc data to out stream
out->data = out->p = xmalloc(outbuf.length);
out->size = outbuf.length;
out_uint8p(out, outbuf.value, outbuf.length);
out = s_alloc(outbuf.length);
out_uint8a(out, outbuf.value, outbuf.length);
s_mark_end(out);
s_seek(out, 0);
gss_release_buffer(&minor_status, &outbuf);
return True;
return out;
}
static RD_BOOL
cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
static STREAM
cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in)
{
OM_uint32 major_status;
OM_uint32 minor_status;
gss_qop_t qop_state;
gss_buffer_desc inbuf, outbuf;
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);
@ -201,17 +202,17 @@ cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
{
cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to decrypt message",
major_status, minor_status);
return False;
return NULL;
}
out->data = out->p = xmalloc(outbuf.length);
out->size = outbuf.length;
out_uint8p(out, outbuf.value, outbuf.length);
out = s_alloc(outbuf.length);
out_uint8a(out, outbuf.value, outbuf.length);
s_mark_end(out);
s_seek(out, 0);
gss_release_buffer(&minor_status, &outbuf);
return True;
return out;
}
@ -234,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -247,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -259,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -295,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -309,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -324,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -339,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -354,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -387,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -397,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -411,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -426,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -467,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -485,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h3);
s_free(h2);
@ -521,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -535,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h5);
s_free(h4);
@ -551,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_free(h2);
s_free(h1);
@ -564,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_uint8p(&message, h1->data, s_length(h1));
out_stream(&message, h1);
s_mark_end(&message);
s_free(h2);
s_free(h1);
@ -575,11 +576,12 @@ 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_uint8p(s, h1->data, s_length(h1));
out_stream(s, h1);
s_mark_end(s);
s_free(h1);
tcp_send(s);
s_free(s);
// cleanup
xfree(message.data);
@ -589,10 +591,10 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
}
RD_BOOL
cssp_read_tsrequest(STREAM token, STREAM pubkey)
STREAM
cssp_read_tsrequest(RD_BOOL pubkey)
{
STREAM s;
STREAM s, out;
int length;
int tagval;
struct stream packet;
@ -600,96 +602,83 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
s = tcp_recv(NULL, 4);
if (s == NULL)
return False;
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 False;
}
// get and verify the header
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
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 False;
// 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;
// parse the response and into nego token
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return False;
// version [0]
if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
return False;
return NULL;
if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of version from stream would overrun",
rdp_protocol_error("consume of version from stream would overrun",
&packet);
}
in_uint8s(s, length);
// negoToken [1]
if (token)
if (!pubkey)
{
if (!ber_in_header(s, &tagval, &length)
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1))
return False;
return NULL;
if (!ber_in_header(s, &tagval, &length)
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return False;
return NULL;
if (!ber_in_header(s, &tagval, &length)
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return False;
return NULL;
if (!ber_in_header(s, &tagval, &length)
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
return False;
return NULL;
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
return False;
return NULL;
if (!s_check_rem(s, length))
{
rdp_protocol_error("cssp_read_tsrequest(), consume of token from stream would overrun",
rdp_protocol_error("consume of token from stream would overrun",
&packet);
}
s_realloc(token, length);
s_reset(token);
out_uint8p(token, s->p, length);
s_mark_end(token);
out = s_alloc(length);
out_uint8stream(out, s, length);
s_mark_end(out);
s_seek(out, 0);
}
// pubKey [3]
if (pubkey)
else
{
if (!ber_in_header(s, &tagval, &length)
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3))
return False;
return NULL;
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
return False;
return NULL;
pubkey->data = pubkey->p = s->p;
pubkey->end = pubkey->data + length;
pubkey->size = length;
out = s_alloc(length);
out_uint8stream(out, s, length);
s_mark_end(out);
s_seek(out, 0);
}
return True;
return out;
}
RD_BOOL
@ -706,9 +695,14 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
gss_OID desired_mech = &_gss_spnego_krb5_mechanism_oid_desc;
STREAM ts_creds;
struct stream token = { 0 };
struct stream pubkey = { 0 };
struct stream pubkey_cmp = { 0 };
STREAM token;
STREAM pubkey, pubkey_cmp;
unsigned char *pubkey_data;
unsigned char *pubkey_cmp_data;
unsigned char first_byte;
RD_BOOL ret;
STREAM blob;
// Verify that system gss support spnego
if (!cssp_gss_mech_available(desired_mech))
@ -732,16 +726,19 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
return False;
}
tcp_tls_get_server_pubkey(&pubkey);
pubkey = tcp_tls_get_server_pubkey();
if (pubkey == NULL)
return False;
pubkey_cmp = NULL;
// Enter the spnego loop
OM_uint32 actual_services;
gss_OID actual_mech;
struct stream blob = { 0 };
gss_ctx = GSS_C_NO_CONTEXT;
cred = GSS_C_NO_CREDENTIAL;
token = NULL;
input_tok.length = 0;
output_tok.length = 0;
minor_status = 0;
@ -762,6 +759,11 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
&actual_mech,
&output_tok, &actual_services, &actual_time);
// input_tok might have pointed to token's data,
// but it's safe to free it now after the call
s_free(token);
token = NULL;
if (GSS_ERROR(major_status))
{
if (i == 0)
@ -786,39 +788,44 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
// Send token to server
if (output_tok.length != 0)
{
if (output_tok.length > token.size)
s_realloc(&token, output_tok.length);
s_reset(&token);
token = s_alloc(output_tok.length);
out_uint8a(token, output_tok.value, output_tok.length);
s_mark_end(token);
out_uint8p(&token, output_tok.value, output_tok.length);
s_mark_end(&token);
if (!cssp_send_tsrequest(&token, NULL, NULL))
goto bail_out;
ret = cssp_send_tsrequest(token, NULL, NULL);
s_free(token);
token = NULL;
(void) gss_release_buffer(&minor_status, &output_tok);
if (!ret)
goto bail_out;
}
// Read token from server
if (major_status & GSS_S_CONTINUE_NEEDED)
{
(void) gss_release_buffer(&minor_status, &input_tok);
if (!cssp_read_tsrequest(&token, NULL))
token = cssp_read_tsrequest(False);
if (token == NULL)
goto bail_out;
input_tok.value = token.data;
input_tok.length = s_length(&token);
input_tok.length = s_length(token);
in_uint8p(token, input_tok.value, input_tok.length);
}
else
{
// Send encrypted pubkey for verification to server
context_established = 1;
if (!cssp_gss_wrap(gss_ctx, &pubkey, &blob))
blob = cssp_gss_wrap(gss_ctx, pubkey);
if (blob == NULL)
goto bail_out;
if (!cssp_send_tsrequest(NULL, NULL, &blob))
ret = cssp_send_tsrequest(NULL, NULL, blob);
s_free(blob);
if (!ret)
goto bail_out;
context_established = 1;
@ -829,37 +836,62 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
}
while (!context_established);
s_free(token);
// read tsrequest response and decrypt for public key validation
if (!cssp_read_tsrequest(NULL, &blob))
blob = cssp_read_tsrequest(True);
if (blob == NULL)
goto bail_out;
if (!cssp_gss_unwrap(gss_ctx, &blob, &pubkey_cmp))
pubkey_cmp = cssp_gss_unwrap(gss_ctx, blob);
s_free(blob);
if (pubkey_cmp == NULL)
goto bail_out;
pubkey_cmp.data[0] -= 1;
// the first byte gets 1 added before being sent by the server
// in order to protect against replays of the data sent earlier
// by the client
in_uint8(pubkey_cmp, first_byte);
s_seek(pubkey_cmp, 0);
out_uint8(pubkey_cmp, first_byte - 1);
s_seek(pubkey_cmp, 0);
// validate public key
if (memcmp(pubkey.data, pubkey_cmp.data, s_length(&pubkey)) != 0)
in_uint8p(pubkey, pubkey_data, s_length(pubkey));
in_uint8p(pubkey_cmp, pubkey_cmp_data, s_length(pubkey_cmp));
if ((s_length(pubkey) != s_length(pubkey_cmp)) ||
(memcmp(pubkey_data, pubkey_cmp_data, s_length(pubkey)) != 0))
{
logger(Core, Error,
"cssp_connect(), public key mismatch, cannot guarantee integrity of server connection");
goto bail_out;
}
s_free(pubkey);
s_free(pubkey_cmp);
// Send TSCredentials
ts_creds = cssp_encode_tscredentials(user, password, domain);
if (!cssp_gss_wrap(gss_ctx, ts_creds, &blob))
goto bail_out;
blob = cssp_gss_wrap(gss_ctx, ts_creds);
s_free(ts_creds);
if (!cssp_send_tsrequest(NULL, &blob, NULL))
if (blob == NULL)
goto bail_out;
ret = cssp_send_tsrequest(NULL, blob, NULL);
s_free(blob);
if (!ret)
goto bail_out;
return True;
bail_out:
xfree(token.data);
s_free(token);
s_free(pubkey);
s_free(pubkey_cmp);
return False;
}

57
disk.c
View File

@ -1131,10 +1131,7 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
struct STATFS_T stat_fs;
struct fileinfo *pfinfo;
FsInfoType *fsinfo;
struct stream stmp;
memset(&stmp, 0, sizeof(stmp));
s_realloc(&stmp, PATH_MAX * 4);
STREAM stmp;
logger(Disk, Debug, "disk_query_volume_information(handle=0x%x, info_class=0x%x)", handle,
info_class);
@ -1153,16 +1150,17 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
switch (info_class)
{
case FileFsVolumeInformation:
s_reset(&stmp);
out_utf16s(&stmp, fsinfo->label);
s_mark_end(&stmp);
stmp = s_alloc(PATH_MAX * 4);
out_utf16s(stmp, fsinfo->label);
s_mark_end(stmp);
out_uint32_le(out, 0); /* volume creation time low */
out_uint32_le(out, 0); /* volume creation time high */
out_uint32_le(out, fsinfo->serial); /* serial */
out_uint32_le(out, s_length(&stmp)); /* length of string */
out_uint32_le(out, s_length(stmp)); /* length of string */
out_uint8(out, 0); /* support objects? */
out_stream(out, &stmp); /* fsinfo->label string */
out_stream(out, stmp); /* fsinfo->label string */
s_free(stmp);
break;
case FileFsSizeInformation:
@ -1183,15 +1181,16 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
break;
case FileFsAttributeInformation:
s_reset(&stmp);
out_utf16s_no_eos(&stmp, fsinfo->type);
s_mark_end(&stmp);
stmp = s_alloc(PATH_MAX * 4);
out_utf16s_no_eos(stmp, fsinfo->type);
s_mark_end(stmp);
out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
out_uint32_le(out, s_length(&stmp)); /* length of fsinfo->type string */
out_stream(out, &stmp); /* fsinfo->typ string */
out_uint32_le(out, s_length(stmp)); /* length of fsinfo->type string */
out_stream(out, stmp); /* fsinfo->typ string */
s_free(stmp);
break;
case FileFsLabelInformation:
@ -1218,7 +1217,7 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
struct dirent *pdirent;
struct stat filestat;
struct fileinfo *pfinfo;
struct stream stmp;
STREAM stmp;
logger(Disk, Debug, "disk_query_directory(handle=0x%x, info_class=0x%x, pattern=%s, ...)",
handle, info_class, pattern);
@ -1228,9 +1227,6 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
dirname = pfinfo->path;
file_attributes = 0;
memset(&stmp, 0, sizeof(stmp));
s_realloc(&stmp, PATH_MAX * 4);
switch (info_class)
{
case FileBothDirectoryInformation:
@ -1299,9 +1295,9 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
}
// Write entry name as utf16 into stmp
s_reset(&stmp);
out_utf16s_no_eos(&stmp, pdirent->d_name);
s_mark_end(&stmp);
stmp = s_alloc(PATH_MAX * 4);
out_utf16s_no_eos(stmp, pdirent->d_name);
s_mark_end(stmp);
switch (info_class)
{
@ -1327,11 +1323,11 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint32_le(out, file_attributes); /* FileAttributes */
out_uint32_le(out, s_length(&stmp)); /* length of dir entry name string */
out_uint32_le(out, s_length(stmp)); /* length of dir entry name string */
out_uint32_le(out, 0); /* EaSize */
out_uint8(out, 0); /* ShortNameLength */
out_uint8s(out, 24); /* ShortName (8.3 name) */
out_stream(out, &stmp); /* dir entry name string */
out_stream(out, stmp); /* dir entry name string */
break;
@ -1357,8 +1353,8 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint32_le(out, file_attributes);
out_uint32_le(out, s_length(&stmp)); /* dir entry name string length */
out_stream(out, &stmp); /* dir entry name */
out_uint32_le(out, s_length(stmp)); /* dir entry name string length */
out_stream(out, stmp); /* dir entry name */
break;
@ -1384,16 +1380,16 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint64_le(out, filestat.st_size); /* filesize */
out_uint32_le(out, file_attributes);
out_uint32_le(out, s_length(&stmp)); /* dir entry name string length */
out_uint32_le(out, s_length(stmp)); /* dir entry name string length */
out_uint32_le(out, 0); /* EaSize */
out_stream(out, &stmp); /* dir entry name */
out_stream(out, stmp); /* dir entry name */
break;
case FileNamesInformation:
out_uint32_le(out, s_length(&stmp)); /* dir entry name string length */
out_stream(out, &stmp); /* dir entry name */
out_uint32_le(out, s_length(stmp)); /* dir entry name string length */
out_stream(out, stmp); /* dir entry name */
break;
@ -1401,9 +1397,12 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
logger(Disk, Warning,
"disk_query_directory(), unhandled directory info class 0x%x",
info_class);
s_free(stmp);
return RD_STATUS_INVALID_PARAMETER;
}
s_free(stmp);
return RD_STATUS_SUCCESS;
}

3
dvc.c
View File

@ -268,6 +268,7 @@ dvc_send(const char *name, STREAM s)
s_mark_end(ls);
channel_send(ls, dvc_channel);
s_free(ls);
}
@ -292,6 +293,7 @@ dvc_send_capabilities_response()
s_mark_end(s);
channel_send(s, dvc_channel);
s_free(s);
}
static void
@ -320,6 +322,7 @@ dvc_send_create_response(RD_BOOL success, dvc_hdr_t hdr, uint32 channelid)
s_mark_end(s);
channel_send(s, dvc_channel);
s_free(s);
}
static void

8
iso.c
View File

@ -55,6 +55,7 @@ iso_send_msg(uint8 code)
s_mark_end(s);
tcp_send(s);
s_free(s);
}
static void
@ -78,8 +79,8 @@ iso_send_connection_request(char *username, uint32 neg_proto)
out_uint16(s, 0); /* src_ref */
out_uint8(s, 0); /* class */
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
out_uint8p(s, username, strlen(username));
out_uint8a(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
out_uint8a(s, username, strlen(username));
out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
out_uint8(s, 0x0a);
@ -95,6 +96,7 @@ iso_send_connection_request(char *username, uint32 neg_proto)
s_mark_end(s);
tcp_send(s);
s_free(s);
}
/* Receive a message on the ISO layer, return code */
@ -177,7 +179,7 @@ iso_send(STREAM s)
uint16 length;
s_pop_layer(s, iso_hdr);
length = s->end - s->p;
length = s_remaining(s);
out_uint8(s, T123_HEADER_VERSION); /* version */
out_uint8(s, 0); /* reserved */

View File

@ -79,24 +79,25 @@ licence_info(uint8 * client_random, uint8 * rsa_data,
out_uint16(s, 0);
out_uint16_le(s, 0x0201);
out_uint8p(s, client_random, SEC_RANDOM_SIZE);
out_uint8a(s, client_random, SEC_RANDOM_SIZE);
out_uint16_le(s, 2);
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8a(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8s(s, SEC_PADDING_SIZE);
out_uint16_le(s, 1);
out_uint16_le(s, licence_size);
out_uint8p(s, licence_data, licence_size);
out_uint8a(s, licence_data, licence_size);
out_uint16_le(s, 1);
out_uint16_le(s, LICENCE_HWID_SIZE);
out_uint8p(s, hwid, LICENCE_HWID_SIZE);
out_uint8a(s, hwid, LICENCE_HWID_SIZE);
out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
out_uint8a(s, signature, LICENCE_SIGNATURE_SIZE);
s_mark_end(s);
sec_send(s, sec_flags);
s_free(s);
}
/* Send a new licence request packet */
@ -120,24 +121,25 @@ licence_send_new_licence_request(uint8 * client_random, uint8 * rsa_data, char *
out_uint16(s, 0);
out_uint16_le(s, 0xff01);
out_uint8p(s, client_random, SEC_RANDOM_SIZE);
out_uint8a(s, client_random, SEC_RANDOM_SIZE);
out_uint16_le(s, 2);
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
out_uint8p(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8a(s, rsa_data, SEC_MODULUS_SIZE);
out_uint8s(s, SEC_PADDING_SIZE);
/* Username LICENSE_BINARY_BLOB */
out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB);
out_uint16_le(s, userlen);
out_uint8p(s, user, userlen);
out_uint8a(s, user, userlen);
/* Machinename LICENSE_BINARY_BLOB */
out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB);
out_uint16_le(s, hostlen);
out_uint8p(s, host, hostlen);
out_uint8a(s, host, hostlen);
s_mark_end(s);
sec_send(s, sec_flags);
s_free(s);
}
/* Process a licence request packet */
@ -204,16 +206,17 @@ licence_send_platform_challenge_response(uint8 * token, uint8 * crypt_hwid, uint
out_uint16_le(s, 1);
out_uint16_le(s, LICENCE_TOKEN_SIZE);
out_uint8p(s, token, LICENCE_TOKEN_SIZE);
out_uint8a(s, token, LICENCE_TOKEN_SIZE);
out_uint16_le(s, 1);
out_uint16_le(s, LICENCE_HWID_SIZE);
out_uint8p(s, crypt_hwid, LICENCE_HWID_SIZE);
out_uint8a(s, crypt_hwid, LICENCE_HWID_SIZE);
out_uint8p(s, signature, LICENCE_SIGNATURE_SIZE);
out_uint8a(s, signature, LICENCE_SIGNATURE_SIZE);
s_mark_end(s);
sec_send(s, sec_flags);
s_free(s);
}
/* Parse an platform challenge request packet */
@ -274,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;
@ -283,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
@ -301,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 */

14
lspci.c
View File

@ -135,17 +135,12 @@ lspci_process(STREAM s)
unsigned int pkglen;
static char *rest = NULL;
char *buf;
struct stream packet = *s;
if (!s_check(s))
{
rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
}
pkglen = s->end - s->p;
pkglen = s_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);
}
@ -169,6 +164,7 @@ lspci_send(const char *output)
len = strlen(output);
s = channel_init(lspci_channel, len);
out_uint8p(s, output, len) s_mark_end(s);
out_uint8a(s, output, len) s_mark_end(s);
channel_send(s, lspci_channel);
s_free(s);
}

31
mcs.c
View File

@ -42,7 +42,7 @@ mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens,
}
/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
static RD_BOOL
static void
mcs_parse_domain_params(STREAM s)
{
uint32 length;
@ -52,19 +52,17 @@ mcs_parse_domain_params(STREAM s)
if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_parse_domain_params(), consume domain params from stream would overrun", &packet);
rdp_protocol_error("consume domain params from stream would overrun", &packet);
}
in_uint8s(s, length);
return s_check(s);
}
/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
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__);
@ -84,10 +82,11 @@ mcs_send_connect_initial(STREAM mcs_data)
mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
out_uint8p(s, mcs_data->data, datalen);
out_uint8a(s, mcs_data->data, datalen);
s_mark_end(s);
iso_send(s);
s_free(s);
}
/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
@ -125,7 +124,7 @@ mcs_recv_connect_response(STREAM mcs_data)
if (!s_check_rem(s, length))
{
rdp_protocol_error("mcs_recv_connect_response(), consume connect id from stream would overrun", &packet);
rdp_protocol_error("consume connect id from stream would overrun", &packet);
}
mcs_parse_domain_params(s);
@ -140,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);
}
@ -161,6 +161,7 @@ mcs_send_edrq(void)
s_mark_end(s);
iso_send(s);
s_free(s);
}
/* Send an AUrq message (ASN.1 PER) */
@ -175,6 +176,7 @@ mcs_send_aurq(void)
s_mark_end(s);
iso_send(s);
s_free(s);
}
/* Expect a AUcf message (ASN.1 PER) */
@ -228,6 +230,7 @@ mcs_send_cjrq(uint16 chanid)
s_mark_end(s);
iso_send(s);
s_free(s);
}
/* Expect a CJcf message (ASN.1 PER) */
@ -275,10 +278,7 @@ mcs_send_dpu(unsigned short reason)
logger(Protocol, Debug, "mcs_send_dpu(), reason=%d", reason);
contents = malloc(sizeof(struct stream));
memset(contents, 0, sizeof(struct stream));
s_realloc(contents, 6);
s_reset(contents);
contents = s_alloc(6);
ber_out_integer(contents, reason); /* Reason */
ber_out_sequence(contents, NULL); /* SEQUENCE OF NonStandradParameters OPTIONAL */
s_mark_end(contents);
@ -290,6 +290,7 @@ mcs_send_dpu(unsigned short reason)
s_mark_end(s);
iso_send(s);
s_free(s);
}
/* Initialise an MCS transport data packet */
@ -311,7 +312,7 @@ mcs_send_to_channel(STREAM s, uint16 channel)
uint16 length;
s_pop_layer(s, mcs_hdr);
length = s->end - s->p - 8;
length = s_remaining(s) - 8;
length |= 0x8000;
out_uint8(s, (MCS_SDRQ << 2));

View File

@ -20,7 +20,7 @@
#include "rdesktop.h"
#include "orders.h"
extern uint8 *g_next_packet;
extern size_t g_next_packet;
static RDP_ORDER_STATE g_order_state;
extern RDP_VERSION g_rdp_version;
@ -101,7 +101,7 @@ rdp_in_colour(STREAM s, uint32 * colour)
}
/* Parse bounds information */
static RD_BOOL
static void
rdp_parse_bounds(STREAM s, BOUNDS * bounds)
{
uint8 present;
@ -127,12 +127,10 @@ rdp_parse_bounds(STREAM s, BOUNDS * bounds)
rdp_in_coord(s, &bounds->bottom, False);
else if (present & 128)
rdp_in_coord(s, &bounds->bottom, True);
return s_check(s);
}
/* Parse a pen */
static RD_BOOL
static void
rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
{
if (present & 1)
@ -143,8 +141,6 @@ rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
if (present & 4)
rdp_in_colour(s, &pen->colour);
return s_check(s);
}
static void
@ -176,7 +172,7 @@ setup_brush(BRUSH * out_brush, BRUSH * in_brush)
}
/* Parse a brush */
static RD_BOOL
static void
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
{
if (present & 1)
@ -193,8 +189,6 @@ rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
if (present & 16)
in_uint8a(s, &brush->pattern[1], 7);
return s_check(s);
}
/* Process a destination blt order */
@ -1258,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);
@ -1272,10 +1266,10 @@ process_secondary_order(STREAM s)
if (!s_check_rem(s, length))
{
rdp_protocol_error("process_secondary_order(), 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)
{
@ -1312,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 */
@ -1454,9 +1448,9 @@ process_orders(STREAM s, uint16 num_orders)
}
#if 0
/* not true when RDP_COMPRESSION is set */
if (s->p != g_next_packet)
if (s_tell(s) != g_next_packet)
logger(Graphics, Error, "process_orders(), %d bytes remaining",
(int) (g_next_packet - s->p));
(int) (g_next_packet - s_tell(s)));
#endif
}

View File

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

11
proto.h
View File

@ -25,6 +25,11 @@ extern "C" {
#endif
/* *INDENT-ON* */
#define UNUSED(param) ((void)param)
#ifdef __GNUC__
# define NORETURN __attribute__((noreturn))
#else
# define NORETURN
#endif // __GNUC__
/* bitmap.c */
RD_BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
/* cache.c */
@ -165,7 +170,9 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
char *directory, RD_BOOL reconnect);
void rdp_reset_state(void);
void rdp_disconnect(void);
void rdp_protocol_error(const char *message, STREAM s);
#define rdp_protocol_error(m, s) _rdp_protocol_error(__FILE__, __LINE__, __func__, m, s)
void _rdp_protocol_error(const char *file, int line, const char *func,
const char *message, STREAM s) NORETURN;
/* rdpdr.c */
int get_device_index(RD_NTHANDLE handle);
void convert_to_unix_filename(char *filename);
@ -220,7 +227,7 @@ char *tcp_get_address(void);
RD_BOOL tcp_is_connected(void);
void tcp_reset_state(void);
RD_BOOL tcp_tls_connect(void);
RD_BOOL tcp_tls_get_server_pubkey(STREAM s);
STREAM tcp_tls_get_server_pubkey();
void tcp_run_ui(RD_BOOL run);
/* asn.c */

View File

@ -836,7 +836,7 @@ main(int argc, char *argv[])
case 'u':
g_username = (char *) xmalloc(strlen(optarg) + 1);
STRNCPY(g_username, optarg, strlen(optarg) + 1);
strcpy(g_username, optarg);
username_option = 1;
break;
@ -1355,7 +1355,7 @@ main(int argc, char *argv[])
STRNCPY(domain, g_redirect_domain, sizeof(domain));
xfree(g_username);
g_username = (char *) xmalloc(strlen(g_redirect_username) + 1);
STRNCPY(g_username, g_redirect_username, strlen(g_redirect_username) + 1);
strcpy(g_username, g_redirect_username);
STRNCPY(server, g_redirect_server, sizeof(server));
flags |= RDP_INFO_AUTOLOGON;
@ -1790,7 +1790,7 @@ str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler,
buf[0] = '\0';
if (*rest)
STRNCPY(buf, *rest, buflen);
strncat(buf, input, inputlen);
strncat(buf, input, buflen);
p = buf;
while (1)

118
rdp.c
View File

@ -59,7 +59,7 @@ extern RD_BOOL g_dynamic_session_resize;
RD_BOOL g_exit_mainloop = False;
uint8 *g_next_packet;
size_t g_next_packet;
uint32 g_rdp_shareid;
extern RDPCOMP g_mppc_dict;
@ -128,6 +128,9 @@ rdp_ts_in_share_control_header(STREAM s, uint8 * type, uint16 * length)
*type = pdu_type & 0xf;
/* Give just the size of the data */
*length -= 6;
return True;
}
@ -142,7 +145,7 @@ rdp_recv(uint8 * type)
while (1)
{
/* fill stream with data if needed for parsing a new packet */
if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
if (g_next_packet == 0)
{
rdp_s = sec_recv(&is_fastpath);
if (rdp_s == NULL)
@ -155,11 +158,16 @@ rdp_recv(uint8 * type)
continue;
}
g_next_packet = rdp_s->p;
g_next_packet = s_tell(rdp_s);
}
else
{
rdp_s->p = g_next_packet;
s_seek(rdp_s, g_next_packet);
if (s_check_end(rdp_s))
{
g_next_packet = 0;
continue;
}
}
/* parse a TS_SHARECONTROLHEADER */
@ -171,7 +179,13 @@ rdp_recv(uint8 * type)
logger(Protocol, Debug, "rdp_recv(), RDP packet #%d, type 0x%x", ++g_packetno, *type);
g_next_packet += length;
if (!s_check_rem(rdp_s, length))
{
rdp_protocol_error("not enough data for PDU", rdp_s);
}
g_next_packet = s_tell(rdp_s) + length;
return rdp_s;
}
@ -194,7 +208,7 @@ rdp_send_data(STREAM s, uint8 data_pdu_type)
uint16 length;
s_pop_layer(s, rdp_hdr);
length = s->end - s->p;
length = s_remaining(s);
out_uint16_le(s, length);
out_uint16_le(s, (RDP_PDU_DATA | 0x10));
@ -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;
@ -296,9 +310,20 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
abort();
}
/* Corner case. We still want to return a null terminated string... */
if (in_len == 0) {
if (*string == NULL)
{
*string = xmalloc(1);
}
**string = '\0';
*str_size = 0;
return;
}
if (!s_check_rem(s, in_len))
{
rdp_protocol_error("rdp_in_unistr(), consume of unicode data from stream would overrun", &packet);
rdp_protocol_error("consume of unicode data from stream would overrun", &packet);
}
// if not already open
@ -323,7 +348,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 +369,7 @@ 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;
/* Always force the last byte to be a null */
*pout = 0;
if (*string)
@ -469,7 +492,7 @@ rdp_send_client_info_pdu(uint32 flags, char *domain, char *user,
if (g_redirect == True && 0 < g_redirect_cookie_len)
{
out_uint8p(s, g_redirect_cookie, g_redirect_cookie_len);
out_uint8a(s, g_redirect_cookie, g_redirect_cookie_len);
}
else
{
@ -535,6 +558,7 @@ rdp_send_client_info_pdu(uint32 flags, char *domain, char *user,
g_redirect = False;
sec_send(s, sec_flags);
s_free(s);
}
/* Send a control PDU */
@ -551,6 +575,7 @@ rdp_send_control(uint16 action)
s_mark_end(s);
rdp_send_data(s, RDP_DATA_PDU_CONTROL);
s_free(s);
}
/* Send a synchronisation PDU */
@ -568,6 +593,7 @@ rdp_send_synchronise(void)
s_mark_end(s);
rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
s_free(s);
}
/* Send a single input event */
@ -591,6 +617,7 @@ rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 par
s_mark_end(s);
rdp_send_data(s, RDP_DATA_PDU_INPUT);
s_free(s);
}
/* Send a Suppress Output PDU */
@ -625,6 +652,7 @@ rdp_send_suppress_output_pdu(enum RDP_SUPPRESS_STATUS allowupdates)
s_mark_end(s);
rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
s_free(s);
current_status = allowupdates;
}
@ -669,6 +697,7 @@ rdp_enum_bmpcache2(void)
s_mark_end(s);
rdp_send_data(s, 0x2b);
s_free(s);
offset += 169;
}
@ -691,6 +720,7 @@ rdp_send_fonts(uint16 seq)
s_mark_end(s);
rdp_send_data(s, RDP_DATA_PDU_FONT2);
s_free(s);
}
/* Output general capability set (TS_GENERAL_CAPABILITYSET) */
@ -792,7 +822,7 @@ rdp_out_ts_order_capabilityset(STREAM s)
out_uint16_le(s, 1); /* maximumOrderLevel (ignored, should be 1) */
out_uint16_le(s, 0); /* numberFonts (ignored, should be 0) */
out_uint16_le(s, orderflags); /* orderFlags */
out_uint8p(s, order_caps, 32); /* orderSupport */
out_uint8a(s, order_caps, 32); /* orderSupport */
out_uint16_le(s, 0); /* textFlags (ignored) */
out_uint16_le(s, 0); /* orderSupportExFlags */
out_uint32_le(s, 0); /* pad4OctetsB */
@ -948,6 +978,7 @@ rdp_process_virtchan_caps(STREAM s)
in_uint32_le(s, flags);
in_uint32_le(s, chunk_size);
UNUSED(flags);
vc_chunk_size = chunk_size;
}
@ -1095,7 +1126,7 @@ rdp_send_confirm_active(void)
out_uint16_le(s, sizeof(RDP_SOURCE));
out_uint16_le(s, caplen);
out_uint8p(s, RDP_SOURCE, sizeof(RDP_SOURCE));
out_uint8a(s, RDP_SOURCE, sizeof(RDP_SOURCE));
out_uint16_le(s, 17); /* num_caps */
out_uint8s(s, 2); /* pad */
@ -1128,6 +1159,7 @@ rdp_send_confirm_active(void)
s_mark_end(s);
sec_send(s, sec_flags);
s_free(s);
}
/* Process a general capability set */
@ -1210,25 +1242,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)
{
@ -1247,7 +1279,7 @@ rdp_process_server_caps(STREAM s, uint16 length)
break;
}
s->p = next;
s_seek(s, next);
}
}
@ -1268,7 +1300,7 @@ process_demand_active(STREAM s)
if (!s_check_rem(s, len_src_descriptor))
{
rdp_protocol_error("rdp_demand_active(), consume of source descriptor from stream would overrun", &packet);
rdp_protocol_error("consume of source descriptor from stream would overrun", &packet);
}
in_uint8s(s, len_src_descriptor);
@ -1416,8 +1448,7 @@ process_pointer_pdu(STREAM s)
case RDP_POINTER_MOVE:
in_uint16_le(s, x);
in_uint16_le(s, y);
if (s_check(s))
ui_move_pointer(x, y);
ui_move_pointer(x, y);
break;
case RDP_POINTER_COLOR:
@ -1521,7 +1552,7 @@ process_bitmap_data(STREAM s)
/* read compressed bitmap data */
if (!s_check_rem(s, size))
{
rdp_protocol_error("process_bitmap_data(), consume of bitmap data from stream would overrun", &packet);
rdp_protocol_error("consume of bitmap data from stream would overrun", &packet);
}
in_uint8p(s, data, size);
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
@ -1718,6 +1749,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);
@ -1734,21 +1766,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;
}
@ -2048,7 +2081,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;
}
@ -2086,7 +2119,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;
@ -2111,10 +2144,11 @@ rdp_disconnect(void)
*/
void
rdp_protocol_error(const char *message, STREAM s)
_rdp_protocol_error(const char *file, int line, const char *func,
const char *message, STREAM s)
{
logger(Protocol, Error, "%s(), %s", __func__, message);
logger(Protocol, Error, "%s:%d: %s(), %s", file, line, func, message);
if (s)
hexdump(s->p, s_length(s));
hexdump(s->data, s_length(s));
exit(0);
}

41
rdp5.c
View File

@ -21,7 +21,7 @@
#include "rdesktop.h"
extern uint8 *g_next_packet;
extern size_t g_next_packet;
extern RDPCOMP g_mppc_dict;
@ -56,8 +56,7 @@ process_ts_fp_update_by_code(STREAM s, uint8 code)
case FASTPATH_UPDATETYPE_PTR_POSITION:
in_uint16_le(s, x);
in_uint16_le(s, y);
if (s_check(s))
ui_move_pointer(x, y);
ui_move_pointer(x, y);
break;
case FASTPATH_UPDATETYPE_COLOR:
process_colour_pointer_pdu(s);
@ -79,16 +78,17 @@ 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;
static STREAM assembled[0x0F] = { 0 };
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 */
@ -101,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;
@ -133,11 +134,7 @@ process_ts_fp_updates(STREAM s)
{
if (assembled[code] == NULL)
{
assembled[code] = xmalloc(sizeof(struct stream));
memset(assembled[code], 0, sizeof(struct stream));
s_realloc(assembled[code],
RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE);
s_reset(assembled[code]);
assembled[code] = s_alloc(RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE);
}
if (frag == FASTPATH_FRAGMENT_FIRST)
@ -145,17 +142,17 @@ process_ts_fp_updates(STREAM s)
s_reset(assembled[code]);
}
out_uint8p(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();
}

142
rdpdr.c
View File

@ -204,6 +204,7 @@ rdpdr_send_client_announce_reply(void)
out_uint32_be(s, g_client_id); /* ClientID */
s_mark_end(s);
channel_send(s, rdpdr_channel);
s_free(s);
}
@ -233,6 +234,7 @@ rdpdr_send_client_name_request(void)
out_stream(s, &name);
s_mark_end(s);
channel_send(s, rdpdr_channel);
s_free(s);
}
/* Returns the size of the payload of the announce packet */
@ -300,7 +302,7 @@ rdpdr_send_client_device_list_announce(void)
{
out_uint32_le(s, g_rdpdr_device[i].device_type);
out_uint32_le(s, i); /* RDP Device ID */
out_uint8p(s, g_rdpdr_device[i].name, 8); /* preferredDosName, limited to 8 characters */
out_uint8a(s, g_rdpdr_device[i].name, 8); /* preferredDosName, limited to 8 characters */
switch (g_rdpdr_device[i].device_type)
{
case DEVICE_TYPE_DISK:
@ -314,7 +316,7 @@ rdpdr_send_client_device_list_announce(void)
disklen = strlen(diskinfo->name) + 1;
out_uint32_le(s, disklen); /* DeviceDataLength */
out_uint8p(s, diskinfo->name, disklen); /* DeviceData */
out_uint8a(s, diskinfo->name, disklen); /* DeviceData */
break;
case DEVICE_TYPE_PRINTER:
@ -357,6 +359,7 @@ rdpdr_send_client_device_list_announce(void)
s_mark_end(s);
channel_send(s, rdpdr_channel);
s_free(s);
}
void
@ -385,13 +388,14 @@ rdpdr_send_completion(uint32 device, uint32 id, uint32 status, uint32 result, ui
out_uint32_le(s, status);
out_uint32_le(s, result);
if (length)
out_uint8p(s, buffer, length);
out_uint8a(s, buffer, length);
s_mark_end(s);
logger(Protocol, Debug, "rdpdr_send_completion()");
/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
channel_send(s, rdpdr_channel);
s_free(s);
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_RDPDR);
#endif
@ -407,7 +411,6 @@ rdpdr_process_irp(STREAM s)
request,
file,
info_level,
buffer_len,
id,
major,
minor,
@ -420,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;
@ -434,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;
}
@ -482,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;
}
@ -516,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:
@ -553,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;
}
@ -584,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)
{
@ -608,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;
}
@ -641,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;
@ -658,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:
@ -674,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:
@ -703,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;
@ -756,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)
@ -801,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:
@ -818,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
@ -868,6 +881,7 @@ rdpdr_send_client_capability_response(void)
s_mark_end(s);
channel_send(s, rdpdr_channel);
s_free(s);
}
static void
@ -877,10 +891,9 @@ rdpdr_process(STREAM s)
uint16 vmin;
uint16 component;
uint16 pakid;
struct stream packet = *s;
logger(Protocol, Debug, "rdpdr_process()");
/* hexdump(s->p, s->end - s->p); */
/* hexdump(s->p, s_remaining(s)); */
in_uint16(s, component); /* RDPDR_HEADER.Component */
in_uint16(s, pakid); /* RDPDR_HEADER.PacketId */
@ -900,15 +913,6 @@ rdpdr_process(STREAM s)
in_uint32_le(s, g_client_id); /* ClientID */
/* g_client_id is sent back to server,
so lets check that we actually got
valid data from stream to prevent
that we leak back data to server */
if (!s_check(s))
{
rdp_protocol_error("rdpdr_process(), consume of g_client_id from stream did overrun", &packet);
}
/* The RDP client is responsibility to provide a random client id
if server version is < 12 */
if (vmin < 0x000c)

View File

@ -64,7 +64,7 @@ rdpedisp_process_pdu(STREAM s)
/* Read DISPLAYCONTROL_HEADER */
in_uint32_le(s, type); /* type */
in_skip(s, 4); /* length */
in_uint8s(s, 4); /* length */
logger(Protocol, Debug, "rdpedisp_process_pdu(), Got PDU type %d", type);

View File

@ -64,6 +64,7 @@ unsigned int queue_hi, queue_lo, queue_pending;
struct audio_packet packet_queue[MAX_QUEUE];
static uint8 packet_opcode;
static size_t packet_len;
static struct stream packet;
void (*wave_out_play) (void);
@ -103,6 +104,7 @@ rdpsnd_send_waveconfirm(uint16 tick, uint8 packet_index)
out_uint8(s, 0);
s_mark_end(s);
rdpsnd_send(s);
s_free(s);
logger(Sound, Debug, "rdpsnd_send_waveconfirm(), tick=%u, index=%u",
(unsigned) tick, (unsigned) packet_index);
@ -259,6 +261,7 @@ rdpsnd_process_negotiate(STREAM in)
(int) format_count);
rdpsnd_send(out);
s_free(out);
rdpsnd_negotiated = True;
}
@ -273,7 +276,7 @@ rdpsnd_process_training(STREAM in)
if (!s_check_rem(in, 4))
{
rdp_protocol_error("rdpsnd_process_training(), consume of training data from stream would overrun", &packet);
rdp_protocol_error("consume of training data from stream would overrun", &packet);
}
in_uint16_le(in, tick);
@ -286,14 +289,18 @@ rdpsnd_process_training(STREAM in)
out_uint16_le(out, packsize);
s_mark_end(out);
rdpsnd_send(out);
s_free(out);
}
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)
{
@ -342,9 +349,12 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
current_format = format;
}
rdpsnd_queue_write(rdpsnd_dsp_process
(s->p, s->end - s->p, 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:
@ -379,14 +389,12 @@ 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->end - s->p) < 4)
if (!s_check_rem(s, 4))
{
logger(Sound, Error,
"rdpsnd_process(), split at packet header, things will go south from here...");
@ -394,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->end - s->p, packet.end - packet.p);
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...",
@ -422,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);
}
}
}
@ -451,15 +459,11 @@ rdpsnddbg_process(STREAM s)
static char *rest = NULL;
char *buf;
if (!s_check(s))
{
rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
}
pkglen = s->end - s->p;
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);
@ -515,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,
@ -643,7 +645,7 @@ rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
queue_hi = next_hi;
packet->s = *s;
packet->s = s;
packet->tick = tick;
packet->index = index;
@ -677,7 +679,7 @@ rdpsnd_queue_clear(void)
while (queue_pending != queue_hi)
{
packet = &packet_queue[queue_pending];
xfree(packet->s.data);
s_free(packet->s);
queue_pending = (queue_pending + 1) % MAX_QUEUE;
}
@ -742,7 +744,7 @@ rdpsnd_queue_complete_pending(void)
(packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
elapsed /= 1000;
xfree(packet->s.data);
s_free(packet->s);
rdpsnd_send_waveconfirm((packet->tick + elapsed) % 65536, packet->index);
queue_pending = (queue_pending + 1) % MAX_QUEUE;
}

View File

@ -19,7 +19,7 @@
struct audio_packet
{
struct stream s;
STREAM s;
uint16 tick;
uint8 index;

View File

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

View File

@ -175,8 +175,8 @@ rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * format)
return True;
}
uint32
rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
STREAM
rdpsnd_dsp_resample(unsigned char *in, unsigned int size,
RD_WAVEFORMATEX * format, RD_BOOL stream_be)
{
UNUSED(stream_be);
@ -190,13 +190,15 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
int innum, outnum;
unsigned char *tmpdata = NULL, *tmp = NULL;
int samplewidth = format->wBitsPerSample / 8;
STREAM out;
int outsize = 0;
unsigned char *data;
int i;
if ((resample_to_bitspersample == format->wBitsPerSample) &&
(resample_to_channels == format->nChannels) &&
(resample_to_srate == format->nSamplesPerSec))
return 0;
return NULL;
#ifdef B_ENDIAN
if (!stream_be)
@ -260,7 +262,7 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
{
logger(Sound, Warning,
"rdpsndp_dsp_resample_set(), no sample rate converter available");
return 0;
return NULL;
}
outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
@ -285,8 +287,9 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
xfree(infloat);
outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
*out = (unsigned char *) xmalloc(outsize);
src_float_to_short_array(outfloat, (short *) *out,
out = s_alloc(outsize);
out_uint8p(out, data, outsize);
src_float_to_short_array(outfloat, (short *) data,
resample_data.output_frames_gen * resample_to_channels);
xfree(outfloat);
@ -302,8 +305,9 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
outnum = (innum * ratio1k) / 1000;
outsize = outnum * samplewidth;
*out = (unsigned char *) xmalloc(outsize);
bzero(*out, outsize);
out = s_alloc(outsize);
out_uint8p(out, data, outsize);
bzero(data, outsize);
for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
{
@ -331,7 +335,7 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
cval1 += (sint8) (cval2 * part) / 100;
memcpy(*out + (i * resample_to_channels * samplewidth) +
memcpy(data + (i * resample_to_channels * samplewidth) +
(samplewidth * j), &cval1, samplewidth);
}
}
@ -349,14 +353,14 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
sval1 += (sint16) (sval2 * part) / 100;
memcpy(*out + (i * resample_to_channels * samplewidth) +
memcpy(data + (i * resample_to_channels * samplewidth) +
(samplewidth * j), &sval1, samplewidth);
}
}
#else /* Nearest neighbor search */
for (j = 0; j < resample_to_channels; j++)
{
memcpy(*out + (i * resample_to_channels * samplewidth) + (samplewidth * j),
memcpy(out + (i * resample_to_channels * samplewidth) + (samplewidth * j),
in + (source * resample_to_channels * samplewidth) +
(samplewidth * j), samplewidth);
}
@ -378,7 +382,7 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
{
for (i = 0; i < outsize; i++)
{
*out[i] = *out[i * 2];
data[i] = data[i * 2];
}
outsize /= 2;
}
@ -386,16 +390,17 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
#ifdef B_ENDIAN
if (!stream_be)
rdpsnd_dsp_swapbytes(*out, outsize, format);
rdpsnd_dsp_swapbytes(data, outsize, format);
#endif
return outsize;
return out;
}
STREAM
rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
RD_WAVEFORMATEX * format)
{
static struct stream out;
STREAM out;
RD_BOOL stream_be = False;
/* softvol and byteswap do not change the amount of data they
@ -411,20 +416,19 @@ rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver *
}
#endif
out.data = NULL;
out = NULL;
if (current_driver->need_resampling)
out.size = rdpsnd_dsp_resample(&out.data, data, size, format, stream_be);
out = rdpsnd_dsp_resample(data, size, format, stream_be);
if (out.data == NULL)
if (out == NULL)
{
out.data = (unsigned char *) xmalloc(size);
memcpy(out.data, data, size);
out.size = size;
out = s_alloc(size);
out_uint8a(out, data, size);
}
out.p = out.data;
out.end = out.p + out.size;
s_mark_end(out);
s_seek(out, 0);
return &out;
return out;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -411,17 +411,22 @@ sun_play(void)
struct audio_packet *packet;
ssize_t len;
STREAM out;
size_t before;
const unsigned char *data;
/* We shouldn't be called if the queue is empty, but still */
if (rdpsnd_queue_empty())
return;
packet = rdpsnd_queue_current_packet();
out = &packet->s;
out = packet->s;
len = out->end - out->p;
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;

191
scard.c
View File

@ -237,10 +237,8 @@ scard_enum_devices(uint32 * id, char *optarg)
tmpMap = nameMapList + nameMapCount - 1;
len = strlen(alias);
strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
len = strlen(name);
strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
STRNCPY(tmpMap->alias, alias, sizeof(tmpMap->alias));
STRNCPY(tmpMap->name, name, sizeof(tmpMap->name));
if (vendor)
{
@ -248,8 +246,8 @@ scard_enum_devices(uint32 * id, char *optarg)
if (len > 0)
{
memset(tmpMap->vendor, 0, 128);
strncpy(tmpMap->vendor, vendor,
(len > 127) ? (127) : (len));
STRNCPY(tmpMap->vendor, vendor,
sizeof(tmpMap->vendor));
}
else
tmpMap->vendor[0] = '\0';
@ -550,7 +548,7 @@ outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned
{
if (header < length)
length = header;
out_uint8p(out, buffer, length);
out_uint8a(out, buffer, length);
outRepos(out, length);
}
}
@ -564,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);
}
@ -626,11 +624,11 @@ outString(STREAM out, char *source, RD_BOOL wide)
buffer[2 * i] = reader[i];
buffer[2 * i + 1] = '\0';
}
out_uint8p(out, buffer, 2 * dataLength);
out_uint8a(out, buffer, 2 * dataLength);
}
else
{
out_uint8p(out, reader, dataLength);
out_uint8a(out, reader, dataLength);
}
SC_xfreeallmemory(&lcHandle);
@ -641,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));
}
@ -719,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;
}
@ -729,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);
@ -754,6 +753,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -764,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);
@ -788,6 +788,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -801,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;
@ -865,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;
}
@ -893,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);
@ -968,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;
}
@ -984,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);
@ -1016,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;
}
@ -1029,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);
@ -1078,6 +1084,7 @@ TS_SCardDisconnect(STREAM in, STREAM out)
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1164,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);
@ -1199,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),
@ -1257,10 +1264,11 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
cur->dwEventState = swap32(cur->dwEventState);
cur->cbAtr = swap32(cur->cbAtr);
out_uint8p(out, (void *) ((unsigned char **) cur + 2),
out_uint8a(out, (void *) ((unsigned char **) cur + 2),
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1272,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);
@ -1291,6 +1299,7 @@ TS_SCardCancel(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardCancel(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1311,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));
@ -1421,11 +1430,12 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
rsCur->dwEventState = swap32(rsCur->dwEventState);
rsCur->cbAtr = swap32(rsCur->cbAtr);
out_uint8p(out, (void *) ((unsigned char **) rsCur + 2),
out_uint8a(out, (void *) ((unsigned char **) rsCur + 2),
sizeof(SCARD_READERSTATE) - 2 * sizeof(unsigned char *));
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1437,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])",
@ -1453,6 +1463,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1464,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);
@ -1485,6 +1496,7 @@ TS_SCardEndTransaction(STREAM in, STREAM out)
logger(SmartCard, Debug, "TS_SCardEndTransaction(), success");
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -1533,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)
@ -1553,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);
@ -1697,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;
}
@ -1714,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",
@ -1792,31 +1805,33 @@ 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);
out_uint32_le(out, dwProtocol);
out_uint8p(out, atr, dwAtrLen);
out_uint8a(out, atr, dwAtrLen);
if (dwAtrLen < 32)
{
out_uint8s(out, 32 - dwAtrLen);
}
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;
}
@ -1833,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",
@ -1903,10 +1918,11 @@ TS_SCardState(STREAM in, STREAM out)
out_uint32_le(out, dwAtrLen);
out_uint32_le(out, 0x00000001);
out_uint32_le(out, dwAtrLen);
out_uint8p(out, atr, dwAtrLen);
out_uint8a(out, atr, dwAtrLen);
outRepos(out, dwAtrLen);
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -1928,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);
@ -1976,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;
}
@ -1992,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);
@ -2040,12 +2057,13 @@ TS_SCardGetAttrib(STREAM in, STREAM out)
}
else
{
out_uint8p(out, pbAttr, dwAttrLen);
out_uint8a(out, pbAttr, dwAttrLen);
}
outRepos(out, dwAttrLen);
out_uint32_le(out, 0x00000000);
}
outForceAlignment(out, 8);
s_mark_end(out);
return rv;
}
@ -2062,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);
@ -2100,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;
}
@ -2125,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)
{
@ -2238,11 +2257,12 @@ TS_SCardControl(STREAM in, STREAM out)
out_uint32_le(out, nBytesReturned);
if (nBytesReturned > 0)
{
out_uint8p(out, pOutBuffer, nBytesReturned);
out_uint8a(out, pOutBuffer, nBytesReturned);
outRepos(out, nBytesReturned);
}
outForceAlignment(out, 8);
s_mark_end(out);
SC_xfreeallmemory(&lcHandle);
return rv;
}
@ -2262,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 */
@ -2272,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)
@ -2412,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;
@ -2440,6 +2463,7 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
static STREAM
duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
{
// FIXME: Shouldn't be allocating streams manually
STREAM d = SC_xmalloc(handle, sizeof(struct stream));
if (d != NULL)
{
@ -2575,13 +2599,18 @@ SC_deviceControl(PSCThreadData data)
RD_NTSTATUS status;
size_t buffer_len = 0;
status = scard_device_control(data->handle, data->request, data->in, data->out, data->srv_buf_len);
buffer_len = (size_t) data->out->p - (size_t) data->out->data;
buffer_len = s_tell(data->out);
/* if iorequest belongs to another epoch, don't send response
back to server due to it's considered as abandoned.
*/
if (data->epoch == curEpoch)
rdpdr_send_completion(data->device, data->id, status, buffer_len, data->out->data, buffer_len);
{
uint8 *buf;
s_seek(data->out, 0);
in_uint8p(data->out, buf, buffer_len);
rdpdr_send_completion(data->device, data->id, status, buffer_len, buf, buffer_len);
}
SC_destroyThreadData(data);
}

View File

@ -376,17 +376,12 @@ seamless_process(STREAM s)
{
unsigned int pkglen;
char *buf;
struct stream packet = *s;
if (!s_check(s))
{
rdp_protocol_error("seamless_process(), stream is in unstable state", &packet);
}
pkglen = s->end - s->p;
pkglen = s_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);
@ -446,11 +441,12 @@ seamless_send(const char *command, const char *format, ...)
len++;
s = channel_init(seamless_channel, len);
out_uint8p(s, buf, len) s_mark_end(s);
out_uint8a(s, buf, len) s_mark_end(s);
logger(Core, Debug, "seamless_send(), sending '%s'", buf);
channel_send(s, seamless_channel);
s_free(s);
return seamless_serial++;
}

123
secure.c
View File

@ -351,10 +351,12 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
if (flags & SEC_ENCRYPT)
{
unsigned char *data;
flags &= ~SEC_ENCRYPT;
datalen = s->end - s->p - 8;
sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
sec_encrypt(s->p + 8, datalen);
datalen = s_remaining(s) - 8;
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);
@ -384,11 +386,12 @@ sec_establish_key(void)
s = sec_init(flags, length + 4);
out_uint32_le(s, length);
out_uint8p(s, g_sec_crypted_random, g_server_public_key_len);
out_uint8a(s, g_sec_crypted_random, g_server_public_key_len);
out_uint8s(s, SEC_PADDING_SIZE);
s_mark_end(s);
sec_send(s, flags);
s_free(s);
}
/* Output connect initial data blob */
@ -523,6 +526,10 @@ sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
{
uint32 magic, modulus_len;
if (!s_check_rem(s, 8)) {
return False;
}
in_uint32_le(s, magic);
if (magic != SEC_RSA_MAGIC)
{
@ -541,13 +548,17 @@ sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
return False;
}
if (!s_check_rem(s, 1 + SEC_EXPONENT_SIZE + modulus_len + SEC_PADDING_SIZE)) {
return False;
}
in_uint8s(s, 8); /* modulus_bits, unknown */
in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
in_uint8a(s, modulus, modulus_len);
in_uint8s(s, SEC_PADDING_SIZE);
g_server_public_key_len = modulus_len;
return s_check(s);
return True;
}
/* Parse a public signature structure */
@ -578,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__);
@ -604,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;
}
@ -618,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)
{
@ -654,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");
@ -674,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,
@ -697,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,
@ -708,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);
@ -805,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) */
@ -814,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);
@ -822,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)
{
@ -847,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);
}
}
@ -860,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)
{
@ -873,35 +887,50 @@ sec_recv(RD_BOOL * is_fastpath)
if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
{
if (!s_check_rem(s, 8)) {
rdp_protocol_error("sec_recv(), consume fastpath signature from stream would overrun", &packet);
rdp_protocol_error("consume fastpath signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p);
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)) {
rdp_protocol_error("sec_recv(), consume encrypt signature from stream would overrun", &packet);
rdp_protocol_error("consume encrypt signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p);
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;
}
@ -911,14 +940,18 @@ sec_recv(RD_BOOL * is_fastpath)
uint8 swapbyte;
if (!s_check_rem(s, 8)) {
rdp_protocol_error("sec_recv(), consume redirect signature from stream would overrun", &packet);
rdp_protocol_error("consume redirect signature from stream would overrun", &packet);
}
in_uint8s(s, 8); /* signature */
sec_decrypt(s->p, s->end - s->p);
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
@ -926,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;
}
}
}
@ -947,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)
@ -968,25 +1002,24 @@ RD_BOOL
sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
{
uint32 selected_proto;
struct stream mcs_data;
STREAM mcs_data;
/* Start a MCS connect sequence */
if (!mcs_connect_start(server, username, domain, password, reconnect, &selected_proto))
return False;
/* We exchange some RDP data during the MCS-Connect */
mcs_data.size = 512;
mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
sec_out_mcs_connect_initial_pdu(&mcs_data, selected_proto);
mcs_data = s_alloc(512);
sec_out_mcs_connect_initial_pdu(mcs_data, selected_proto);
/* finalize the MCS connect sequence */
if (!mcs_connect_finalize(&mcs_data))
if (!mcs_connect_finalize(mcs_data))
return False;
/* sec_process_mcs_data(&mcs_data); */
if (g_encryption)
sec_establish_key();
xfree(mcs_data.data);
s_free(mcs_data);
return True;
}

14
ssl.c
View File

@ -74,20 +74,6 @@ rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len)
arcfour_crypt(rc4, len, out_data, in_data);
}
static void
reverse(uint8 * p, int len)
{
int i, j;
uint8 temp;
for (i = 0, j = len - 1; i < j; i++, j--)
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
void
rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
uint8 * exponent)

View File

@ -25,6 +25,31 @@
extern char g_codepage[16];
STREAM
s_alloc(unsigned int size)
{
STREAM s;
s = xmalloc(sizeof(struct stream));
memset(s, 0, sizeof(struct stream));
s_realloc(s, size);
return s;
}
STREAM
s_inherit(unsigned char *data, unsigned int size)
{
STREAM s;
s = xmalloc(sizeof(struct stream));
memset(s, 0, sizeof(struct stream));
s->p = s->data = data;
s->size = size;
return s;
}
void
s_realloc(STREAM s, unsigned int size)
{
@ -59,6 +84,8 @@ s_reset(STREAM s)
void
s_free(STREAM s)
{
if (s == NULL)
return;
free(s->data);
free(s);
}

118
stream.h
View File

@ -41,8 +41,15 @@ typedef struct stream
}
*STREAM;
/* Return a newly allocated STREAM object of the specified size */
STREAM s_alloc(unsigned int size);
/* Wrap an existing buffer in a STREAM object, transferring ownership */
STREAM s_inherit(unsigned char *data, unsigned int size);
/* Resize an existing STREAM object, keeping all data and offsets intact */
void s_realloc(STREAM s, unsigned int size);
/* Free STREAM object and its associated buffer */
void s_free(STREAM s);
/* Reset all internal offsets, but keep the allocated size */
void s_reset(STREAM s);
void out_utf16s(STREAM s, const char *string);
@ -52,42 +59,60 @@ void out_utf16s_no_eos(STREAM s, const char *string);
size_t in_ansi_string(STREAM s, char *string, size_t len);
/* Store current offset as header h and skip n bytes */
#define s_push_layer(s,h,n) { (s)->h = (s)->p; (s)->p += n; }
/* Set header h as current offset */
#define s_pop_layer(s,h) (s)->p = (s)->h;
/* Mark current offset as end of readable data */
#define s_mark_end(s) (s)->end = (s)->p;
#define s_check(s) ((s)->p <= (s)->end)
#define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
/* Return current read offset in the STREAM */
#define s_tell(s) (size_t)((s)->p - (s)->data)
/* Set current read offset in the STREAM */
#define s_seek(s,o) (s)->p = (s)->data; s_assert_r(s,o); (s)->p += o;
/* Returns number of bytes that can still be read from STREAM */
#define s_remaining(s) (size_t)((s)->end - (s)->p)
/* True if at least n bytes can still be read */
#define s_check_rem(s,n) (((s)->p <= (s)->end) && ((size_t)n <= s_remaining(s)))
/* True if all data has been read */
#define s_check_end(s) ((s)->p == (s)->end)
/* Return the total number of bytes that can be read */
#define s_length(s) ((s)->end - (s)->data)
#define s_left(s) ((s)->size - ((s)->p - (s)->data))
/* Return the number of bytes that can still be written */
#define s_left(s) ((s)->size - (size_t)((s)->p - (s)->data))
/* Verify that there is enough data/space before accessing a STREAM */
#define s_assert_r(s,n) { if (!s_check_rem(s, n)) rdp_protocol_error( "unexpected stream overrun", s); }
#define s_assert_w(s,n) { if (s_left(s) < (size_t)n) { logger(Core, Error, "%s:%d: %s(), %s", __FILE__, __LINE__, __func__, "unexpected stream overrun"); exit(0); } }
/* Read/write an unsigned integer in little-endian order */
#if defined(L_ENDIAN) && !defined(NEED_ALIGN)
#define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; }
#define in_uint32_le(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; }
#define in_uint64_le(s,v) { v = *(uint64 *)((s)->p); (s)->p += 8; }
#define out_uint16_le(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; }
#define out_uint32_le(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; }
#define out_uint64_le(s,v) { *(uint64 *)((s)->p) = v; (s)->p += 8; }
#define in_uint16_le(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; }
#define in_uint32_le(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; }
#define in_uint64_le(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; }
#define out_uint16_le(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; }
#define out_uint32_le(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; }
#define out_uint64_le(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; }
#else
#define in_uint16_le(s,v) { v = *((s)->p++); v += *((s)->p++) << 8; }
#define in_uint32_le(s,v) { in_uint16_le(s,v) \
#define in_uint16_le(s,v) { s_assert_r(s, 2); v = *((s)->p++); v += *((s)->p++) << 8; }
#define in_uint32_le(s,v) { s_assert_r(s, 4); in_uint16_le(s,v) \
v += *((s)->p++) << 16; v += *((s)->p++) << 24; }
#define in_uint64_le(s,v) { in_uint32_le(s,v) \
#define in_uint64_le(s,v) { s_assert_r(s, 8); in_uint32_le(s,v) \
v += *((s)->p++) << 32; v += *((s)->p++) << 40; \
v += *((s)->p++) << 48; v += *((s)->p++) << 56; }
#define out_uint16_le(s,v) { *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; }
#define out_uint32_le(s,v) { out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); }
#define out_uint64_le(s,v) { out_uint32_le(s, (v) & 0xffffffff); out_uint32_le(s, ((v) >> 32) & 0xffffffff); }
#define out_uint16_le(s,v) { s_assert_w(s, 2); *((s)->p++) = (v) & 0xff; *((s)->p++) = ((v) >> 8) & 0xff; }
#define out_uint32_le(s,v) { s_assert_w(s, 4); out_uint16_le(s, (v) & 0xffff); out_uint16_le(s, ((v) >> 16) & 0xffff); }
#define out_uint64_le(s,v) { s_assert_w(s, 8); out_uint32_le(s, (v) & 0xffffffff); out_uint32_le(s, ((v) >> 32) & 0xffffffff); }
#endif
/* Read/write an unsigned integer in big-endian order */
#if defined(B_ENDIAN) && !defined(NEED_ALIGN)
#define in_uint16_be(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; }
#define in_uint32_be(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; }
#define in_uint64_be(s,v) { v = *(uint64 *)((s)->p); (s)->p += 8; }
#define out_uint16_be(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; }
#define out_uint32_be(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; }
#define out_uint64_be(s,v) { *(uint64 *)((s)->p) = v; (s)->p += 8; }
#define in_uint16_be(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; }
#define in_uint32_be(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; }
#define in_uint64_be(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; }
#define out_uint16_be(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; }
#define out_uint32_be(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; }
#define out_uint64_be(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; }
#define B_ENDIAN_PREFERRED
#define in_uint16(s,v) in_uint16_be(s,v)
@ -99,12 +124,12 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
#define out_uint64(s,v) out_uint64_be(s,v)
#else
#define in_uint16_be(s,v) { v = *((s)->p++); next_be(s,v); }
#define in_uint32_be(s,v) { in_uint16_be(s,v); next_be(s,v); next_be(s,v); }
#define in_uint64_be(s,v) { in_uint32_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); }
#define out_uint16_be(s,v) { *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; }
#define out_uint32_be(s,v) { out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); }
#define out_uint64_be(s,v) { out_uint32_be(s, ((v) >> 32) & 0xffffffff); out_uint32_be(s, (v) & 0xffffffff); }
#define in_uint16_be(s,v) { s_assert_r(s, 2); v = *((s)->p++); next_be(s,v); }
#define in_uint32_be(s,v) { s_assert_r(s, 4); in_uint16_be(s,v); next_be(s,v); next_be(s,v); }
#define in_uint64_be(s,v) { s_assert_r(s, 8); in_uint32_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); next_be(s,v); }
#define out_uint16_be(s,v) { s_assert_w(s, 2); *((s)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; }
#define out_uint32_be(s,v) { s_assert_w(s, 4); out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); }
#define out_uint64_be(s,v) { s_assert_w(s, 8); out_uint32_be(s, ((v) >> 32) & 0xffffffff); out_uint32_be(s, (v) & 0xffffffff); }
#endif
#ifndef B_ENDIAN_PREFERRED
@ -116,18 +141,35 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
#define out_uint64(s,v) out_uint64_le(s,v)
#endif
#define in_uint8(s,v) v = *((s)->p++);
#define in_uint8p(s,v,n) { v = (s)->p; (s)->p += n; }
#define in_uint8a(s,v,n) { memcpy(v,(s)->p,n); (s)->p += n; }
#define in_uint8s(s,n) (s)->p += n;
#define in_skip(s,n) in_uint8s(s,n)
#define out_uint8(s,v) *((s)->p++) = v;
#define out_uint8p(s,v,n) { memcpy((s)->p,v,n); (s)->p += n; }
#define out_uint8a(s,v,n) out_uint8p(s,v,n);
#define out_uint8s(s,n) { memset((s)->p,0,n); (s)->p += n; }
#define out_stream(s, v) out_uint8p(s, (v)->data, s_length((v)))
/* Read a single unsigned byte in v from STREAM s */
#define in_uint8(s,v) { s_assert_r(s, 1); v = *((s)->p++); }
/* Return a pointer in v to manually read n bytes from STREAM s */
#define in_uint8p(s,v,n) { s_assert_r(s, n); v = (s)->p; (s)->p += n; }
/* Copy n bytes from STREAM s in to array v */
#define in_uint8a(s,v,n) { s_assert_r(s, n); memcpy(v,(s)->p,n); (s)->p += n; }
/* Skip reading n bytes in STREAM s */
#define in_uint8s(s,n) { s_assert_r(s, n); (s)->p += n; }
/* Write a single unsigned byte from v to STREAM s */
#define out_uint8(s,v) { s_assert_w(s, 1); *((s)->p++) = v; }
/* Return a pointer in v to manually fill in n bytes in STREAM s */
#define out_uint8p(s,v,n) { s_assert_w(s, n); v = (s)->p; (s)->p += n; }
/* Copy n bytes from array v in to STREAM s */
#define out_uint8a(s,v,n) { s_assert_w(s, n); memcpy((s)->p,v,n); (s)->p += n; }
/* Fill n bytes with 0:s in STREAM s */
#define out_uint8s(s,n) { s_assert_w(s, n); memset((s)->p,0,n); (s)->p += n; }
#define next_be(s,v) v = ((v) << 8) + *((s)->p++);
/* Copy n bytes from STREAM s in to STREAM v */
#define in_uint8stream(s,v,n) { s_assert_r(s, n); out_uint8a((v), (s)->p, n); (s)->p += n; }
/* Copy n bytes in to STREAM s from STREAM v */
#define out_uint8stream(s,v,n) in_uint8stream(v,s,n)
/* 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; }
/* Read one more byte of an unsigned big-endian integer */
#define next_be(s,v) { s_assert_r(s, 1); v = ((v) << 8) + *((s)->p++); }
#endif /* _STREAM_H */

122
tcp.c
View File

@ -58,12 +58,6 @@
#define INADDR_NONE ((unsigned long) -1)
#endif
#ifdef WITH_SCARD
#define STREAM_COUNT 8
#else
#define STREAM_COUNT 1
#endif
#ifdef IPv6
static struct addrinfo *g_server_address = NULL;
#else
@ -75,7 +69,6 @@ static RD_BOOL g_ssl_initialized = False;
static int g_sock;
static RD_BOOL g_run_ui = False;
static struct stream g_in;
static struct stream g_out[STREAM_COUNT];
int g_tcp_port_rdp = TCP_PORT_RDP;
extern RD_BOOL g_exit_mainloop;
@ -109,28 +102,16 @@ tcp_can_send(int sck, int millis)
STREAM
tcp_init(uint32 maxlen)
{
static int cur_stream_id = 0;
STREAM result = NULL;
#ifdef WITH_SCARD
scard_lock(SCARD_LOCK_TCP);
#endif
result = &g_out[cur_stream_id];
s_realloc(result, maxlen);
s_reset(result);
cur_stream_id = (cur_stream_id + 1) % STREAM_COUNT;
#ifdef WITH_SCARD
scard_unlock(SCARD_LOCK_TCP);
#endif
return result;
return s_alloc(maxlen);
}
/* Send TCP transport data packet */
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;
@ -139,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
@ -159,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)
@ -179,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);
@ -190,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)
@ -199,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)
@ -235,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)) {
@ -251,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)
@ -273,6 +257,7 @@ tcp_recv(STREAM s, uint32 length)
}
}
// FIXME: Should probably have a macro for this
s->end += rcvd;
length -= rcvd;
}
@ -349,9 +334,6 @@ tcp_tls_connect(void)
{
int err;
int type;
int status;
gnutls_datum_t out;
gnutls_certificate_credentials_t xcred;
/* Initialize TLS session */
@ -422,8 +404,8 @@ fail:
}
/* Get public key from server of TLS 1.x connection */
RD_BOOL
tcp_tls_get_server_pubkey(STREAM s)
STREAM
tcp_tls_get_server_pubkey()
{
int ret;
unsigned int list_size;
@ -436,8 +418,7 @@ tcp_tls_get_server_pubkey(STREAM s)
int pk_size;
uint8_t pk_data[1024];
s->data = s->p = NULL;
s->size = 0;
STREAM s = NULL;
cert_list = gnutls_certificate_get_peers(g_tls_session, &list_size);
@ -489,11 +470,10 @@ tcp_tls_get_server_pubkey(STREAM s)
goto out;
}
s->size = pk_size;
s->data = s->p = xmalloc(s->size);
memcpy((void *)s->data, (void *)pk_data, pk_size);
s->p = s->data;
s->end = s->p + s->size;
s = s_alloc(pk_size);
out_uint8a(s, pk_data, pk_size);
s_mark_end(s);
s_seek(s, 0);
out:
if ((e.size != 0) && (e.data)) {
@ -504,7 +484,7 @@ out:
free(m.data);
}
return (s->size != 0);
return s;
}
/* Helper function to determine if rdesktop should resolve hostnames again or not */
@ -530,7 +510,6 @@ tcp_connect(char *server)
{
socklen_t option_len;
uint32 option_value;
int i;
char buf[NI_MAXHOST];
#ifdef IPv6
@ -681,12 +660,6 @@ tcp_connect(char *server)
g_in.size = 4096;
g_in.data = (uint8 *) xmalloc(g_in.size);
for (i = 0; i < STREAM_COUNT; i++)
{
g_out[i].size = 4096;
g_out[i].data = (uint8 *) xmalloc(g_out[i].size);
}
/* After successful connect: update the last server name */
if (g_last_server_name)
xfree(g_last_server_name);
@ -698,8 +671,6 @@ tcp_connect(char *server)
void
tcp_disconnect(void)
{
int i;
if (g_ssl_initialized) {
(void)gnutls_bye(g_tls_session, GNUTLS_SHUT_WR);
gnutls_deinit(g_tls_session);
@ -715,13 +686,6 @@ tcp_disconnect(void)
g_in.size = 0;
xfree(g_in.data);
g_in.data = NULL;
for (i = 0; i < STREAM_COUNT; i++)
{
g_out[i].size = 0;
xfree(g_out[i].data);
g_out[i].data = NULL;
}
}
char *
@ -755,16 +719,8 @@ tcp_is_connected()
void
tcp_reset_state(void)
{
int i;
/* Clear the incoming stream */
s_reset(&g_in);
/* Clear the outgoing stream(s) */
for (i = 0; i < STREAM_COUNT; i++)
{
s_reset(&g_out[i]);
}
}
void

View File

@ -46,23 +46,13 @@ xfree(void *mem)
free(mem);
}
static struct stream *stream_new(size_t size) {
struct stream *s;
s = malloc(sizeof(struct stream));
memset(s, 0, sizeof(struct stream));
s_realloc(s, size);
s_reset(s);
return(s);
}
Ensure(ASN1, can_create_empty_sequence)
{
struct stream *s, *empty;
uint8_t expected_data[] = {0x30, 0x00};
s = stream_new(100);
empty = stream_new(100);
s = s_alloc(100);
empty = s_alloc(100);
ber_out_sequence(s, empty);
s_mark_end(s);
@ -76,7 +66,7 @@ Ensure(ASN1, can_create_empty_sequence_using_null)
struct stream *s;
uint8_t expected_data[] = {0x30, 0x00};
s = stream_new(100);
s = s_alloc(100);
ber_out_sequence(s, NULL);
s_mark_end(s);
@ -90,8 +80,8 @@ Ensure(ASN1, can_create_sequence_of_two_integers)
struct stream *s, *content;
uint8_t expected_data[] = {0x30, 0x08, 0x02, 0x02, 0x00, 0xbe, 0x02, 0x02, 0x00, 0xef};
s = stream_new(100);
content = stream_new(100);
s = s_alloc(100);
content = s_alloc(100);
ber_out_integer(content, 0xbe);
ber_out_integer(content, 0xef);
@ -109,8 +99,8 @@ Ensure(ASN1, can_create_sequence_of_one_integer)
struct stream *s, *content;
uint8_t expected_data[] = {0x30, 0x04, 0x02, 0x02, 0x00, 0xbe};
s = stream_new(100);
content = stream_new(100);
s = s_alloc(100);
content = s_alloc(100);
ber_out_integer(content, 0xbe);
s_mark_end(content);

View File

@ -52,15 +52,6 @@ xfree(void *mem)
free(mem);
}
static struct stream *stream_new(size_t size) {
struct stream *s;
s = malloc(sizeof(struct stream));
memset(s, 0, sizeof(struct stream));
s_realloc(s, size);
s_reset(s);
return(s);
}
/* Test function */
Ensure(MCS, should_produce_valid_packet_for_McsSendCJrq)
@ -69,7 +60,7 @@ Ensure(MCS, should_produce_valid_packet_for_McsSendCJrq)
uint8_t content[] = {0x38, 0x00, 0x2A, 0x00, 0x0D};
struct stream *s;
s = stream_new(5);
s = s_alloc(5);
chan_id = 13;
g_mcs_userid = 42;
@ -89,7 +80,7 @@ Ensure(MCS, should_produce_valid_packet_for_McsSendDPU)
struct stream *s;
uint8_t content[] = {0x30, 0x06, 0x02, 0x02, 0x00, reason, 0x30, 0x00};
s = stream_new(8);
s = s_alloc(8);
expect(logger);
expect(iso_init, will_return(s));

View File

@ -412,17 +412,6 @@ Ensure(Resize, UsingRDPEDISPHonoursServerSessionWidthConstraintMustBeEven)
free(s.data);
}
/* FIXME: promote to actual function in stream.c */
STREAM s_alloc(size_t capacity)
{
STREAM s;
s = xmalloc(sizeof(struct stream));
memset(s, 0, sizeof(struct stream));
s_realloc(s, capacity);
s_reset(s);
return s;
}
void get_width_and_height_from_mcs_connect_initial(int *width, int *height)
{
STREAM s;
@ -433,7 +422,7 @@ void get_width_and_height_from_mcs_connect_initial(int *width, int *height)
/* Rewind and extract the requested session size */
s_reset(s);
in_skip(s, 31);
in_uint8s(s, 31);
in_uint16_le(s, *width); /* desktopWidth */
in_uint16_le(s, *height); /* desktopHeight */