Merge branch 'secfix' of https://github.com/CendioOssman/rdesktop
This commit is contained in:
commit
a88cd226bb
14
asn.c
14
asn.c
@ -41,10 +41,16 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
|
|||||||
|
|
||||||
if (tagval > 0xff)
|
if (tagval > 0xff)
|
||||||
{
|
{
|
||||||
|
if (!s_check_rem(s, 2)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
in_uint16_be(s, tag);
|
in_uint16_be(s, tag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (!s_check_rem(s, 1)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
in_uint8(s, tag);
|
in_uint8(s, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,11 +60,17 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 1)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
in_uint8(s, len);
|
in_uint8(s, len);
|
||||||
|
|
||||||
if (len & 0x80)
|
if (len & 0x80)
|
||||||
{
|
{
|
||||||
len &= ~0x80;
|
len &= ~0x80;
|
||||||
|
if (!s_check_rem(s, len)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
*length = 0;
|
*length = 0;
|
||||||
while (len--)
|
while (len--)
|
||||||
next_be(s, *length);
|
next_be(s, *length);
|
||||||
@ -66,7 +78,7 @@ ber_parse_header(STREAM s, int tagval, uint32 *length)
|
|||||||
else
|
else
|
||||||
*length = len;
|
*length = len;
|
||||||
|
|
||||||
return s_check(s);
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
147
channels.c
147
channels.c
@ -80,65 +80,101 @@ channel_init(VCHANNEL * channel, uint32 length)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
channel_send(STREAM s, VCHANNEL * channel)
|
channel_send_chunk(STREAM s, VCHANNEL * channel, uint32 length)
|
||||||
{
|
{
|
||||||
uint32 length, flags;
|
uint32 flags;
|
||||||
uint32 thislength, remaining;
|
uint32 thislength;
|
||||||
uint8 *data;
|
RD_BOOL inplace;
|
||||||
|
STREAM chunk;
|
||||||
|
|
||||||
#ifdef WITH_SCARD
|
/* Note: In the original clipboard implementation, this number was
|
||||||
scard_lock(SCARD_LOCK_CHANNEL);
|
1592, not 1600. However, I don't remember the reason and 1600 seems
|
||||||
#endif
|
to work so.. This applies only to *this* length, not the length of
|
||||||
|
continuation or ending packets. */
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
/* Actually, CHANNEL_CHUNK_LENGTH (default value is 1600 bytes) is described
|
/* 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 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) */
|
in the optional field VCChunkSize of VC Caps) */
|
||||||
|
|
||||||
remaining = length - thislength;
|
thislength = MIN(s_remaining(s), vc_chunk_size);
|
||||||
flags = (remaining == 0) ? CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST : CHANNEL_FLAG_FIRST;
|
|
||||||
if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
|
|
||||||
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
|
|
||||||
|
|
||||||
out_uint32_le(s, length);
|
flags = 0;
|
||||||
out_uint32_le(s, flags);
|
if (length == s_remaining(s))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
thislength = MIN(remaining, vc_chunk_size);
|
flags |= CHANNEL_FLAG_FIRST;
|
||||||
remaining -= thislength;
|
}
|
||||||
flags = (remaining == 0) ? CHANNEL_FLAG_LAST : 0;
|
if (s_remaining(s) == thislength)
|
||||||
if (channel->flags & CHANNEL_OPTION_SHOW_PROTOCOL)
|
{
|
||||||
flags |= CHANNEL_FLAG_SHOW_PROTOCOL;
|
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",
|
logger(Protocol, Debug, "channel_send_chunk(), sending %d bytes with flags 0x%x",
|
||||||
thislength, flags);
|
thislength, flags);
|
||||||
|
|
||||||
s = sec_init(g_encryption ? SEC_ENCRYPT : 0, thislength + 8);
|
/* first fragment sent in-place */
|
||||||
out_uint32_le(s, length);
|
inplace = False;
|
||||||
out_uint32_le(s, flags);
|
if ((flags & (CHANNEL_FLAG_FIRST|CHANNEL_FLAG_LAST)) ==
|
||||||
out_uint8p(s, data, thislength);
|
(CHANNEL_FLAG_FIRST|CHANNEL_FLAG_LAST))
|
||||||
s_mark_end(s);
|
{
|
||||||
sec_send_to_channel(s, g_encryption ? SEC_ENCRYPT : 0, channel->mcs_id);
|
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
|
#ifdef WITH_SCARD
|
||||||
@ -150,7 +186,6 @@ void
|
|||||||
channel_process(STREAM s, uint16 mcs_channel)
|
channel_process(STREAM s, uint16 mcs_channel)
|
||||||
{
|
{
|
||||||
uint32 length, flags;
|
uint32 length, flags;
|
||||||
uint32 thislength;
|
|
||||||
VCHANNEL *channel = NULL;
|
VCHANNEL *channel = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
STREAM in;
|
STREAM in;
|
||||||
@ -178,22 +213,16 @@ channel_process(STREAM s, uint16 mcs_channel)
|
|||||||
in = &channel->in;
|
in = &channel->in;
|
||||||
if (flags & CHANNEL_FLAG_FIRST)
|
if (flags & CHANNEL_FLAG_FIRST)
|
||||||
{
|
{
|
||||||
if (length > in->size)
|
s_realloc(in, length);
|
||||||
{
|
s_reset(in);
|
||||||
in->data = (uint8 *) xrealloc(in->data, length);
|
|
||||||
in->size = length;
|
|
||||||
}
|
|
||||||
in->p = in->data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thislength = MIN(s->end - s->p, in->data + in->size - in->p);
|
out_uint8stream(in, s, s_remaining(s));
|
||||||
memcpy(in->p, s->p, thislength);
|
|
||||||
in->p += thislength;
|
|
||||||
|
|
||||||
if (flags & CHANNEL_FLAG_LAST)
|
if (flags & CHANNEL_FLAG_LAST)
|
||||||
{
|
{
|
||||||
in->end = in->p;
|
s_mark_end(in);
|
||||||
in->p = in->data;
|
s_seek(in, 0);
|
||||||
channel->process(in);
|
channel->process(in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
cliprdr.c
12
cliprdr.c
@ -48,10 +48,11 @@ cliprdr_send_packet(uint16 type, uint16 status, uint8 * data, uint32 length)
|
|||||||
out_uint16_le(s, type);
|
out_uint16_le(s, type);
|
||||||
out_uint16_le(s, status);
|
out_uint16_le(s, status);
|
||||||
out_uint32_le(s, length);
|
out_uint32_le(s, length);
|
||||||
out_uint8p(s, data, length);
|
out_uint8a(s, data, length);
|
||||||
out_uint32(s, 0); /* pad? */
|
out_uint32(s, 0); /* pad? */
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
channel_send(s, cliprdr_channel);
|
channel_send(s, cliprdr_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper which announces our readiness to supply clipboard data
|
/* Helper which announces our readiness to supply clipboard data
|
||||||
@ -118,21 +119,14 @@ cliprdr_process(STREAM s)
|
|||||||
uint16 type, status;
|
uint16 type, status;
|
||||||
uint32 length, format;
|
uint32 length, format;
|
||||||
uint8 *data;
|
uint8 *data;
|
||||||
struct stream packet = *s;
|
|
||||||
|
|
||||||
in_uint16_le(s, type);
|
in_uint16_le(s, type);
|
||||||
in_uint16_le(s, status);
|
in_uint16_le(s, status);
|
||||||
in_uint32_le(s, length);
|
in_uint32_le(s, length);
|
||||||
data = s->p;
|
|
||||||
|
|
||||||
logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
|
logger(Clipboard, Debug, "cliprdr_process(), type=%d, status=%d, length=%d", type, status,
|
||||||
length);
|
length);
|
||||||
|
|
||||||
if (!s_check_rem(s, length))
|
|
||||||
{
|
|
||||||
rdp_protocol_error("cliprdr_process(), consume of packet from stream would overrun", &packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == CLIPRDR_ERROR)
|
if (status == CLIPRDR_ERROR)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
@ -160,6 +154,7 @@ cliprdr_process(STREAM s)
|
|||||||
ui_clip_sync();
|
ui_clip_sync();
|
||||||
break;
|
break;
|
||||||
case CLIPRDR_FORMAT_ANNOUNCE:
|
case CLIPRDR_FORMAT_ANNOUNCE:
|
||||||
|
in_uint8p(s, data, length);
|
||||||
ui_clip_format_announce(data, length);
|
ui_clip_format_announce(data, length);
|
||||||
cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
|
cliprdr_send_packet(CLIPRDR_FORMAT_ACK, CLIPRDR_RESPONSE, NULL, 0);
|
||||||
return;
|
return;
|
||||||
@ -170,6 +165,7 @@ cliprdr_process(STREAM s)
|
|||||||
ui_clip_request_data(format);
|
ui_clip_request_data(format);
|
||||||
break;
|
break;
|
||||||
case CLIPRDR_DATA_RESPONSE:
|
case CLIPRDR_DATA_RESPONSE:
|
||||||
|
in_uint8p(s, data, length);
|
||||||
ui_clip_handle_data(data, length);
|
ui_clip_handle_data(data, length);
|
||||||
break;
|
break;
|
||||||
case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */
|
case 7: /* TODO: W2K3 SP1 sends this on connect with a value of 1 */
|
||||||
|
268
cssp.c
268
cssp.c
@ -36,14 +36,9 @@ ber_wrap_hdr_data(int tagval, STREAM in)
|
|||||||
STREAM out;
|
STREAM out;
|
||||||
int size = s_length(in) + 16;
|
int size = s_length(in) + 16;
|
||||||
|
|
||||||
out = xmalloc(sizeof(struct stream));
|
out = s_alloc(size);
|
||||||
memset(out, 0, sizeof(struct stream));
|
|
||||||
out->data = xmalloc(size);
|
|
||||||
out->size = size;
|
|
||||||
out->p = out->data;
|
|
||||||
|
|
||||||
ber_out_header(out, tagval, s_length(in));
|
ber_out_header(out, tagval, s_length(in));
|
||||||
out_uint8p(out, in->data, s_length(in));
|
out_stream(out, in);
|
||||||
s_mark_end(out);
|
s_mark_end(out);
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
@ -144,16 +139,19 @@ cssp_gss_get_service_name(char *server, gss_name_t * name)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RD_BOOL
|
static STREAM
|
||||||
cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
|
cssp_gss_wrap(gss_ctx_id_t ctx, STREAM in)
|
||||||
{
|
{
|
||||||
int conf_state;
|
int conf_state;
|
||||||
OM_uint32 major_status;
|
OM_uint32 major_status;
|
||||||
OM_uint32 minor_status;
|
OM_uint32 minor_status;
|
||||||
gss_buffer_desc inbuf, outbuf;
|
gss_buffer_desc inbuf, outbuf;
|
||||||
|
STREAM out;
|
||||||
|
|
||||||
inbuf.value = in->data;
|
s_seek(in, 0);
|
||||||
inbuf.length = s_length(in);
|
inbuf.length = s_length(in);
|
||||||
|
in_uint8p(in, inbuf.value, s_length(in));
|
||||||
|
s_seek(in, 0);
|
||||||
|
|
||||||
major_status = gss_wrap(&minor_status, ctx, True,
|
major_status = gss_wrap(&minor_status, ctx, True,
|
||||||
GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf);
|
GSS_C_QOP_DEFAULT, &inbuf, &conf_state, &outbuf);
|
||||||
@ -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",
|
cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to encrypt and sign message",
|
||||||
major_status, minor_status);
|
major_status, minor_status);
|
||||||
return False;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!conf_state)
|
if (!conf_state)
|
||||||
{
|
{
|
||||||
logger(Core, Error,
|
logger(Core, Error,
|
||||||
"cssp_gss_wrap(), GSS Confidentiality failed, no encryption of message performed.");
|
"cssp_gss_wrap(), GSS Confidentiality failed, no encryption of message performed.");
|
||||||
return False;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write enc data to out stream
|
// write enc data to out stream
|
||||||
out->data = out->p = xmalloc(outbuf.length);
|
out = s_alloc(outbuf.length);
|
||||||
out->size = outbuf.length;
|
out_uint8a(out, outbuf.value, outbuf.length);
|
||||||
out_uint8p(out, outbuf.value, outbuf.length);
|
|
||||||
s_mark_end(out);
|
s_mark_end(out);
|
||||||
|
s_seek(out, 0);
|
||||||
|
|
||||||
gss_release_buffer(&minor_status, &outbuf);
|
gss_release_buffer(&minor_status, &outbuf);
|
||||||
|
|
||||||
return True;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RD_BOOL
|
static STREAM
|
||||||
cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in, STREAM out)
|
cssp_gss_unwrap(gss_ctx_id_t ctx, STREAM in)
|
||||||
{
|
{
|
||||||
OM_uint32 major_status;
|
OM_uint32 major_status;
|
||||||
OM_uint32 minor_status;
|
OM_uint32 minor_status;
|
||||||
gss_qop_t qop_state;
|
gss_qop_t qop_state;
|
||||||
gss_buffer_desc inbuf, outbuf;
|
gss_buffer_desc inbuf, outbuf;
|
||||||
int conf_state;
|
int conf_state;
|
||||||
|
STREAM out;
|
||||||
|
|
||||||
inbuf.value = in->data;
|
s_seek(in, 0);
|
||||||
inbuf.length = s_length(in);
|
inbuf.length = s_length(in);
|
||||||
|
in_uint8p(in, inbuf.value, s_length(in));
|
||||||
|
s_seek(in, 0);
|
||||||
|
|
||||||
major_status = gss_unwrap(&minor_status, ctx, &inbuf, &outbuf, &conf_state, &qop_state);
|
major_status = gss_unwrap(&minor_status, ctx, &inbuf, &outbuf, &conf_state, &qop_state);
|
||||||
|
|
||||||
@ -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",
|
cssp_gss_report_error(GSS_C_GSS_CODE, "Failed to decrypt message",
|
||||||
major_status, minor_status);
|
major_status, minor_status);
|
||||||
return False;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->data = out->p = xmalloc(outbuf.length);
|
out = s_alloc(outbuf.length);
|
||||||
out->size = outbuf.length;
|
out_uint8a(out, outbuf.value, outbuf.length);
|
||||||
out_uint8p(out, outbuf.value, outbuf.length);
|
|
||||||
s_mark_end(out);
|
s_mark_end(out);
|
||||||
|
s_seek(out, 0);
|
||||||
|
|
||||||
gss_release_buffer(&minor_status, &outbuf);
|
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);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -247,7 +248,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -259,7 +260,7 @@ cssp_encode_tspasswordcreds(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -295,7 +296,7 @@ cssp_encode_tscspdatadetail(unsigned char keyspec, char *card, char *reader, cha
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -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);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -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);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -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);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -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);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -387,7 +388,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -397,7 +398,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
|
|||||||
g_sc_container_name, g_sc_csp_name);
|
g_sc_container_name, g_sc_csp_name);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -411,7 +412,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -426,7 +427,7 @@ cssp_encode_tssmartcardcreds(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -467,7 +468,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -485,7 +486,7 @@ cssp_encode_tscredentials(char *username, char *password, char *domain)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3);
|
h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h3);
|
s_free(h3);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
@ -521,7 +522,7 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
|
|||||||
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -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);
|
h2 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, h3);
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2);
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h5);
|
s_free(h5);
|
||||||
s_free(h4);
|
s_free(h4);
|
||||||
@ -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);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2);
|
||||||
|
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
|
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
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);
|
h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2);
|
||||||
|
|
||||||
s_realloc(&message, s_length(&message) + s_length(h1));
|
s_realloc(&message, s_length(&message) + s_length(h1));
|
||||||
out_uint8p(&message, h1->data, s_length(h1));
|
out_stream(&message, h1);
|
||||||
s_mark_end(&message);
|
s_mark_end(&message);
|
||||||
s_free(h2);
|
s_free(h2);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
@ -575,11 +576,12 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
|
|||||||
// Todo: can h1 be send directly instead of tcp_init() approach
|
// Todo: can h1 be send directly instead of tcp_init() approach
|
||||||
h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
|
h1 = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message);
|
||||||
s = tcp_init(s_length(h1));
|
s = tcp_init(s_length(h1));
|
||||||
out_uint8p(s, h1->data, s_length(h1));
|
out_stream(s, h1);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
s_free(h1);
|
s_free(h1);
|
||||||
|
|
||||||
tcp_send(s);
|
tcp_send(s);
|
||||||
|
s_free(s);
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
xfree(message.data);
|
xfree(message.data);
|
||||||
@ -589,10 +591,10 @@ cssp_send_tsrequest(STREAM token, STREAM auth, STREAM pubkey)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RD_BOOL
|
STREAM
|
||||||
cssp_read_tsrequest(STREAM token, STREAM pubkey)
|
cssp_read_tsrequest(RD_BOOL pubkey)
|
||||||
{
|
{
|
||||||
STREAM s;
|
STREAM s, out;
|
||||||
int length;
|
int length;
|
||||||
int tagval;
|
int tagval;
|
||||||
struct stream packet;
|
struct stream packet;
|
||||||
@ -600,96 +602,83 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
|
|||||||
s = tcp_recv(NULL, 4);
|
s = tcp_recv(NULL, 4);
|
||||||
|
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
return False;
|
return NULL;
|
||||||
|
|
||||||
// verify ASN.1 header
|
// get and verify the header
|
||||||
if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
if (!ber_in_header(s, &tagval, &length) ||
|
||||||
{
|
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
||||||
logger(Protocol, Error,
|
return NULL;
|
||||||
"cssp_read_tsrequest(), expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x",
|
|
||||||
s->p[0]);
|
|
||||||
return False;
|
|
||||||
}
|
|
||||||
|
|
||||||
// peek at first 4 bytes to get full message length
|
// We've already read 4 bytes, but the header might have been
|
||||||
if (s->p[1] < 0x80)
|
// less than that, so we need to adjust the length
|
||||||
length = s->p[1] - 2;
|
length -= s_remaining(s);
|
||||||
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;
|
|
||||||
|
|
||||||
// receive the remainings of message
|
// receive the remainings of message
|
||||||
s = tcp_recv(s, length);
|
s = tcp_recv(s, length);
|
||||||
|
if (s == NULL)
|
||||||
|
return NULL;
|
||||||
packet = *s;
|
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]
|
// version [0]
|
||||||
if (!ber_in_header(s, &tagval, &length) ||
|
if (!ber_in_header(s, &tagval, &length) ||
|
||||||
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
|
tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
|
||||||
return False;
|
return NULL;
|
||||||
|
|
||||||
if (!s_check_rem(s, length))
|
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);
|
&packet);
|
||||||
}
|
}
|
||||||
in_uint8s(s, length);
|
in_uint8s(s, length);
|
||||||
|
|
||||||
// negoToken [1]
|
// negoToken [1]
|
||||||
if (token)
|
if (!pubkey)
|
||||||
{
|
{
|
||||||
if (!ber_in_header(s, &tagval, &length)
|
if (!ber_in_header(s, &tagval, &length)
|
||||||
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1))
|
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1))
|
||||||
return False;
|
return NULL;
|
||||||
if (!ber_in_header(s, &tagval, &length)
|
if (!ber_in_header(s, &tagval, &length)
|
||||||
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
||||||
return False;
|
return NULL;
|
||||||
if (!ber_in_header(s, &tagval, &length)
|
if (!ber_in_header(s, &tagval, &length)
|
||||||
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
|| tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
|
||||||
return False;
|
return NULL;
|
||||||
if (!ber_in_header(s, &tagval, &length)
|
if (!ber_in_header(s, &tagval, &length)
|
||||||
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
|
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0))
|
||||||
return False;
|
return NULL;
|
||||||
|
|
||||||
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
|
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
|
||||||
return False;
|
return NULL;
|
||||||
|
|
||||||
if (!s_check_rem(s, length))
|
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);
|
&packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_realloc(token, length);
|
out = s_alloc(length);
|
||||||
s_reset(token);
|
out_uint8stream(out, s, length);
|
||||||
out_uint8p(token, s->p, length);
|
s_mark_end(out);
|
||||||
s_mark_end(token);
|
s_seek(out, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pubKey [3]
|
// pubKey [3]
|
||||||
if (pubkey)
|
else
|
||||||
{
|
{
|
||||||
if (!ber_in_header(s, &tagval, &length)
|
if (!ber_in_header(s, &tagval, &length)
|
||||||
|| tagval != (BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3))
|
|| 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)
|
if (!ber_in_header(s, &tagval, &length) || tagval != BER_TAG_OCTET_STRING)
|
||||||
return False;
|
return NULL;
|
||||||
|
|
||||||
pubkey->data = pubkey->p = s->p;
|
out = s_alloc(length);
|
||||||
pubkey->end = pubkey->data + length;
|
out_uint8stream(out, s, length);
|
||||||
pubkey->size = length;
|
s_mark_end(out);
|
||||||
|
s_seek(out, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return True;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
RD_BOOL
|
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;
|
gss_OID desired_mech = &_gss_spnego_krb5_mechanism_oid_desc;
|
||||||
|
|
||||||
STREAM ts_creds;
|
STREAM ts_creds;
|
||||||
struct stream token = { 0 };
|
STREAM token;
|
||||||
struct stream pubkey = { 0 };
|
STREAM pubkey, pubkey_cmp;
|
||||||
struct stream pubkey_cmp = { 0 };
|
unsigned char *pubkey_data;
|
||||||
|
unsigned char *pubkey_cmp_data;
|
||||||
|
unsigned char first_byte;
|
||||||
|
|
||||||
|
RD_BOOL ret;
|
||||||
|
STREAM blob;
|
||||||
|
|
||||||
// Verify that system gss support spnego
|
// Verify that system gss support spnego
|
||||||
if (!cssp_gss_mech_available(desired_mech))
|
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;
|
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
|
// Enter the spnego loop
|
||||||
OM_uint32 actual_services;
|
OM_uint32 actual_services;
|
||||||
gss_OID actual_mech;
|
gss_OID actual_mech;
|
||||||
struct stream blob = { 0 };
|
|
||||||
|
|
||||||
gss_ctx = GSS_C_NO_CONTEXT;
|
gss_ctx = GSS_C_NO_CONTEXT;
|
||||||
cred = GSS_C_NO_CREDENTIAL;
|
cred = GSS_C_NO_CREDENTIAL;
|
||||||
|
|
||||||
|
token = NULL;
|
||||||
input_tok.length = 0;
|
input_tok.length = 0;
|
||||||
output_tok.length = 0;
|
output_tok.length = 0;
|
||||||
minor_status = 0;
|
minor_status = 0;
|
||||||
@ -762,6 +759,11 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
|
|||||||
&actual_mech,
|
&actual_mech,
|
||||||
&output_tok, &actual_services, &actual_time);
|
&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 (GSS_ERROR(major_status))
|
||||||
{
|
{
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@ -786,39 +788,44 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
|
|||||||
// Send token to server
|
// Send token to server
|
||||||
if (output_tok.length != 0)
|
if (output_tok.length != 0)
|
||||||
{
|
{
|
||||||
if (output_tok.length > token.size)
|
token = s_alloc(output_tok.length);
|
||||||
s_realloc(&token, output_tok.length);
|
out_uint8a(token, output_tok.value, output_tok.length);
|
||||||
s_reset(&token);
|
s_mark_end(token);
|
||||||
|
|
||||||
out_uint8p(&token, output_tok.value, output_tok.length);
|
ret = cssp_send_tsrequest(token, NULL, NULL);
|
||||||
s_mark_end(&token);
|
|
||||||
|
|
||||||
if (!cssp_send_tsrequest(&token, NULL, NULL))
|
|
||||||
goto bail_out;
|
|
||||||
|
|
||||||
|
s_free(token);
|
||||||
|
token = NULL;
|
||||||
(void) gss_release_buffer(&minor_status, &output_tok);
|
(void) gss_release_buffer(&minor_status, &output_tok);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
goto bail_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read token from server
|
// Read token from server
|
||||||
if (major_status & GSS_S_CONTINUE_NEEDED)
|
if (major_status & GSS_S_CONTINUE_NEEDED)
|
||||||
{
|
{
|
||||||
(void) gss_release_buffer(&minor_status, &input_tok);
|
token = cssp_read_tsrequest(False);
|
||||||
|
if (token == NULL)
|
||||||
if (!cssp_read_tsrequest(&token, NULL))
|
|
||||||
goto bail_out;
|
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
|
else
|
||||||
{
|
{
|
||||||
// Send encrypted pubkey for verification to server
|
// Send encrypted pubkey for verification to server
|
||||||
context_established = 1;
|
context_established = 1;
|
||||||
|
|
||||||
if (!cssp_gss_wrap(gss_ctx, &pubkey, &blob))
|
blob = cssp_gss_wrap(gss_ctx, pubkey);
|
||||||
|
if (blob == NULL)
|
||||||
goto bail_out;
|
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;
|
goto bail_out;
|
||||||
|
|
||||||
context_established = 1;
|
context_established = 1;
|
||||||
@ -829,37 +836,62 @@ cssp_connect(char *server, char *user, char *domain, char *password, STREAM s)
|
|||||||
}
|
}
|
||||||
while (!context_established);
|
while (!context_established);
|
||||||
|
|
||||||
|
s_free(token);
|
||||||
|
|
||||||
// read tsrequest response and decrypt for public key validation
|
// 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;
|
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;
|
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
|
// 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,
|
logger(Core, Error,
|
||||||
"cssp_connect(), public key mismatch, cannot guarantee integrity of server connection");
|
"cssp_connect(), public key mismatch, cannot guarantee integrity of server connection");
|
||||||
goto bail_out;
|
goto bail_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_free(pubkey);
|
||||||
|
s_free(pubkey_cmp);
|
||||||
|
|
||||||
// Send TSCredentials
|
// Send TSCredentials
|
||||||
ts_creds = cssp_encode_tscredentials(user, password, domain);
|
ts_creds = cssp_encode_tscredentials(user, password, domain);
|
||||||
|
|
||||||
if (!cssp_gss_wrap(gss_ctx, ts_creds, &blob))
|
blob = cssp_gss_wrap(gss_ctx, ts_creds);
|
||||||
goto bail_out;
|
|
||||||
|
|
||||||
s_free(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;
|
goto bail_out;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
|
|
||||||
bail_out:
|
bail_out:
|
||||||
xfree(token.data);
|
s_free(token);
|
||||||
|
s_free(pubkey);
|
||||||
|
s_free(pubkey_cmp);
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
57
disk.c
57
disk.c
@ -1131,10 +1131,7 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
|
|||||||
struct STATFS_T stat_fs;
|
struct STATFS_T stat_fs;
|
||||||
struct fileinfo *pfinfo;
|
struct fileinfo *pfinfo;
|
||||||
FsInfoType *fsinfo;
|
FsInfoType *fsinfo;
|
||||||
struct stream stmp;
|
STREAM stmp;
|
||||||
|
|
||||||
memset(&stmp, 0, sizeof(stmp));
|
|
||||||
s_realloc(&stmp, PATH_MAX * 4);
|
|
||||||
|
|
||||||
logger(Disk, Debug, "disk_query_volume_information(handle=0x%x, info_class=0x%x)", handle,
|
logger(Disk, Debug, "disk_query_volume_information(handle=0x%x, info_class=0x%x)", handle,
|
||||||
info_class);
|
info_class);
|
||||||
@ -1153,16 +1150,17 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
|
|||||||
switch (info_class)
|
switch (info_class)
|
||||||
{
|
{
|
||||||
case FileFsVolumeInformation:
|
case FileFsVolumeInformation:
|
||||||
s_reset(&stmp);
|
stmp = s_alloc(PATH_MAX * 4);
|
||||||
out_utf16s(&stmp, fsinfo->label);
|
out_utf16s(stmp, fsinfo->label);
|
||||||
s_mark_end(&stmp);
|
s_mark_end(stmp);
|
||||||
|
|
||||||
out_uint32_le(out, 0); /* volume creation time low */
|
out_uint32_le(out, 0); /* volume creation time low */
|
||||||
out_uint32_le(out, 0); /* volume creation time high */
|
out_uint32_le(out, 0); /* volume creation time high */
|
||||||
out_uint32_le(out, fsinfo->serial); /* serial */
|
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_uint8(out, 0); /* support objects? */
|
||||||
out_stream(out, &stmp); /* fsinfo->label string */
|
out_stream(out, stmp); /* fsinfo->label string */
|
||||||
|
s_free(stmp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsSizeInformation:
|
case FileFsSizeInformation:
|
||||||
@ -1183,15 +1181,16 @@ disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsAttributeInformation:
|
case FileFsAttributeInformation:
|
||||||
s_reset(&stmp);
|
stmp = s_alloc(PATH_MAX * 4);
|
||||||
out_utf16s_no_eos(&stmp, fsinfo->type);
|
out_utf16s_no_eos(stmp, fsinfo->type);
|
||||||
s_mark_end(&stmp);
|
s_mark_end(stmp);
|
||||||
|
|
||||||
out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
|
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, F_NAMELEN(stat_fs)); /* max length of filename */
|
||||||
|
|
||||||
out_uint32_le(out, s_length(&stmp)); /* length of fsinfo->type string */
|
out_uint32_le(out, s_length(stmp)); /* length of fsinfo->type string */
|
||||||
out_stream(out, &stmp); /* fsinfo->typ string */
|
out_stream(out, stmp); /* fsinfo->typ string */
|
||||||
|
s_free(stmp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileFsLabelInformation:
|
case FileFsLabelInformation:
|
||||||
@ -1218,7 +1217,7 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
|
|||||||
struct dirent *pdirent;
|
struct dirent *pdirent;
|
||||||
struct stat filestat;
|
struct stat filestat;
|
||||||
struct fileinfo *pfinfo;
|
struct fileinfo *pfinfo;
|
||||||
struct stream stmp;
|
STREAM stmp;
|
||||||
|
|
||||||
logger(Disk, Debug, "disk_query_directory(handle=0x%x, info_class=0x%x, pattern=%s, ...)",
|
logger(Disk, Debug, "disk_query_directory(handle=0x%x, info_class=0x%x, pattern=%s, ...)",
|
||||||
handle, info_class, pattern);
|
handle, info_class, pattern);
|
||||||
@ -1228,9 +1227,6 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
|
|||||||
dirname = pfinfo->path;
|
dirname = pfinfo->path;
|
||||||
file_attributes = 0;
|
file_attributes = 0;
|
||||||
|
|
||||||
memset(&stmp, 0, sizeof(stmp));
|
|
||||||
s_realloc(&stmp, PATH_MAX * 4);
|
|
||||||
|
|
||||||
switch (info_class)
|
switch (info_class)
|
||||||
{
|
{
|
||||||
case FileBothDirectoryInformation:
|
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
|
// Write entry name as utf16 into stmp
|
||||||
s_reset(&stmp);
|
stmp = s_alloc(PATH_MAX * 4);
|
||||||
out_utf16s_no_eos(&stmp, pdirent->d_name);
|
out_utf16s_no_eos(stmp, pdirent->d_name);
|
||||||
s_mark_end(&stmp);
|
s_mark_end(stmp);
|
||||||
|
|
||||||
switch (info_class)
|
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_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, 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_uint32_le(out, 0); /* EaSize */
|
||||||
out_uint8(out, 0); /* ShortNameLength */
|
out_uint8(out, 0); /* ShortNameLength */
|
||||||
out_uint8s(out, 24); /* ShortName (8.3 name) */
|
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;
|
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_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, 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_stream(out, &stmp); /* dir entry name */
|
out_stream(out, stmp); /* dir entry name */
|
||||||
break;
|
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_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, 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_uint32_le(out, 0); /* EaSize */
|
||||||
out_stream(out, &stmp); /* dir entry name */
|
out_stream(out, stmp); /* dir entry name */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case FileNamesInformation:
|
case FileNamesInformation:
|
||||||
|
|
||||||
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_stream(out, &stmp); /* dir entry name */
|
out_stream(out, stmp); /* dir entry name */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
@ -1401,9 +1397,12 @@ disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREA
|
|||||||
logger(Disk, Warning,
|
logger(Disk, Warning,
|
||||||
"disk_query_directory(), unhandled directory info class 0x%x",
|
"disk_query_directory(), unhandled directory info class 0x%x",
|
||||||
info_class);
|
info_class);
|
||||||
|
s_free(stmp);
|
||||||
return RD_STATUS_INVALID_PARAMETER;
|
return RD_STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_free(stmp);
|
||||||
|
|
||||||
return RD_STATUS_SUCCESS;
|
return RD_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
dvc.c
3
dvc.c
@ -268,6 +268,7 @@ dvc_send(const char *name, STREAM s)
|
|||||||
s_mark_end(ls);
|
s_mark_end(ls);
|
||||||
|
|
||||||
channel_send(ls, dvc_channel);
|
channel_send(ls, dvc_channel);
|
||||||
|
s_free(ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -292,6 +293,7 @@ dvc_send_capabilities_response()
|
|||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
|
|
||||||
channel_send(s, dvc_channel);
|
channel_send(s, dvc_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -320,6 +322,7 @@ dvc_send_create_response(RD_BOOL success, dvc_hdr_t hdr, uint32 channelid)
|
|||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
|
|
||||||
channel_send(s, dvc_channel);
|
channel_send(s, dvc_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
8
iso.c
8
iso.c
@ -55,6 +55,7 @@ iso_send_msg(uint8 code)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
tcp_send(s);
|
tcp_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -78,8 +79,8 @@ iso_send_connection_request(char *username, uint32 neg_proto)
|
|||||||
out_uint16(s, 0); /* src_ref */
|
out_uint16(s, 0); /* src_ref */
|
||||||
out_uint8(s, 0); /* class */
|
out_uint8(s, 0); /* class */
|
||||||
|
|
||||||
out_uint8p(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
|
out_uint8a(s, "Cookie: mstshash=", strlen("Cookie: mstshash="));
|
||||||
out_uint8p(s, username, strlen(username));
|
out_uint8a(s, username, strlen(username));
|
||||||
|
|
||||||
out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
|
out_uint8(s, 0x0d); /* cookie termination string: CR+LF */
|
||||||
out_uint8(s, 0x0a);
|
out_uint8(s, 0x0a);
|
||||||
@ -95,6 +96,7 @@ iso_send_connection_request(char *username, uint32 neg_proto)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
tcp_send(s);
|
tcp_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive a message on the ISO layer, return code */
|
/* Receive a message on the ISO layer, return code */
|
||||||
@ -177,7 +179,7 @@ iso_send(STREAM s)
|
|||||||
uint16 length;
|
uint16 length;
|
||||||
|
|
||||||
s_pop_layer(s, iso_hdr);
|
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, T123_HEADER_VERSION); /* version */
|
||||||
out_uint8(s, 0); /* reserved */
|
out_uint8(s, 0); /* reserved */
|
||||||
|
37
licence.c
37
licence.c
@ -79,24 +79,25 @@ licence_info(uint8 * client_random, uint8 * rsa_data,
|
|||||||
out_uint16(s, 0);
|
out_uint16(s, 0);
|
||||||
out_uint16_le(s, 0x0201);
|
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, 2);
|
||||||
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
|
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_uint8s(s, SEC_PADDING_SIZE);
|
||||||
|
|
||||||
out_uint16_le(s, 1);
|
out_uint16_le(s, 1);
|
||||||
out_uint16_le(s, licence_size);
|
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, 1);
|
||||||
out_uint16_le(s, LICENCE_HWID_SIZE);
|
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);
|
s_mark_end(s);
|
||||||
sec_send(s, sec_flags);
|
sec_send(s, sec_flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a new licence request packet */
|
/* 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(s, 0);
|
||||||
out_uint16_le(s, 0xff01);
|
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, 2);
|
||||||
out_uint16_le(s, (SEC_MODULUS_SIZE + SEC_PADDING_SIZE));
|
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_uint8s(s, SEC_PADDING_SIZE);
|
||||||
|
|
||||||
/* Username LICENSE_BINARY_BLOB */
|
/* Username LICENSE_BINARY_BLOB */
|
||||||
out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB);
|
out_uint16_le(s, BB_CLIENT_USER_NAME_BLOB);
|
||||||
out_uint16_le(s, userlen);
|
out_uint16_le(s, userlen);
|
||||||
out_uint8p(s, user, userlen);
|
out_uint8a(s, user, userlen);
|
||||||
|
|
||||||
/* Machinename LICENSE_BINARY_BLOB */
|
/* Machinename LICENSE_BINARY_BLOB */
|
||||||
out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB);
|
out_uint16_le(s, BB_CLIENT_MACHINE_NAME_BLOB);
|
||||||
out_uint16_le(s, hostlen);
|
out_uint16_le(s, hostlen);
|
||||||
out_uint8p(s, host, hostlen);
|
out_uint8a(s, host, hostlen);
|
||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
sec_send(s, sec_flags);
|
sec_send(s, sec_flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process a licence request packet */
|
/* 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, 1);
|
||||||
out_uint16_le(s, LICENCE_TOKEN_SIZE);
|
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, 1);
|
||||||
out_uint16_le(s, LICENCE_HWID_SIZE);
|
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);
|
s_mark_end(s);
|
||||||
sec_send(s, sec_flags);
|
sec_send(s, sec_flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse an platform challenge request packet */
|
/* Parse an platform challenge request packet */
|
||||||
@ -274,6 +277,7 @@ licence_process_platform_challenge(STREAM s)
|
|||||||
static void
|
static void
|
||||||
licence_process_new_license(STREAM s)
|
licence_process_new_license(STREAM s)
|
||||||
{
|
{
|
||||||
|
unsigned char *data;
|
||||||
RDSSL_RC4 crypt_key;
|
RDSSL_RC4 crypt_key;
|
||||||
uint32 length;
|
uint32 length;
|
||||||
int i;
|
int i;
|
||||||
@ -283,8 +287,12 @@ licence_process_new_license(STREAM s)
|
|||||||
if (!s_check_rem(s, length))
|
if (!s_check_rem(s, length))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
inout_uint8p(s, data, length);
|
||||||
|
|
||||||
rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
|
rdssl_rc4_set_key(&crypt_key, g_licence_key, 16);
|
||||||
rdssl_rc4_crypt(&crypt_key, s->p, s->p, length);
|
rdssl_rc4_crypt(&crypt_key, data, data, length);
|
||||||
|
|
||||||
|
s_seek(s, s_tell(s) - length);
|
||||||
|
|
||||||
/* Parse NEW_LICENSE_INFO block */
|
/* Parse NEW_LICENSE_INFO block */
|
||||||
in_uint8s(s, 4); // skip dwVersion
|
in_uint8s(s, 4); // skip dwVersion
|
||||||
@ -301,7 +309,8 @@ licence_process_new_license(STREAM s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_licence_issued = True;
|
g_licence_issued = True;
|
||||||
save_licence(s->p, length);
|
in_uint8p(s, data, length);
|
||||||
|
save_licence(data, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* process a licence error alert packet */
|
/* process a licence error alert packet */
|
||||||
|
14
lspci.c
14
lspci.c
@ -135,17 +135,12 @@ lspci_process(STREAM s)
|
|||||||
unsigned int pkglen;
|
unsigned int pkglen;
|
||||||
static char *rest = NULL;
|
static char *rest = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
struct stream packet = *s;
|
|
||||||
|
|
||||||
if (!s_check(s))
|
pkglen = s_remaining(s);
|
||||||
{
|
|
||||||
rdp_protocol_error("lspci_process(), stream is in unstable state", &packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
pkglen = s->end - s->p;
|
|
||||||
/* str_handle_lines requires null terminated strings */
|
/* str_handle_lines requires null terminated strings */
|
||||||
buf = xmalloc(pkglen + 1);
|
buf = xmalloc(pkglen + 1);
|
||||||
STRNCPY(buf, (char *) s->p, pkglen + 1);
|
in_uint8a(s, buf, pkglen);
|
||||||
|
buf[pkglen] = '\0';
|
||||||
str_handle_lines(buf, &rest, lspci_process_line, NULL);
|
str_handle_lines(buf, &rest, lspci_process_line, NULL);
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
}
|
}
|
||||||
@ -169,6 +164,7 @@ lspci_send(const char *output)
|
|||||||
|
|
||||||
len = strlen(output);
|
len = strlen(output);
|
||||||
s = channel_init(lspci_channel, len);
|
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);
|
channel_send(s, lspci_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
31
mcs.c
31
mcs.c
@ -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) */
|
/* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
|
||||||
static RD_BOOL
|
static void
|
||||||
mcs_parse_domain_params(STREAM s)
|
mcs_parse_domain_params(STREAM s)
|
||||||
{
|
{
|
||||||
uint32 length;
|
uint32 length;
|
||||||
@ -52,19 +52,17 @@ mcs_parse_domain_params(STREAM s)
|
|||||||
|
|
||||||
if (!s_check_rem(s, length))
|
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);
|
in_uint8s(s, length);
|
||||||
|
|
||||||
return s_check(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
|
/* Send an MCS_CONNECT_INITIAL message (ASN.1 BER) */
|
||||||
static void
|
static void
|
||||||
mcs_send_connect_initial(STREAM mcs_data)
|
mcs_send_connect_initial(STREAM mcs_data)
|
||||||
{
|
{
|
||||||
int datalen = mcs_data->end - mcs_data->data;
|
int datalen = s_length(mcs_data);
|
||||||
int length = 9 + 3 * 34 + 4 + datalen;
|
int length = 9 + 3 * 34 + 4 + datalen;
|
||||||
STREAM s;
|
STREAM s;
|
||||||
logger(Protocol, Debug, "%s()", __func__);
|
logger(Protocol, Debug, "%s()", __func__);
|
||||||
@ -84,10 +82,11 @@ mcs_send_connect_initial(STREAM mcs_data)
|
|||||||
mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
|
mcs_out_domain_params(s, 0xffff, 0xfc17, 0xffff, 0xffff); /* max params */
|
||||||
|
|
||||||
ber_out_header(s, BER_TAG_OCTET_STRING, datalen);
|
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);
|
s_mark_end(s);
|
||||||
iso_send(s);
|
iso_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expect a MCS_CONNECT_RESPONSE message (ASN.1 BER) */
|
/* 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))
|
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);
|
mcs_parse_domain_params(s);
|
||||||
@ -140,9 +139,10 @@ mcs_recv_connect_response(STREAM mcs_data)
|
|||||||
length = mcs_data->size;
|
length = mcs_data->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_uint8a(s, mcs_data->data, length);
|
s_reset(mcs_data);
|
||||||
mcs_data->p = mcs_data->data;
|
in_uint8stream(s, mcs_data, length);
|
||||||
mcs_data->end = mcs_data->data + length;
|
s_mark_end(mcs_data);
|
||||||
|
s_seek(mcs_data, 0);
|
||||||
*/
|
*/
|
||||||
return s_check_end(s);
|
return s_check_end(s);
|
||||||
}
|
}
|
||||||
@ -161,6 +161,7 @@ mcs_send_edrq(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
iso_send(s);
|
iso_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send an AUrq message (ASN.1 PER) */
|
/* Send an AUrq message (ASN.1 PER) */
|
||||||
@ -175,6 +176,7 @@ mcs_send_aurq(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
iso_send(s);
|
iso_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expect a AUcf message (ASN.1 PER) */
|
/* Expect a AUcf message (ASN.1 PER) */
|
||||||
@ -228,6 +230,7 @@ mcs_send_cjrq(uint16 chanid)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
iso_send(s);
|
iso_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Expect a CJcf message (ASN.1 PER) */
|
/* 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);
|
logger(Protocol, Debug, "mcs_send_dpu(), reason=%d", reason);
|
||||||
|
|
||||||
contents = malloc(sizeof(struct stream));
|
contents = s_alloc(6);
|
||||||
memset(contents, 0, sizeof(struct stream));
|
|
||||||
s_realloc(contents, 6);
|
|
||||||
s_reset(contents);
|
|
||||||
ber_out_integer(contents, reason); /* Reason */
|
ber_out_integer(contents, reason); /* Reason */
|
||||||
ber_out_sequence(contents, NULL); /* SEQUENCE OF NonStandradParameters OPTIONAL */
|
ber_out_sequence(contents, NULL); /* SEQUENCE OF NonStandradParameters OPTIONAL */
|
||||||
s_mark_end(contents);
|
s_mark_end(contents);
|
||||||
@ -290,6 +290,7 @@ mcs_send_dpu(unsigned short reason)
|
|||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
|
|
||||||
iso_send(s);
|
iso_send(s);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialise an MCS transport data packet */
|
/* Initialise an MCS transport data packet */
|
||||||
@ -311,7 +312,7 @@ mcs_send_to_channel(STREAM s, uint16 channel)
|
|||||||
uint16 length;
|
uint16 length;
|
||||||
|
|
||||||
s_pop_layer(s, mcs_hdr);
|
s_pop_layer(s, mcs_hdr);
|
||||||
length = s->end - s->p - 8;
|
length = s_remaining(s) - 8;
|
||||||
length |= 0x8000;
|
length |= 0x8000;
|
||||||
|
|
||||||
out_uint8(s, (MCS_SDRQ << 2));
|
out_uint8(s, (MCS_SDRQ << 2));
|
||||||
|
26
orders.c
26
orders.c
@ -20,7 +20,7 @@
|
|||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
#include "orders.h"
|
#include "orders.h"
|
||||||
|
|
||||||
extern uint8 *g_next_packet;
|
extern size_t g_next_packet;
|
||||||
static RDP_ORDER_STATE g_order_state;
|
static RDP_ORDER_STATE g_order_state;
|
||||||
extern RDP_VERSION g_rdp_version;
|
extern RDP_VERSION g_rdp_version;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ rdp_in_colour(STREAM s, uint32 * colour)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse bounds information */
|
/* Parse bounds information */
|
||||||
static RD_BOOL
|
static void
|
||||||
rdp_parse_bounds(STREAM s, BOUNDS * bounds)
|
rdp_parse_bounds(STREAM s, BOUNDS * bounds)
|
||||||
{
|
{
|
||||||
uint8 present;
|
uint8 present;
|
||||||
@ -127,12 +127,10 @@ rdp_parse_bounds(STREAM s, BOUNDS * bounds)
|
|||||||
rdp_in_coord(s, &bounds->bottom, False);
|
rdp_in_coord(s, &bounds->bottom, False);
|
||||||
else if (present & 128)
|
else if (present & 128)
|
||||||
rdp_in_coord(s, &bounds->bottom, True);
|
rdp_in_coord(s, &bounds->bottom, True);
|
||||||
|
|
||||||
return s_check(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a pen */
|
/* Parse a pen */
|
||||||
static RD_BOOL
|
static void
|
||||||
rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
|
rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
|
||||||
{
|
{
|
||||||
if (present & 1)
|
if (present & 1)
|
||||||
@ -143,8 +141,6 @@ rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
|
|||||||
|
|
||||||
if (present & 4)
|
if (present & 4)
|
||||||
rdp_in_colour(s, &pen->colour);
|
rdp_in_colour(s, &pen->colour);
|
||||||
|
|
||||||
return s_check(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -176,7 +172,7 @@ setup_brush(BRUSH * out_brush, BRUSH * in_brush)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a brush */
|
/* Parse a brush */
|
||||||
static RD_BOOL
|
static void
|
||||||
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
|
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
|
||||||
{
|
{
|
||||||
if (present & 1)
|
if (present & 1)
|
||||||
@ -193,8 +189,6 @@ rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
|
|||||||
|
|
||||||
if (present & 16)
|
if (present & 16)
|
||||||
in_uint8a(s, &brush->pattern[1], 7);
|
in_uint8a(s, &brush->pattern[1], 7);
|
||||||
|
|
||||||
return s_check(s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process a destination blt order */
|
/* Process a destination blt order */
|
||||||
@ -1258,7 +1252,7 @@ process_secondary_order(STREAM s)
|
|||||||
sint16 length;
|
sint16 length;
|
||||||
uint16 flags;
|
uint16 flags;
|
||||||
uint8 type;
|
uint8 type;
|
||||||
uint8 *next_order;
|
size_t next_order;
|
||||||
struct stream packet = *s;
|
struct stream packet = *s;
|
||||||
|
|
||||||
in_uint16_le(s, length);
|
in_uint16_le(s, length);
|
||||||
@ -1272,10 +1266,10 @@ process_secondary_order(STREAM s)
|
|||||||
|
|
||||||
if (!s_check_rem(s, length))
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -1312,7 +1306,7 @@ process_secondary_order(STREAM s)
|
|||||||
"process_secondary_order(), unhandled secondary order %d", type);
|
"process_secondary_order(), unhandled secondary order %d", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p = next_order;
|
s_seek(s, next_order);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process an order PDU */
|
/* Process an order PDU */
|
||||||
@ -1454,9 +1448,9 @@ process_orders(STREAM s, uint16 num_orders)
|
|||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
/* not true when RDP_COMPRESSION is set */
|
/* not true when RDP_COMPRESSION is set */
|
||||||
if (s->p != g_next_packet)
|
if (s_tell(s) != g_next_packet)
|
||||||
logger(Graphics, Error, "process_orders(), %d bytes remaining",
|
logger(Graphics, Error, "process_orders(), %d bytes remaining",
|
||||||
(int) (g_next_packet - s->p));
|
(int) (g_next_packet - s_tell(s)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,8 @@ printercache_process(STREAM s)
|
|||||||
{
|
{
|
||||||
uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
|
uint32 type, printer_length, driver_length, printer_unicode_length, blob_length;
|
||||||
char device_name[9], *printer, *driver;
|
char device_name[9], *printer, *driver;
|
||||||
|
size_t blob_start;
|
||||||
|
unsigned char *blob;
|
||||||
|
|
||||||
printer = driver = NULL;
|
printer = driver = NULL;
|
||||||
|
|
||||||
@ -279,8 +281,10 @@ printercache_process(STREAM s)
|
|||||||
{
|
{
|
||||||
rdp_in_unistr(s, printer_unicode_length, &printer,
|
rdp_in_unistr(s, printer_unicode_length, &printer,
|
||||||
&printer_unicode_length);
|
&printer_unicode_length);
|
||||||
if (printer)
|
if (printer) {
|
||||||
printercache_save_blob(printer, s->p, blob_length);
|
in_uint8p(s, blob, blob_length);
|
||||||
|
printercache_save_blob(printer, blob, blob_length);
|
||||||
|
}
|
||||||
free(printer);
|
free(printer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -289,6 +293,7 @@ printercache_process(STREAM s)
|
|||||||
in_uint8a(s, device_name, 5); /* get LPTx/COMx name */
|
in_uint8a(s, device_name, 5); /* get LPTx/COMx name */
|
||||||
|
|
||||||
/* need to fetch this data so that we can get the length of the packet to store. */
|
/* need to fetch this data so that we can get the length of the packet to store. */
|
||||||
|
blob_start = s_tell(s);
|
||||||
in_uint8s(s, 0x2); /* ??? */
|
in_uint8s(s, 0x2); /* ??? */
|
||||||
in_uint8s(s, 0x2) /* pad?? */
|
in_uint8s(s, 0x2) /* pad?? */
|
||||||
in_uint32_be(s, driver_length);
|
in_uint32_be(s, driver_length);
|
||||||
@ -302,10 +307,11 @@ printercache_process(STREAM s)
|
|||||||
/* rewind stream so that we can save this blob */
|
/* rewind stream so that we can save this blob */
|
||||||
/* length is driver_length + printer_length + 19 */
|
/* length is driver_length + printer_length + 19 */
|
||||||
/* rewind stream */
|
/* rewind stream */
|
||||||
s->p = s->p - 19;
|
s_seek(s, blob_start);
|
||||||
|
|
||||||
printercache_save_blob(device_name, s->p,
|
blob_length = driver_length + printer_length + 19;
|
||||||
driver_length + printer_length + 19);
|
in_uint8p(s, blob, blob_length);
|
||||||
|
printercache_save_blob(device_name, blob, blob_length);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger(Protocol, Warning,
|
logger(Protocol, Warning,
|
||||||
|
11
proto.h
11
proto.h
@ -25,6 +25,11 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
#define UNUSED(param) ((void)param)
|
#define UNUSED(param) ((void)param)
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define NORETURN __attribute__((noreturn))
|
||||||
|
#else
|
||||||
|
# define NORETURN
|
||||||
|
#endif // __GNUC__
|
||||||
/* bitmap.c */
|
/* bitmap.c */
|
||||||
RD_BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
|
RD_BOOL bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp);
|
||||||
/* cache.c */
|
/* cache.c */
|
||||||
@ -165,7 +170,9 @@ RD_BOOL rdp_connect(char *server, uint32 flags, char *domain, char *password, ch
|
|||||||
char *directory, RD_BOOL reconnect);
|
char *directory, RD_BOOL reconnect);
|
||||||
void rdp_reset_state(void);
|
void rdp_reset_state(void);
|
||||||
void rdp_disconnect(void);
|
void rdp_disconnect(void);
|
||||||
void rdp_protocol_error(const char *message, STREAM s);
|
#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 */
|
/* rdpdr.c */
|
||||||
int get_device_index(RD_NTHANDLE handle);
|
int get_device_index(RD_NTHANDLE handle);
|
||||||
void convert_to_unix_filename(char *filename);
|
void convert_to_unix_filename(char *filename);
|
||||||
@ -220,7 +227,7 @@ char *tcp_get_address(void);
|
|||||||
RD_BOOL tcp_is_connected(void);
|
RD_BOOL tcp_is_connected(void);
|
||||||
void tcp_reset_state(void);
|
void tcp_reset_state(void);
|
||||||
RD_BOOL tcp_tls_connect(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);
|
void tcp_run_ui(RD_BOOL run);
|
||||||
|
|
||||||
/* asn.c */
|
/* asn.c */
|
||||||
|
@ -836,7 +836,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
case 'u':
|
case 'u':
|
||||||
g_username = (char *) xmalloc(strlen(optarg) + 1);
|
g_username = (char *) xmalloc(strlen(optarg) + 1);
|
||||||
STRNCPY(g_username, optarg, strlen(optarg) + 1);
|
strcpy(g_username, optarg);
|
||||||
username_option = 1;
|
username_option = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1355,7 +1355,7 @@ main(int argc, char *argv[])
|
|||||||
STRNCPY(domain, g_redirect_domain, sizeof(domain));
|
STRNCPY(domain, g_redirect_domain, sizeof(domain));
|
||||||
xfree(g_username);
|
xfree(g_username);
|
||||||
g_username = (char *) xmalloc(strlen(g_redirect_username) + 1);
|
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));
|
STRNCPY(server, g_redirect_server, sizeof(server));
|
||||||
flags |= RDP_INFO_AUTOLOGON;
|
flags |= RDP_INFO_AUTOLOGON;
|
||||||
|
|
||||||
@ -1790,7 +1790,7 @@ str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler,
|
|||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
if (*rest)
|
if (*rest)
|
||||||
STRNCPY(buf, *rest, buflen);
|
STRNCPY(buf, *rest, buflen);
|
||||||
strncat(buf, input, inputlen);
|
strncat(buf, input, buflen);
|
||||||
p = buf;
|
p = buf;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
|
118
rdp.c
118
rdp.c
@ -59,7 +59,7 @@ extern RD_BOOL g_dynamic_session_resize;
|
|||||||
|
|
||||||
RD_BOOL g_exit_mainloop = False;
|
RD_BOOL g_exit_mainloop = False;
|
||||||
|
|
||||||
uint8 *g_next_packet;
|
size_t g_next_packet;
|
||||||
uint32 g_rdp_shareid;
|
uint32 g_rdp_shareid;
|
||||||
|
|
||||||
extern RDPCOMP g_mppc_dict;
|
extern RDPCOMP g_mppc_dict;
|
||||||
@ -128,6 +128,9 @@ rdp_ts_in_share_control_header(STREAM s, uint8 * type, uint16 * length)
|
|||||||
|
|
||||||
*type = pdu_type & 0xf;
|
*type = pdu_type & 0xf;
|
||||||
|
|
||||||
|
/* Give just the size of the data */
|
||||||
|
*length -= 6;
|
||||||
|
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +145,7 @@ rdp_recv(uint8 * type)
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* fill stream with data if needed for parsing a new packet */
|
/* fill stream with data if needed for parsing a new packet */
|
||||||
if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end) || (g_next_packet == NULL))
|
if (g_next_packet == 0)
|
||||||
{
|
{
|
||||||
rdp_s = sec_recv(&is_fastpath);
|
rdp_s = sec_recv(&is_fastpath);
|
||||||
if (rdp_s == NULL)
|
if (rdp_s == NULL)
|
||||||
@ -155,11 +158,16 @@ rdp_recv(uint8 * type)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_next_packet = rdp_s->p;
|
g_next_packet = s_tell(rdp_s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rdp_s->p = g_next_packet;
|
s_seek(rdp_s, g_next_packet);
|
||||||
|
if (s_check_end(rdp_s))
|
||||||
|
{
|
||||||
|
g_next_packet = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a TS_SHARECONTROLHEADER */
|
/* parse a TS_SHARECONTROLHEADER */
|
||||||
@ -171,7 +179,13 @@ rdp_recv(uint8 * type)
|
|||||||
|
|
||||||
logger(Protocol, Debug, "rdp_recv(), RDP packet #%d, type 0x%x", ++g_packetno, *type);
|
logger(Protocol, Debug, "rdp_recv(), RDP packet #%d, type 0x%x", ++g_packetno, *type);
|
||||||
|
|
||||||
g_next_packet += length;
|
if (!s_check_rem(rdp_s, length))
|
||||||
|
{
|
||||||
|
rdp_protocol_error("not enough data for PDU", rdp_s);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_next_packet = s_tell(rdp_s) + length;
|
||||||
|
|
||||||
return rdp_s;
|
return rdp_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +208,7 @@ rdp_send_data(STREAM s, uint8 data_pdu_type)
|
|||||||
uint16 length;
|
uint16 length;
|
||||||
|
|
||||||
s_pop_layer(s, rdp_hdr);
|
s_pop_layer(s, rdp_hdr);
|
||||||
length = s->end - s->p;
|
length = s_remaining(s);
|
||||||
|
|
||||||
out_uint16_le(s, length);
|
out_uint16_le(s, length);
|
||||||
out_uint16_le(s, (RDP_PDU_DATA | 0x10));
|
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;
|
static iconv_t icv_local_to_utf16;
|
||||||
size_t ibl, obl;
|
size_t ibl, obl;
|
||||||
char *pin, *pout;
|
char *pin;
|
||||||
|
unsigned char *pout;
|
||||||
|
|
||||||
|
|
||||||
if (string == NULL || len == 0)
|
if (string == NULL || len == 0)
|
||||||
@ -263,18 +278,16 @@ rdp_out_unistr(STREAM s, char *string, int len)
|
|||||||
ibl = strlen(string);
|
ibl = strlen(string);
|
||||||
obl = len + 2;
|
obl = len + 2;
|
||||||
pin = string;
|
pin = string;
|
||||||
pout = (char *) s->p;
|
out_uint8p(s, pout, len + 2);
|
||||||
|
|
||||||
memset(pout, 0, len + 4);
|
memset(pout, 0, len + 2);
|
||||||
|
|
||||||
|
|
||||||
if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
|
if (iconv(icv_local_to_utf16, (char **) &pin, &ibl, (char **)&pout, &obl) == (size_t) - 1)
|
||||||
{
|
{
|
||||||
logger(Protocol, Error, "rdp_out_unistr(), iconv(2) fail, errno %d", errno);
|
logger(Protocol, Error, "rdp_out_unistr(), iconv(2) fail, errno %d", errno);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p += len + 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Input a string in Unicode
|
/* Input a string in Unicode
|
||||||
@ -286,7 +299,8 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
|
|||||||
{
|
{
|
||||||
static iconv_t icv_utf16_to_local;
|
static iconv_t icv_utf16_to_local;
|
||||||
size_t ibl, obl;
|
size_t ibl, obl;
|
||||||
char *pin, *pout;
|
unsigned char *pin;
|
||||||
|
char *pout;
|
||||||
|
|
||||||
struct stream packet = *s;
|
struct stream packet = *s;
|
||||||
|
|
||||||
@ -296,9 +310,20 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
|
|||||||
abort();
|
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))
|
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
|
// if not already open
|
||||||
@ -323,7 +348,7 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
|
|||||||
|
|
||||||
ibl = in_len;
|
ibl = in_len;
|
||||||
obl = *str_size - 1;
|
obl = *str_size - 1;
|
||||||
pin = (char *) s->p;
|
in_uint8p(s, pin, in_len);
|
||||||
pout = *string;
|
pout = *string;
|
||||||
|
|
||||||
if (iconv(icv_utf16_to_local, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
|
if (iconv(icv_utf16_to_local, (char **) &pin, &ibl, &pout, &obl) == (size_t) - 1)
|
||||||
@ -344,9 +369,7 @@ rdp_in_unistr(STREAM s, int in_len, char **string, uint32 * str_size)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we must update the location of the current STREAM for future reads of s->p */
|
/* Always force the last byte to be a null */
|
||||||
s->p += in_len;
|
|
||||||
|
|
||||||
*pout = 0;
|
*pout = 0;
|
||||||
|
|
||||||
if (*string)
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -535,6 +558,7 @@ rdp_send_client_info_pdu(uint32 flags, char *domain, char *user,
|
|||||||
g_redirect = False;
|
g_redirect = False;
|
||||||
|
|
||||||
sec_send(s, sec_flags);
|
sec_send(s, sec_flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a control PDU */
|
/* Send a control PDU */
|
||||||
@ -551,6 +575,7 @@ rdp_send_control(uint16 action)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, RDP_DATA_PDU_CONTROL);
|
rdp_send_data(s, RDP_DATA_PDU_CONTROL);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a synchronisation PDU */
|
/* Send a synchronisation PDU */
|
||||||
@ -568,6 +593,7 @@ rdp_send_synchronise(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
|
rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a single input event */
|
/* 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);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, RDP_DATA_PDU_INPUT);
|
rdp_send_data(s, RDP_DATA_PDU_INPUT);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send a Suppress Output PDU */
|
/* Send a Suppress Output PDU */
|
||||||
@ -625,6 +652,7 @@ rdp_send_suppress_output_pdu(enum RDP_SUPPRESS_STATUS allowupdates)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
|
rdp_send_data(s, RDP_DATA_PDU_CLIENT_WINDOW_STATUS);
|
||||||
|
s_free(s);
|
||||||
current_status = allowupdates;
|
current_status = allowupdates;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,6 +697,7 @@ rdp_enum_bmpcache2(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, 0x2b);
|
rdp_send_data(s, 0x2b);
|
||||||
|
s_free(s);
|
||||||
|
|
||||||
offset += 169;
|
offset += 169;
|
||||||
}
|
}
|
||||||
@ -691,6 +720,7 @@ rdp_send_fonts(uint16 seq)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdp_send_data(s, RDP_DATA_PDU_FONT2);
|
rdp_send_data(s, RDP_DATA_PDU_FONT2);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output general capability set (TS_GENERAL_CAPABILITYSET) */
|
/* 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, 1); /* maximumOrderLevel (ignored, should be 1) */
|
||||||
out_uint16_le(s, 0); /* numberFonts (ignored, should be 0) */
|
out_uint16_le(s, 0); /* numberFonts (ignored, should be 0) */
|
||||||
out_uint16_le(s, orderflags); /* orderFlags */
|
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); /* textFlags (ignored) */
|
||||||
out_uint16_le(s, 0); /* orderSupportExFlags */
|
out_uint16_le(s, 0); /* orderSupportExFlags */
|
||||||
out_uint32_le(s, 0); /* pad4OctetsB */
|
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, flags);
|
||||||
in_uint32_le(s, chunk_size);
|
in_uint32_le(s, chunk_size);
|
||||||
|
|
||||||
|
UNUSED(flags);
|
||||||
vc_chunk_size = chunk_size;
|
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, sizeof(RDP_SOURCE));
|
||||||
out_uint16_le(s, caplen);
|
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_uint16_le(s, 17); /* num_caps */
|
||||||
out_uint8s(s, 2); /* pad */
|
out_uint8s(s, 2); /* pad */
|
||||||
|
|
||||||
@ -1128,6 +1159,7 @@ rdp_send_confirm_active(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
sec_send(s, sec_flags);
|
sec_send(s, sec_flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process a general capability set */
|
/* Process a general capability set */
|
||||||
@ -1210,25 +1242,25 @@ static void
|
|||||||
rdp_process_server_caps(STREAM s, uint16 length)
|
rdp_process_server_caps(STREAM s, uint16 length)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
uint8 *next, *start;
|
size_t next, start;
|
||||||
uint16 ncapsets, capset_type, capset_length;
|
uint16 ncapsets, capset_type, capset_length;
|
||||||
|
|
||||||
logger(Protocol, Debug, "%s()", __func__);
|
logger(Protocol, Debug, "%s()", __func__);
|
||||||
|
|
||||||
start = s->p;
|
start = s_tell(s);
|
||||||
|
|
||||||
in_uint16_le(s, ncapsets);
|
in_uint16_le(s, ncapsets);
|
||||||
in_uint8s(s, 2); /* pad */
|
in_uint8s(s, 2); /* pad */
|
||||||
|
|
||||||
for (n = 0; n < ncapsets; n++)
|
for (n = 0; n < ncapsets; n++)
|
||||||
{
|
{
|
||||||
if (s->p > start + length)
|
if (s_tell(s) > start + length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
in_uint16_le(s, capset_type);
|
in_uint16_le(s, capset_type);
|
||||||
in_uint16_le(s, capset_length);
|
in_uint16_le(s, capset_length);
|
||||||
|
|
||||||
next = s->p + capset_length - 4;
|
next = s_tell(s) + capset_length - 4;
|
||||||
|
|
||||||
switch (capset_type)
|
switch (capset_type)
|
||||||
{
|
{
|
||||||
@ -1247,7 +1279,7 @@ rdp_process_server_caps(STREAM s, uint16 length)
|
|||||||
break;
|
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))
|
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);
|
in_uint8s(s, len_src_descriptor);
|
||||||
|
|
||||||
@ -1416,8 +1448,7 @@ process_pointer_pdu(STREAM s)
|
|||||||
case RDP_POINTER_MOVE:
|
case RDP_POINTER_MOVE:
|
||||||
in_uint16_le(s, x);
|
in_uint16_le(s, x);
|
||||||
in_uint16_le(s, y);
|
in_uint16_le(s, y);
|
||||||
if (s_check(s))
|
ui_move_pointer(x, y);
|
||||||
ui_move_pointer(x, y);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RDP_POINTER_COLOR:
|
case RDP_POINTER_COLOR:
|
||||||
@ -1521,7 +1552,7 @@ process_bitmap_data(STREAM s)
|
|||||||
/* read compressed bitmap data */
|
/* read compressed bitmap data */
|
||||||
if (!s_check_rem(s, size))
|
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);
|
in_uint8p(s, data, size);
|
||||||
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
|
bmpdata = (uint8 *) xmalloc(width * height * Bpp);
|
||||||
@ -1718,6 +1749,7 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
|
|||||||
uint16 clen;
|
uint16 clen;
|
||||||
uint32 len;
|
uint32 len;
|
||||||
|
|
||||||
|
uint8 *buf;
|
||||||
uint32 roff, rlen;
|
uint32 roff, rlen;
|
||||||
|
|
||||||
struct stream *ns = &(g_mppc_dict.ns);
|
struct stream *ns = &(g_mppc_dict.ns);
|
||||||
@ -1734,21 +1766,22 @@ process_data_pdu(STREAM s, uint32 * ext_disc_reason)
|
|||||||
if (len > RDP_MPPC_DICT_SIZE)
|
if (len > RDP_MPPC_DICT_SIZE)
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
"process_data_pdu(), error decompressed packet size exceeds max");
|
"process_data_pdu(), error decompressed packet size exceeds max");
|
||||||
if (mppc_expand(s->p, clen, ctype, &roff, &rlen) == -1)
|
in_uint8p(s, buf, clen);
|
||||||
|
if (mppc_expand(buf, clen, ctype, &roff, &rlen) == -1)
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
"process_data_pdu(), error while decompressing packet");
|
"process_data_pdu(), error while decompressing packet");
|
||||||
|
|
||||||
/* len -= 18; */
|
/* len -= 18; */
|
||||||
|
|
||||||
/* allocate memory and copy the uncompressed data into the temporary stream */
|
/* allocate memory and copy the uncompressed data into the temporary stream */
|
||||||
ns->data = (uint8 *) xrealloc(ns->data, rlen);
|
s_realloc(ns, rlen);
|
||||||
|
s_reset(ns);
|
||||||
|
|
||||||
memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
|
out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen);
|
||||||
|
|
||||||
ns->size = rlen;
|
s_mark_end(ns);
|
||||||
ns->end = (ns->data + ns->size);
|
s_seek(ns, 0);
|
||||||
ns->p = ns->data;
|
s_push_layer(ns, rdp_hdr, 0);
|
||||||
ns->rdp_hdr = ns->p;
|
|
||||||
|
|
||||||
s = ns;
|
s = ns;
|
||||||
}
|
}
|
||||||
@ -2048,7 +2081,7 @@ rdp_loop(RD_BOOL * deactivated, uint32 * ext_disc_reason)
|
|||||||
logger(Protocol, Warning,
|
logger(Protocol, Warning,
|
||||||
"rdp_loop(), unhandled PDU type %d received", type);
|
"rdp_loop(), unhandled PDU type %d received", type);
|
||||||
}
|
}
|
||||||
cont = g_next_packet < s->end;
|
cont = g_next_packet < s_length(s);
|
||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
@ -2086,7 +2119,7 @@ void
|
|||||||
rdp_reset_state(void)
|
rdp_reset_state(void)
|
||||||
{
|
{
|
||||||
logger(Protocol, Debug, "%s()", __func__);
|
logger(Protocol, Debug, "%s()", __func__);
|
||||||
g_next_packet = NULL; /* reset the packet information */
|
g_next_packet = 0; /* reset the packet information */
|
||||||
g_rdp_shareid = 0;
|
g_rdp_shareid = 0;
|
||||||
g_exit_mainloop = False;
|
g_exit_mainloop = False;
|
||||||
g_first_bitmap_caps = True;
|
g_first_bitmap_caps = True;
|
||||||
@ -2111,10 +2144,11 @@ rdp_disconnect(void)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
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)
|
if (s)
|
||||||
hexdump(s->p, s_length(s));
|
hexdump(s->data, s_length(s));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
41
rdp5.c
41
rdp5.c
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include "rdesktop.h"
|
#include "rdesktop.h"
|
||||||
|
|
||||||
extern uint8 *g_next_packet;
|
extern size_t g_next_packet;
|
||||||
|
|
||||||
extern RDPCOMP g_mppc_dict;
|
extern RDPCOMP g_mppc_dict;
|
||||||
|
|
||||||
@ -56,8 +56,7 @@ process_ts_fp_update_by_code(STREAM s, uint8 code)
|
|||||||
case FASTPATH_UPDATETYPE_PTR_POSITION:
|
case FASTPATH_UPDATETYPE_PTR_POSITION:
|
||||||
in_uint16_le(s, x);
|
in_uint16_le(s, x);
|
||||||
in_uint16_le(s, y);
|
in_uint16_le(s, y);
|
||||||
if (s_check(s))
|
ui_move_pointer(x, y);
|
||||||
ui_move_pointer(x, y);
|
|
||||||
break;
|
break;
|
||||||
case FASTPATH_UPDATETYPE_COLOR:
|
case FASTPATH_UPDATETYPE_COLOR:
|
||||||
process_colour_pointer_pdu(s);
|
process_colour_pointer_pdu(s);
|
||||||
@ -79,16 +78,17 @@ process_ts_fp_updates(STREAM s)
|
|||||||
{
|
{
|
||||||
uint16 length;
|
uint16 length;
|
||||||
uint8 hdr, code, frag, comp, ctype = 0;
|
uint8 hdr, code, frag, comp, ctype = 0;
|
||||||
uint8 *next;
|
size_t next;
|
||||||
|
|
||||||
|
uint8 *buf;
|
||||||
uint32 roff, rlen;
|
uint32 roff, rlen;
|
||||||
struct stream *ns = &(g_mppc_dict.ns);
|
struct stream *ns = &(g_mppc_dict.ns);
|
||||||
struct stream *ts;
|
struct stream *ts;
|
||||||
|
|
||||||
static STREAM assembled[0x0F] = { 0 };
|
static STREAM assembled[16] = { 0 };
|
||||||
|
|
||||||
ui_begin_update();
|
ui_begin_update();
|
||||||
while (s->p < s->end)
|
while (!s_check_end(s))
|
||||||
{
|
{
|
||||||
/* Reading a number of TS_FP_UPDATE structures from the stream here.. */
|
/* Reading a number of TS_FP_UPDATE structures from the stream here.. */
|
||||||
in_uint8(s, hdr); /* updateHeader */
|
in_uint8(s, hdr); /* updateHeader */
|
||||||
@ -101,23 +101,24 @@ process_ts_fp_updates(STREAM s)
|
|||||||
|
|
||||||
in_uint16_le(s, length); /* length */
|
in_uint16_le(s, length); /* length */
|
||||||
|
|
||||||
g_next_packet = next = s->p + length;
|
g_next_packet = next = s_tell(s) + length;
|
||||||
|
|
||||||
if (ctype & RDP_MPPC_COMPRESSED)
|
if (ctype & RDP_MPPC_COMPRESSED)
|
||||||
{
|
{
|
||||||
if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1)
|
in_uint8p(s, buf, length);
|
||||||
|
if (mppc_expand(buf, length, ctype, &roff, &rlen) == -1)
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
"process_ts_fp_update_pdu(), error while decompressing packet");
|
"process_ts_fp_update_pdu(), error while decompressing packet");
|
||||||
|
|
||||||
/* allocate memory and copy the uncompressed data into the temporary stream */
|
/* allocate memory and copy the uncompressed data into the temporary stream */
|
||||||
ns->data = (uint8 *) xrealloc(ns->data, rlen);
|
s_realloc(ns, rlen);
|
||||||
|
s_reset(ns);
|
||||||
|
|
||||||
memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff), rlen);
|
out_uint8a(ns, (unsigned char *) (g_mppc_dict.hist + roff), rlen);
|
||||||
|
|
||||||
ns->size = rlen;
|
s_mark_end(ns);
|
||||||
ns->end = (ns->data + ns->size);
|
s_seek(ns, 0);
|
||||||
ns->p = ns->data;
|
s_push_layer(ns, rdp_hdr, 0);
|
||||||
ns->rdp_hdr = ns->p;
|
|
||||||
|
|
||||||
length = rlen;
|
length = rlen;
|
||||||
ts = ns;
|
ts = ns;
|
||||||
@ -133,11 +134,7 @@ process_ts_fp_updates(STREAM s)
|
|||||||
{
|
{
|
||||||
if (assembled[code] == NULL)
|
if (assembled[code] == NULL)
|
||||||
{
|
{
|
||||||
assembled[code] = xmalloc(sizeof(struct stream));
|
assembled[code] = s_alloc(RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE);
|
||||||
memset(assembled[code], 0, sizeof(struct stream));
|
|
||||||
s_realloc(assembled[code],
|
|
||||||
RDESKTOP_FASTPATH_MULTIFRAGMENT_MAX_SIZE);
|
|
||||||
s_reset(assembled[code]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frag == FASTPATH_FRAGMENT_FIRST)
|
if (frag == FASTPATH_FRAGMENT_FIRST)
|
||||||
@ -145,17 +142,17 @@ process_ts_fp_updates(STREAM s)
|
|||||||
s_reset(assembled[code]);
|
s_reset(assembled[code]);
|
||||||
}
|
}
|
||||||
|
|
||||||
out_uint8p(assembled[code], ts->p, length);
|
out_uint8stream(assembled[code], ts, length);
|
||||||
|
|
||||||
if (frag == FASTPATH_FRAGMENT_LAST)
|
if (frag == FASTPATH_FRAGMENT_LAST)
|
||||||
{
|
{
|
||||||
s_mark_end(assembled[code]);
|
s_mark_end(assembled[code]);
|
||||||
assembled[code]->p = assembled[code]->data;
|
s_seek(assembled[code], 0);
|
||||||
process_ts_fp_update_by_code(assembled[code], code);
|
process_ts_fp_update_by_code(assembled[code], code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p = next;
|
s_seek(s, next);
|
||||||
}
|
}
|
||||||
ui_end_update();
|
ui_end_update();
|
||||||
}
|
}
|
||||||
|
142
rdpdr.c
142
rdpdr.c
@ -204,6 +204,7 @@ rdpdr_send_client_announce_reply(void)
|
|||||||
out_uint32_be(s, g_client_id); /* ClientID */
|
out_uint32_be(s, g_client_id); /* ClientID */
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
channel_send(s, rdpdr_channel);
|
channel_send(s, rdpdr_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -233,6 +234,7 @@ rdpdr_send_client_name_request(void)
|
|||||||
out_stream(s, &name);
|
out_stream(s, &name);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
channel_send(s, rdpdr_channel);
|
channel_send(s, rdpdr_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the size of the payload of the announce packet */
|
/* 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, g_rdpdr_device[i].device_type);
|
||||||
out_uint32_le(s, i); /* RDP Device ID */
|
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)
|
switch (g_rdpdr_device[i].device_type)
|
||||||
{
|
{
|
||||||
case DEVICE_TYPE_DISK:
|
case DEVICE_TYPE_DISK:
|
||||||
@ -314,7 +316,7 @@ rdpdr_send_client_device_list_announce(void)
|
|||||||
disklen = strlen(diskinfo->name) + 1;
|
disklen = strlen(diskinfo->name) + 1;
|
||||||
|
|
||||||
out_uint32_le(s, disklen); /* DeviceDataLength */
|
out_uint32_le(s, disklen); /* DeviceDataLength */
|
||||||
out_uint8p(s, diskinfo->name, disklen); /* DeviceData */
|
out_uint8a(s, diskinfo->name, disklen); /* DeviceData */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE_TYPE_PRINTER:
|
case DEVICE_TYPE_PRINTER:
|
||||||
@ -357,6 +359,7 @@ rdpdr_send_client_device_list_announce(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
channel_send(s, rdpdr_channel);
|
channel_send(s, rdpdr_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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, status);
|
||||||
out_uint32_le(s, result);
|
out_uint32_le(s, result);
|
||||||
if (length)
|
if (length)
|
||||||
out_uint8p(s, buffer, length);
|
out_uint8a(s, buffer, length);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
|
|
||||||
logger(Protocol, Debug, "rdpdr_send_completion()");
|
logger(Protocol, Debug, "rdpdr_send_completion()");
|
||||||
/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
|
/* hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8); */
|
||||||
|
|
||||||
channel_send(s, rdpdr_channel);
|
channel_send(s, rdpdr_channel);
|
||||||
|
s_free(s);
|
||||||
#ifdef WITH_SCARD
|
#ifdef WITH_SCARD
|
||||||
scard_unlock(SCARD_LOCK_RDPDR);
|
scard_unlock(SCARD_LOCK_RDPDR);
|
||||||
#endif
|
#endif
|
||||||
@ -407,7 +411,6 @@ rdpdr_process_irp(STREAM s)
|
|||||||
request,
|
request,
|
||||||
file,
|
file,
|
||||||
info_level,
|
info_level,
|
||||||
buffer_len,
|
|
||||||
id,
|
id,
|
||||||
major,
|
major,
|
||||||
minor,
|
minor,
|
||||||
@ -420,8 +423,8 @@ rdpdr_process_irp(STREAM s)
|
|||||||
char *filename;
|
char *filename;
|
||||||
uint32 filename_len;
|
uint32 filename_len;
|
||||||
|
|
||||||
uint8 *buffer, *pst_buf;
|
uint8 *pst_buf;
|
||||||
struct stream out;
|
STREAM out;
|
||||||
DEVICE_FNS *fns;
|
DEVICE_FNS *fns;
|
||||||
RD_BOOL rw_blocking = True;
|
RD_BOOL rw_blocking = True;
|
||||||
RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST;
|
RD_NTSTATUS status = RD_STATUS_INVALID_DEVICE_REQUEST;
|
||||||
@ -434,16 +437,13 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
filename = NULL;
|
filename = NULL;
|
||||||
|
|
||||||
buffer_len = 0;
|
out = NULL;
|
||||||
buffer = (uint8 *) xmalloc(1024);
|
|
||||||
buffer[0] = 0;
|
|
||||||
|
|
||||||
if (device >= RDPDR_MAX_DEVICES)
|
if (device >= RDPDR_MAX_DEVICES)
|
||||||
{
|
{
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
"rdpdr_process_irp(), invalid irp device=0x%lx, file=0x%lx, id=0x%lx, major=0x%lx, minor=0x%lx",
|
"rdpdr_process_irp(), invalid irp device=0x%lx, file=0x%lx, id=0x%lx, major=0x%lx, minor=0x%lx",
|
||||||
device, file, id, major, minor);
|
device, file, id, major, minor);
|
||||||
xfree(buffer);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +482,6 @@ rdpdr_process_irp(STREAM s)
|
|||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
"rdpdr_process_irp(), received IRP for unknown device type %ld",
|
"rdpdr_process_irp(), received IRP for unknown device type %ld",
|
||||||
device);
|
device);
|
||||||
xfree(buffer);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,7 +515,9 @@ rdpdr_process_irp(STREAM s)
|
|||||||
flags_and_attributes, filename, &result);
|
flags_and_attributes, filename, &result);
|
||||||
|
|
||||||
free(filename);
|
free(filename);
|
||||||
buffer_len = 1;
|
out = s_alloc(1);
|
||||||
|
out_uint8(out, 0);
|
||||||
|
s_mark_end(out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MJ_CLOSE:
|
case IRP_MJ_CLOSE:
|
||||||
@ -553,14 +554,14 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
if (rw_blocking) /* Complete read immediately */
|
if (rw_blocking) /* Complete read immediately */
|
||||||
{
|
{
|
||||||
buffer = (uint8 *) xrealloc((void *) buffer, length);
|
uint8* buffer;
|
||||||
if (!buffer)
|
out = s_alloc(length);
|
||||||
{
|
out_uint8p(out, buffer, length);
|
||||||
status = RD_STATUS_CANCELLED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
status = fns->read(file, buffer, length, offset, &result);
|
status = fns->read(file, buffer, length, offset, &result);
|
||||||
buffer_len = result;
|
/* Might have read less */
|
||||||
|
s_mark_end(out);
|
||||||
|
s_seek(out, result);
|
||||||
|
s_mark_end(out);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +585,9 @@ rdpdr_process_irp(STREAM s)
|
|||||||
break;
|
break;
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
|
|
||||||
buffer_len = 1;
|
out = s_alloc(1);
|
||||||
|
out_uint8(out, 0);
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
if (!fns->write)
|
if (!fns->write)
|
||||||
{
|
{
|
||||||
@ -608,7 +611,9 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
if (rw_blocking) /* Complete immediately */
|
if (rw_blocking) /* Complete immediately */
|
||||||
{
|
{
|
||||||
status = fns->write(file, s->p, length, offset, &result);
|
unsigned char *data;
|
||||||
|
in_uint8p(s, data, length);
|
||||||
|
status = fns->write(file, data, length, offset, &result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,10 +646,10 @@ rdpdr_process_irp(STREAM s)
|
|||||||
}
|
}
|
||||||
in_uint32_le(s, info_level);
|
in_uint32_le(s, info_level);
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
out = s_alloc(1024);
|
||||||
out.size = sizeof(buffer);
|
status = disk_query_information(file, info_level, out);
|
||||||
status = disk_query_information(file, info_level, &out);
|
s_mark_end(out);
|
||||||
result = buffer_len = out.p - out.data;
|
result = s_length(out);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -658,10 +663,10 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
in_uint32_le(s, info_level);
|
in_uint32_le(s, info_level);
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
out = s_alloc(1024);
|
||||||
out.size = sizeof(buffer);
|
status = disk_set_information(file, info_level, s, out);
|
||||||
status = disk_set_information(file, info_level, s, &out);
|
s_mark_end(out);
|
||||||
result = buffer_len = out.p - out.data;
|
result = s_length(out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
case IRP_MJ_QUERY_VOLUME_INFORMATION:
|
||||||
@ -674,10 +679,10 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
in_uint32_le(s, info_level);
|
in_uint32_le(s, info_level);
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
out = s_alloc(1024);
|
||||||
out.size = sizeof(buffer);
|
status = disk_query_volume_information(file, info_level, out);
|
||||||
status = disk_query_volume_information(file, info_level, &out);
|
s_mark_end(out);
|
||||||
result = buffer_len = out.p - out.data;
|
result = s_length(out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MJ_DIRECTORY_CONTROL:
|
case IRP_MJ_DIRECTORY_CONTROL:
|
||||||
@ -703,13 +708,16 @@ rdpdr_process_irp(STREAM s)
|
|||||||
convert_to_unix_filename(filename);
|
convert_to_unix_filename(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
out = s_alloc(1024);
|
||||||
out.size = sizeof(buffer);
|
|
||||||
status = disk_query_directory(file, info_level, filename,
|
status = disk_query_directory(file, info_level, filename,
|
||||||
&out);
|
out);
|
||||||
result = buffer_len = out.p - out.data;
|
s_mark_end(out);
|
||||||
if (!buffer_len)
|
if (!s_length(out))
|
||||||
buffer_len++;
|
{
|
||||||
|
out_uint8(out, 0);
|
||||||
|
s_mark_end(out);
|
||||||
|
}
|
||||||
|
result = s_length(out);
|
||||||
|
|
||||||
free(filename);
|
free(filename);
|
||||||
break;
|
break;
|
||||||
@ -756,23 +764,14 @@ rdpdr_process_irp(STREAM s)
|
|||||||
in_uint8s(s, 0x14);
|
in_uint8s(s, 0x14);
|
||||||
|
|
||||||
/* TODO: Why do we need to increase length by padlen? Or is it hdr len? */
|
/* TODO: Why do we need to increase length by padlen? Or is it hdr len? */
|
||||||
buffer = (uint8 *) xrealloc((void *) buffer, bytes_out + 0x14);
|
out = s_alloc(bytes_out + 0x14);
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
status = RD_STATUS_CANCELLED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
|
||||||
/* Guess, just a simple mistype. Check others */
|
|
||||||
//out.size = sizeof(buffer);
|
|
||||||
out.size = bytes_out + 0x14;
|
|
||||||
|
|
||||||
#ifdef WITH_SCARD
|
#ifdef WITH_SCARD
|
||||||
scardSetInfo(g_epoch, device, id, bytes_out + 0x14);
|
scardSetInfo(g_epoch, device, id, bytes_out + 0x14);
|
||||||
#endif
|
#endif
|
||||||
status = fns->device_control(file, request, s, &out);
|
status = fns->device_control(file, request, s, out);
|
||||||
result = buffer_len = out.p - out.data;
|
s_mark_end(out);
|
||||||
|
result = s_length(out);
|
||||||
|
|
||||||
/* Serial SERIAL_WAIT_ON_MASK */
|
/* Serial SERIAL_WAIT_ON_MASK */
|
||||||
if (status == RD_STATUS_PENDING)
|
if (status == RD_STATUS_PENDING)
|
||||||
@ -801,12 +800,12 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
in_uint32_le(s, info_level);
|
in_uint32_le(s, info_level);
|
||||||
|
|
||||||
out.data = out.p = buffer;
|
out = s_alloc(1024);
|
||||||
out.size = sizeof(buffer);
|
|
||||||
/* FIXME: Perhaps consider actually *do*
|
/* FIXME: Perhaps consider actually *do*
|
||||||
something here :-) */
|
something here :-) */
|
||||||
status = RD_STATUS_SUCCESS;
|
status = RD_STATUS_SUCCESS;
|
||||||
result = buffer_len = out.p - out.data;
|
s_mark_end(out);
|
||||||
|
result = s_length(out);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -818,11 +817,25 @@ rdpdr_process_irp(STREAM s)
|
|||||||
|
|
||||||
if (status != RD_STATUS_PENDING)
|
if (status != RD_STATUS_PENDING)
|
||||||
{
|
{
|
||||||
|
size_t buffer_len;
|
||||||
|
uint8 *buffer;
|
||||||
|
|
||||||
|
if (out != NULL)
|
||||||
|
{
|
||||||
|
buffer_len = s_length(out);
|
||||||
|
s_seek(out, 0);
|
||||||
|
in_uint8p(out, buffer, buffer_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer_len = 0;
|
||||||
|
buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
|
rdpdr_send_completion(device, id, status, result, buffer, buffer_len);
|
||||||
}
|
}
|
||||||
if (buffer)
|
if (out)
|
||||||
xfree(buffer);
|
s_free(out);
|
||||||
buffer = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -868,6 +881,7 @@ rdpdr_send_client_capability_response(void)
|
|||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
channel_send(s, rdpdr_channel);
|
channel_send(s, rdpdr_channel);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -877,10 +891,9 @@ rdpdr_process(STREAM s)
|
|||||||
uint16 vmin;
|
uint16 vmin;
|
||||||
uint16 component;
|
uint16 component;
|
||||||
uint16 pakid;
|
uint16 pakid;
|
||||||
struct stream packet = *s;
|
|
||||||
|
|
||||||
logger(Protocol, Debug, "rdpdr_process()");
|
logger(Protocol, Debug, "rdpdr_process()");
|
||||||
/* hexdump(s->p, s->end - s->p); */
|
/* hexdump(s->p, s_remaining(s)); */
|
||||||
|
|
||||||
in_uint16(s, component); /* RDPDR_HEADER.Component */
|
in_uint16(s, component); /* RDPDR_HEADER.Component */
|
||||||
in_uint16(s, pakid); /* RDPDR_HEADER.PacketId */
|
in_uint16(s, pakid); /* RDPDR_HEADER.PacketId */
|
||||||
@ -900,15 +913,6 @@ rdpdr_process(STREAM s)
|
|||||||
|
|
||||||
in_uint32_le(s, g_client_id); /* ClientID */
|
in_uint32_le(s, g_client_id); /* ClientID */
|
||||||
|
|
||||||
/* g_client_id is sent back to server,
|
|
||||||
so lets check that we actually got
|
|
||||||
valid data from stream to prevent
|
|
||||||
that we leak back data to server */
|
|
||||||
if (!s_check(s))
|
|
||||||
{
|
|
||||||
rdp_protocol_error("rdpdr_process(), consume of g_client_id from stream did overrun", &packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The RDP client is responsibility to provide a random client id
|
/* The RDP client is responsibility to provide a random client id
|
||||||
if server version is < 12 */
|
if server version is < 12 */
|
||||||
if (vmin < 0x000c)
|
if (vmin < 0x000c)
|
||||||
|
@ -64,7 +64,7 @@ rdpedisp_process_pdu(STREAM s)
|
|||||||
|
|
||||||
/* Read DISPLAYCONTROL_HEADER */
|
/* Read DISPLAYCONTROL_HEADER */
|
||||||
in_uint32_le(s, type); /* type */
|
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);
|
logger(Protocol, Debug, "rdpedisp_process_pdu(), Got PDU type %d", type);
|
||||||
|
|
||||||
|
78
rdpsnd.c
78
rdpsnd.c
@ -64,6 +64,7 @@ unsigned int queue_hi, queue_lo, queue_pending;
|
|||||||
struct audio_packet packet_queue[MAX_QUEUE];
|
struct audio_packet packet_queue[MAX_QUEUE];
|
||||||
|
|
||||||
static uint8 packet_opcode;
|
static uint8 packet_opcode;
|
||||||
|
static size_t packet_len;
|
||||||
static struct stream packet;
|
static struct stream packet;
|
||||||
|
|
||||||
void (*wave_out_play) (void);
|
void (*wave_out_play) (void);
|
||||||
@ -103,6 +104,7 @@ rdpsnd_send_waveconfirm(uint16 tick, uint8 packet_index)
|
|||||||
out_uint8(s, 0);
|
out_uint8(s, 0);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
rdpsnd_send(s);
|
rdpsnd_send(s);
|
||||||
|
s_free(s);
|
||||||
|
|
||||||
logger(Sound, Debug, "rdpsnd_send_waveconfirm(), tick=%u, index=%u",
|
logger(Sound, Debug, "rdpsnd_send_waveconfirm(), tick=%u, index=%u",
|
||||||
(unsigned) tick, (unsigned) packet_index);
|
(unsigned) tick, (unsigned) packet_index);
|
||||||
@ -259,6 +261,7 @@ rdpsnd_process_negotiate(STREAM in)
|
|||||||
(int) format_count);
|
(int) format_count);
|
||||||
|
|
||||||
rdpsnd_send(out);
|
rdpsnd_send(out);
|
||||||
|
s_free(out);
|
||||||
|
|
||||||
rdpsnd_negotiated = True;
|
rdpsnd_negotiated = True;
|
||||||
}
|
}
|
||||||
@ -273,7 +276,7 @@ rdpsnd_process_training(STREAM in)
|
|||||||
|
|
||||||
if (!s_check_rem(in, 4))
|
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);
|
in_uint16_le(in, tick);
|
||||||
@ -286,14 +289,18 @@ rdpsnd_process_training(STREAM in)
|
|||||||
out_uint16_le(out, packsize);
|
out_uint16_le(out, packsize);
|
||||||
s_mark_end(out);
|
s_mark_end(out);
|
||||||
rdpsnd_send(out);
|
rdpsnd_send(out);
|
||||||
|
s_free(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rdpsnd_process_packet(uint8 opcode, STREAM s)
|
rdpsnd_process_packet(uint8 opcode, STREAM s)
|
||||||
{
|
{
|
||||||
uint16 vol_left, vol_right;
|
uint16 vol_left, vol_right;
|
||||||
static uint16 tick, format;
|
|
||||||
static uint8 packet_index;
|
uint16 tick, format;
|
||||||
|
uint8 packet_index;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
@ -342,9 +349,12 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
|
|||||||
current_format = format;
|
current_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdpsnd_queue_write(rdpsnd_dsp_process
|
size = s_remaining(s);
|
||||||
(s->p, s->end - s->p, current_driver,
|
in_uint8p(s, data, size);
|
||||||
&formats[current_format]), tick, packet_index);
|
rdpsnd_queue_write(rdpsnd_dsp_process(data, size,
|
||||||
|
current_driver,
|
||||||
|
&formats[current_format]),
|
||||||
|
tick, packet_index);
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case SNDC_CLOSE:
|
case SNDC_CLOSE:
|
||||||
@ -379,14 +389,12 @@ rdpsnd_process_packet(uint8 opcode, STREAM s)
|
|||||||
static void
|
static void
|
||||||
rdpsnd_process(STREAM s)
|
rdpsnd_process(STREAM s)
|
||||||
{
|
{
|
||||||
uint16 len;
|
|
||||||
|
|
||||||
while (!s_check_end(s))
|
while (!s_check_end(s))
|
||||||
{
|
{
|
||||||
/* New packet */
|
/* New packet */
|
||||||
if (packet.size == 0)
|
if (packet_len == 0)
|
||||||
{
|
{
|
||||||
if ((s->end - s->p) < 4)
|
if (!s_check_rem(s, 4))
|
||||||
{
|
{
|
||||||
logger(Sound, Error,
|
logger(Sound, Error,
|
||||||
"rdpsnd_process(), split at packet header, things will go south from here...");
|
"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_uint8(s, packet_opcode);
|
||||||
in_uint8s(s, 1); /* Padding */
|
in_uint8s(s, 1); /* Padding */
|
||||||
in_uint16_le(s, len);
|
in_uint16_le(s, packet_len);
|
||||||
|
|
||||||
logger(Sound, Debug, "rdpsnd_process(), Opcode = 0x%x Length= %d",
|
logger(Sound, Debug, "rdpsnd_process(), Opcode = 0x%x Length= %d",
|
||||||
(int) packet_opcode, (int) len);
|
(int) packet_opcode, (int) packet_len);
|
||||||
|
|
||||||
packet.p = packet.data;
|
|
||||||
packet.end = packet.data + len;
|
|
||||||
packet.size = len;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len = MIN(s->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... */
|
/* Microsoft's server is so broken it's not even funny... */
|
||||||
if (packet_opcode == SNDC_WAVE)
|
if (packet_opcode == SNDC_WAVE)
|
||||||
{
|
{
|
||||||
if ((packet.p - packet.data) < 12)
|
if (s_length(&packet) < 12)
|
||||||
len = MIN(len, 12 - (packet.p - packet.data));
|
len = MIN(len, 12 - s_length(&packet));
|
||||||
else if ((packet.p - packet.data) == 12)
|
else if (s_length(&packet) == 12)
|
||||||
{
|
{
|
||||||
logger(Sound, Debug,
|
logger(Sound, Debug,
|
||||||
"rdpsnd_process(), eating 4 bytes of %d bytes...",
|
"rdpsnd_process(), eating 4 bytes of %d bytes...",
|
||||||
@ -422,16 +428,18 @@ rdpsnd_process(STREAM s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
in_uint8a(s, packet.p, len);
|
in_uint8stream(s, &packet, len);
|
||||||
packet.p += len;
|
/* Always end it so s_length() works */
|
||||||
|
s_mark_end(&packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Packet fully assembled */
|
/* Packet fully assembled */
|
||||||
if (packet.p == packet.end)
|
if (s_length(&packet) == packet_len)
|
||||||
{
|
{
|
||||||
packet.p = packet.data;
|
s_seek(&packet, 0);
|
||||||
rdpsnd_process_packet(packet_opcode, &packet);
|
rdpsnd_process_packet(packet_opcode, &packet);
|
||||||
packet.size = 0;
|
packet_len = 0;
|
||||||
|
s_reset(&packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,15 +459,11 @@ rdpsnddbg_process(STREAM s)
|
|||||||
static char *rest = NULL;
|
static char *rest = NULL;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
if (!s_check(s))
|
pkglen = s_remaining(s);
|
||||||
{
|
|
||||||
rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
pkglen = s->end - s->p;
|
|
||||||
/* str_handle_lines requires null terminated strings */
|
/* str_handle_lines requires null terminated strings */
|
||||||
buf = (char *) xmalloc(pkglen + 1);
|
buf = (char *) xmalloc(pkglen + 1);
|
||||||
STRNCPY(buf, (char *) s->p, pkglen + 1);
|
in_uint8a(s, buf, pkglen);
|
||||||
|
buf[pkglen] = '\0';
|
||||||
|
|
||||||
str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
|
str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
|
||||||
|
|
||||||
@ -515,9 +519,7 @@ rdpsnd_init(char *optarg)
|
|||||||
|
|
||||||
drivers = NULL;
|
drivers = NULL;
|
||||||
|
|
||||||
packet.data = (uint8 *) xmalloc(65536);
|
s_realloc(&packet, 65536);
|
||||||
packet.p = packet.end = packet.data;
|
|
||||||
packet.size = 0;
|
|
||||||
|
|
||||||
rdpsnd_channel =
|
rdpsnd_channel =
|
||||||
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
|
channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
|
||||||
@ -643,7 +645,7 @@ rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
|
|||||||
|
|
||||||
queue_hi = next_hi;
|
queue_hi = next_hi;
|
||||||
|
|
||||||
packet->s = *s;
|
packet->s = s;
|
||||||
packet->tick = tick;
|
packet->tick = tick;
|
||||||
packet->index = index;
|
packet->index = index;
|
||||||
|
|
||||||
@ -677,7 +679,7 @@ rdpsnd_queue_clear(void)
|
|||||||
while (queue_pending != queue_hi)
|
while (queue_pending != queue_hi)
|
||||||
{
|
{
|
||||||
packet = &packet_queue[queue_pending];
|
packet = &packet_queue[queue_pending];
|
||||||
xfree(packet->s.data);
|
s_free(packet->s);
|
||||||
queue_pending = (queue_pending + 1) % MAX_QUEUE;
|
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);
|
(packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
|
||||||
elapsed /= 1000;
|
elapsed /= 1000;
|
||||||
|
|
||||||
xfree(packet->s.data);
|
s_free(packet->s);
|
||||||
rdpsnd_send_waveconfirm((packet->tick + elapsed) % 65536, packet->index);
|
rdpsnd_send_waveconfirm((packet->tick + elapsed) % 65536, packet->index);
|
||||||
queue_pending = (queue_pending + 1) % MAX_QUEUE;
|
queue_pending = (queue_pending + 1) % MAX_QUEUE;
|
||||||
}
|
}
|
||||||
|
2
rdpsnd.h
2
rdpsnd.h
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
struct audio_packet
|
struct audio_packet
|
||||||
{
|
{
|
||||||
struct stream s;
|
STREAM s;
|
||||||
uint16 tick;
|
uint16 tick;
|
||||||
uint8 index;
|
uint8 index;
|
||||||
|
|
||||||
|
@ -358,6 +358,8 @@ alsa_play(void)
|
|||||||
struct audio_packet *packet;
|
struct audio_packet *packet;
|
||||||
STREAM out;
|
STREAM out;
|
||||||
int len;
|
int len;
|
||||||
|
const unsigned char *data;
|
||||||
|
size_t before;
|
||||||
static long prev_s, prev_us;
|
static long prev_s, prev_us;
|
||||||
int duration;
|
int duration;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@ -376,17 +378,25 @@ alsa_play(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
packet = rdpsnd_queue_current_packet();
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = packet->s;
|
||||||
|
|
||||||
next_tick = rdpsnd_queue_next_tick();
|
next_tick = rdpsnd_queue_next_tick();
|
||||||
|
|
||||||
len = (out->end - out->p) / (samplewidth_out * audiochannels_out);
|
before = s_tell(out);
|
||||||
if ((len = snd_pcm_writei(out_handle, out->p, ((MAX_FRAMES < len) ? MAX_FRAMES : len))) < 0)
|
|
||||||
|
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);
|
snd_pcm_prepare(out_handle);
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
out->p += (len * samplewidth_out * audiochannels_out);
|
|
||||||
|
/* We might not have written everything */
|
||||||
|
s_seek(out, before + len * samplewidth_out * audiochannels_out);
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
@ -395,7 +405,7 @@ alsa_play(void)
|
|||||||
if (packet->tick > next_tick)
|
if (packet->tick > next_tick)
|
||||||
next_tick += 65536;
|
next_tick += 65536;
|
||||||
|
|
||||||
if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
|
if (s_check_end(out) || duration > next_tick - packet->tick + 500)
|
||||||
{
|
{
|
||||||
snd_pcm_sframes_t delay_frames;
|
snd_pcm_sframes_t delay_frames;
|
||||||
unsigned long delay_us;
|
unsigned long delay_us;
|
||||||
|
52
rdpsnd_dsp.c
52
rdpsnd_dsp.c
@ -175,8 +175,8 @@ rdpsnd_dsp_resample_supported(RD_WAVEFORMATEX * format)
|
|||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32
|
STREAM
|
||||||
rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
|
rdpsnd_dsp_resample(unsigned char *in, unsigned int size,
|
||||||
RD_WAVEFORMATEX * format, RD_BOOL stream_be)
|
RD_WAVEFORMATEX * format, RD_BOOL stream_be)
|
||||||
{
|
{
|
||||||
UNUSED(stream_be);
|
UNUSED(stream_be);
|
||||||
@ -190,13 +190,15 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
|
|||||||
int innum, outnum;
|
int innum, outnum;
|
||||||
unsigned char *tmpdata = NULL, *tmp = NULL;
|
unsigned char *tmpdata = NULL, *tmp = NULL;
|
||||||
int samplewidth = format->wBitsPerSample / 8;
|
int samplewidth = format->wBitsPerSample / 8;
|
||||||
|
STREAM out;
|
||||||
int outsize = 0;
|
int outsize = 0;
|
||||||
|
unsigned char *data;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((resample_to_bitspersample == format->wBitsPerSample) &&
|
if ((resample_to_bitspersample == format->wBitsPerSample) &&
|
||||||
(resample_to_channels == format->nChannels) &&
|
(resample_to_channels == format->nChannels) &&
|
||||||
(resample_to_srate == format->nSamplesPerSec))
|
(resample_to_srate == format->nSamplesPerSec))
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
#ifdef B_ENDIAN
|
#ifdef B_ENDIAN
|
||||||
if (!stream_be)
|
if (!stream_be)
|
||||||
@ -260,7 +262,7 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
|
|||||||
{
|
{
|
||||||
logger(Sound, Warning,
|
logger(Sound, Warning,
|
||||||
"rdpsndp_dsp_resample_set(), no sample rate converter available");
|
"rdpsndp_dsp_resample_set(), no sample rate converter available");
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
outnum = ((float) innum * ((float) resample_to_srate / (float) format->nSamplesPerSec)) + 1;
|
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);
|
xfree(infloat);
|
||||||
|
|
||||||
outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
|
outsize = resample_data.output_frames_gen * resample_to_channels * samplewidth;
|
||||||
*out = (unsigned char *) xmalloc(outsize);
|
out = s_alloc(outsize);
|
||||||
src_float_to_short_array(outfloat, (short *) *out,
|
out_uint8p(out, data, outsize);
|
||||||
|
src_float_to_short_array(outfloat, (short *) data,
|
||||||
resample_data.output_frames_gen * resample_to_channels);
|
resample_data.output_frames_gen * resample_to_channels);
|
||||||
xfree(outfloat);
|
xfree(outfloat);
|
||||||
|
|
||||||
@ -302,8 +305,9 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
|
|||||||
outnum = (innum * ratio1k) / 1000;
|
outnum = (innum * ratio1k) / 1000;
|
||||||
|
|
||||||
outsize = outnum * samplewidth;
|
outsize = outnum * samplewidth;
|
||||||
*out = (unsigned char *) xmalloc(outsize);
|
out = s_alloc(outsize);
|
||||||
bzero(*out, outsize);
|
out_uint8p(out, data, outsize);
|
||||||
|
bzero(data, outsize);
|
||||||
|
|
||||||
for (i = 0; i < outsize / (resample_to_channels * samplewidth); i++)
|
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;
|
cval1 += (sint8) (cval2 * part) / 100;
|
||||||
|
|
||||||
memcpy(*out + (i * resample_to_channels * samplewidth) +
|
memcpy(data + (i * resample_to_channels * samplewidth) +
|
||||||
(samplewidth * j), &cval1, 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;
|
sval1 += (sint16) (sval2 * part) / 100;
|
||||||
|
|
||||||
memcpy(*out + (i * resample_to_channels * samplewidth) +
|
memcpy(data + (i * resample_to_channels * samplewidth) +
|
||||||
(samplewidth * j), &sval1, samplewidth);
|
(samplewidth * j), &sval1, samplewidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* Nearest neighbor search */
|
#else /* Nearest neighbor search */
|
||||||
for (j = 0; j < resample_to_channels; j++)
|
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) +
|
in + (source * resample_to_channels * samplewidth) +
|
||||||
(samplewidth * j), 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++)
|
for (i = 0; i < outsize; i++)
|
||||||
{
|
{
|
||||||
*out[i] = *out[i * 2];
|
data[i] = data[i * 2];
|
||||||
}
|
}
|
||||||
outsize /= 2;
|
outsize /= 2;
|
||||||
}
|
}
|
||||||
@ -386,16 +390,17 @@ rdpsnd_dsp_resample(unsigned char **out, unsigned char *in, unsigned int size,
|
|||||||
|
|
||||||
#ifdef B_ENDIAN
|
#ifdef B_ENDIAN
|
||||||
if (!stream_be)
|
if (!stream_be)
|
||||||
rdpsnd_dsp_swapbytes(*out, outsize, format);
|
rdpsnd_dsp_swapbytes(data, outsize, format);
|
||||||
#endif
|
#endif
|
||||||
return outsize;
|
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
STREAM
|
STREAM
|
||||||
rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
|
rdpsnd_dsp_process(unsigned char *data, unsigned int size, struct audio_driver * current_driver,
|
||||||
RD_WAVEFORMATEX * format)
|
RD_WAVEFORMATEX * format)
|
||||||
{
|
{
|
||||||
static struct stream out;
|
STREAM out;
|
||||||
RD_BOOL stream_be = False;
|
RD_BOOL stream_be = False;
|
||||||
|
|
||||||
/* softvol and byteswap do not change the amount of data they
|
/* 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
|
#endif
|
||||||
|
|
||||||
out.data = NULL;
|
out = NULL;
|
||||||
|
|
||||||
if (current_driver->need_resampling)
|
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);
|
out = s_alloc(size);
|
||||||
memcpy(out.data, data, size);
|
out_uint8a(out, data, size);
|
||||||
out.size = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out.p = out.data;
|
s_mark_end(out);
|
||||||
out.end = out.p + out.size;
|
s_seek(out, 0);
|
||||||
|
|
||||||
return &out;
|
return out;
|
||||||
}
|
}
|
||||||
|
@ -148,6 +148,7 @@ libao_play(void)
|
|||||||
{
|
{
|
||||||
struct audio_packet *packet;
|
struct audio_packet *packet;
|
||||||
STREAM out;
|
STREAM out;
|
||||||
|
unsigned char *data;
|
||||||
int len;
|
int len;
|
||||||
static long prev_s, prev_us;
|
static long prev_s, prev_us;
|
||||||
int duration;
|
int duration;
|
||||||
@ -167,13 +168,13 @@ libao_play(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
packet = rdpsnd_queue_current_packet();
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = packet->s;
|
||||||
|
|
||||||
next_tick = rdpsnd_queue_next_tick();
|
next_tick = rdpsnd_queue_next_tick();
|
||||||
|
|
||||||
len = (WAVEOUTLEN > (out->end - out->p)) ? (out->end - out->p) : WAVEOUTLEN;
|
len = MIN(WAVEOUTLEN, s_remaining(out));
|
||||||
ao_play(o_device, (char *) out->p, len);
|
in_uint8p(out, data, len);
|
||||||
out->p += len;
|
ao_play(o_device, (char *) data, len);
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
|
|
||||||
@ -182,7 +183,7 @@ libao_play(void)
|
|||||||
if (packet->tick > next_tick)
|
if (packet->tick > next_tick)
|
||||||
next_tick += 65536;
|
next_tick += 65536;
|
||||||
|
|
||||||
if ((out->p == out->end) || duration > next_tick - packet->tick + 500)
|
if (s_check_end(out) || duration > next_tick - packet->tick + 500)
|
||||||
{
|
{
|
||||||
unsigned int delay_us;
|
unsigned int delay_us;
|
||||||
|
|
||||||
|
16
rdpsnd_oss.c
16
rdpsnd_oss.c
@ -402,6 +402,8 @@ oss_play(void)
|
|||||||
struct audio_packet *packet;
|
struct audio_packet *packet;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
STREAM out;
|
STREAM out;
|
||||||
|
size_t before;
|
||||||
|
const unsigned char *data;
|
||||||
|
|
||||||
assert(dsp_fd != -1);
|
assert(dsp_fd != -1);
|
||||||
|
|
||||||
@ -410,11 +412,14 @@ oss_play(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
packet = rdpsnd_queue_current_packet();
|
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 (len == -1)
|
||||||
{
|
{
|
||||||
if (errno != EWOULDBLOCK)
|
if (errno != EWOULDBLOCK)
|
||||||
@ -429,9 +434,10 @@ oss_play(void)
|
|||||||
|
|
||||||
dsp_broken = False;
|
dsp_broken = False;
|
||||||
|
|
||||||
out->p += len;
|
/* We might not have written everything */
|
||||||
|
s_seek(out, before + len);
|
||||||
|
|
||||||
if (out->p == out->end)
|
if (s_check_end(out))
|
||||||
{
|
{
|
||||||
int delay_bytes;
|
int delay_bytes;
|
||||||
unsigned long delay_us;
|
unsigned long delay_us;
|
||||||
|
@ -1154,7 +1154,7 @@ pulse_play(void)
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
packet = rdpsnd_queue_current_packet();
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = packet->s;
|
||||||
|
|
||||||
ti = pa_stream_get_timing_info(playback_stream);
|
ti = pa_stream_get_timing_info(playback_stream);
|
||||||
if (ti == NULL)
|
if (ti == NULL)
|
||||||
@ -1192,11 +1192,14 @@ pulse_play(void)
|
|||||||
playback_seek = PA_SEEK_RELATIVE;
|
playback_seek = PA_SEEK_RELATIVE;
|
||||||
|
|
||||||
avail_space = pa_stream_writable_size(playback_stream);
|
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)
|
if (audio_size)
|
||||||
{
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
|
in_uint8p(out, data, audio_size);
|
||||||
if (pa_stream_write
|
if (pa_stream_write
|
||||||
(playback_stream, out->p, audio_size, NULL, 0, playback_seek) != 0)
|
(playback_stream, data, audio_size, NULL, 0, playback_seek) != 0)
|
||||||
{
|
{
|
||||||
err = pa_context_errno(context);
|
err = pa_context_errno(context);
|
||||||
logger(Sound, Error, "pulse_play(), pa_stream_write: %s",
|
logger(Sound, Error, "pulse_play(), pa_stream_write: %s",
|
||||||
@ -1207,9 +1210,7 @@ pulse_play(void)
|
|||||||
playback_seek = PA_SEEK_RELATIVE;
|
playback_seek = PA_SEEK_RELATIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->p += audio_size;
|
if (s_check_end(out))
|
||||||
|
|
||||||
if (out->p == out->end)
|
|
||||||
{
|
{
|
||||||
ret = pa_stream_get_latency(playback_stream, &delay, NULL);
|
ret = pa_stream_get_latency(playback_stream, &delay, NULL);
|
||||||
if (ret != 0 && (err = pa_context_errno(context)) == PA_ERR_NODATA)
|
if (ret != 0 && (err = pa_context_errno(context)) == PA_ERR_NODATA)
|
||||||
@ -1251,7 +1252,7 @@ pulse_play(void)
|
|||||||
|
|
||||||
pa_threaded_mainloop_unlock(mainloop);
|
pa_threaded_mainloop_unlock(mainloop);
|
||||||
|
|
||||||
if (out->p == out->end)
|
if (s_check_end(out))
|
||||||
rdpsnd_queue_next(delay);
|
rdpsnd_queue_next(delay);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
11
rdpsnd_sgi.c
11
rdpsnd_sgi.c
@ -246,6 +246,7 @@ sgi_play(void)
|
|||||||
struct audio_packet *packet;
|
struct audio_packet *packet;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
STREAM out;
|
STREAM out;
|
||||||
|
unsigned char *data;
|
||||||
int gf;
|
int gf;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -254,14 +255,14 @@ sgi_play(void)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
packet = rdpsnd_queue_current_packet();
|
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 (s_check_end(out))
|
||||||
if (out->p == out->end)
|
|
||||||
{
|
{
|
||||||
gf = alGetFilled(output_port);
|
gf = alGetFilled(output_port);
|
||||||
if (gf < (4 * maxFillable / 10))
|
if (gf < (4 * maxFillable / 10))
|
||||||
|
16
rdpsnd_sun.c
16
rdpsnd_sun.c
@ -411,17 +411,22 @@ sun_play(void)
|
|||||||
struct audio_packet *packet;
|
struct audio_packet *packet;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
STREAM out;
|
STREAM out;
|
||||||
|
size_t before;
|
||||||
|
const unsigned char *data;
|
||||||
|
|
||||||
/* We shouldn't be called if the queue is empty, but still */
|
/* We shouldn't be called if the queue is empty, but still */
|
||||||
if (rdpsnd_queue_empty())
|
if (rdpsnd_queue_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
packet = rdpsnd_queue_current_packet();
|
packet = rdpsnd_queue_current_packet();
|
||||||
out = &packet->s;
|
out = packet->s;
|
||||||
|
|
||||||
len = 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 (len == -1)
|
||||||
{
|
{
|
||||||
if (errno != EWOULDBLOCK)
|
if (errno != EWOULDBLOCK)
|
||||||
@ -439,9 +444,10 @@ sun_play(void)
|
|||||||
|
|
||||||
dsp_broken = False;
|
dsp_broken = False;
|
||||||
|
|
||||||
out->p += len;
|
/* We might not have written everything */
|
||||||
|
s_seek(out, before + len);
|
||||||
|
|
||||||
if (out->p == out->end)
|
if (s_check_end(out))
|
||||||
{
|
{
|
||||||
audio_info_t info;
|
audio_info_t info;
|
||||||
uint_t delay_samples;
|
uint_t delay_samples;
|
||||||
|
191
scard.c
191
scard.c
@ -237,10 +237,8 @@ scard_enum_devices(uint32 * id, char *optarg)
|
|||||||
|
|
||||||
tmpMap = nameMapList + nameMapCount - 1;
|
tmpMap = nameMapList + nameMapCount - 1;
|
||||||
|
|
||||||
len = strlen(alias);
|
STRNCPY(tmpMap->alias, alias, sizeof(tmpMap->alias));
|
||||||
strncpy(tmpMap->alias, alias, (len > 127) ? (127) : (len));
|
STRNCPY(tmpMap->name, name, sizeof(tmpMap->name));
|
||||||
len = strlen(name);
|
|
||||||
strncpy(tmpMap->name, name, (len > 127) ? (127) : (len));
|
|
||||||
|
|
||||||
if (vendor)
|
if (vendor)
|
||||||
{
|
{
|
||||||
@ -248,8 +246,8 @@ scard_enum_devices(uint32 * id, char *optarg)
|
|||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
memset(tmpMap->vendor, 0, 128);
|
memset(tmpMap->vendor, 0, 128);
|
||||||
strncpy(tmpMap->vendor, vendor,
|
STRNCPY(tmpMap->vendor, vendor,
|
||||||
(len > 127) ? (127) : (len));
|
sizeof(tmpMap->vendor));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmpMap->vendor[0] = '\0';
|
tmpMap->vendor[0] = '\0';
|
||||||
@ -550,7 +548,7 @@ outBufferFinishWithLimit(STREAM out, char *buffer, unsigned int length, unsigned
|
|||||||
{
|
{
|
||||||
if (header < length)
|
if (header < length)
|
||||||
length = header;
|
length = header;
|
||||||
out_uint8p(out, buffer, length);
|
out_uint8a(out, buffer, length);
|
||||||
outRepos(out, length);
|
outRepos(out, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,7 +562,7 @@ outBufferFinish(STREAM out, char *buffer, unsigned int length)
|
|||||||
static void
|
static void
|
||||||
outForceAlignment(STREAM out, unsigned int seed)
|
outForceAlignment(STREAM out, unsigned int seed)
|
||||||
{
|
{
|
||||||
SERVER_DWORD add = (seed - (out->p - out->data) % seed) % seed;
|
SERVER_DWORD add = (seed - s_tell(out) % seed) % seed;
|
||||||
if (add > 0)
|
if (add > 0)
|
||||||
out_uint8s(out, add);
|
out_uint8s(out, add);
|
||||||
}
|
}
|
||||||
@ -626,11 +624,11 @@ outString(STREAM out, char *source, RD_BOOL wide)
|
|||||||
buffer[2 * i] = reader[i];
|
buffer[2 * i] = reader[i];
|
||||||
buffer[2 * i + 1] = '\0';
|
buffer[2 * i + 1] = '\0';
|
||||||
}
|
}
|
||||||
out_uint8p(out, buffer, 2 * dataLength);
|
out_uint8a(out, buffer, 2 * dataLength);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_uint8p(out, reader, dataLength);
|
out_uint8a(out, reader, dataLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
@ -641,7 +639,7 @@ static void
|
|||||||
inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
|
inReaderName(PMEM_HANDLE * handle, STREAM in, char **destination, RD_BOOL wide)
|
||||||
{
|
{
|
||||||
SERVER_DWORD dataLength;
|
SERVER_DWORD dataLength;
|
||||||
in->p += 0x08;
|
in_uint8s(in, 0x08);
|
||||||
in_uint32_le(in, dataLength);
|
in_uint32_le(in, dataLength);
|
||||||
inRepos(in, inString(handle, in, destination, dataLength, wide));
|
inRepos(in, inString(handle, in, destination, dataLength, wide));
|
||||||
}
|
}
|
||||||
@ -719,6 +717,7 @@ TS_SCardEstablishContext(STREAM in, STREAM out)
|
|||||||
out_uint32_le(out, 0x00000004);
|
out_uint32_le(out, 0x00000004);
|
||||||
out_uint32_le(out, hContext);
|
out_uint32_le(out, hContext);
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,7 +728,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out)
|
|||||||
MYPCSC_SCARDCONTEXT myHContext;
|
MYPCSC_SCARDCONTEXT myHContext;
|
||||||
SERVER_SCARDCONTEXT hContext;
|
SERVER_SCARDCONTEXT hContext;
|
||||||
|
|
||||||
in->p += 0x1C;
|
in_uint8s(in, 0x1C);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
|
|
||||||
@ -754,6 +753,7 @@ TS_SCardReleaseContext(STREAM in, STREAM out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,7 +764,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out)
|
|||||||
SERVER_SCARDCONTEXT hContext;
|
SERVER_SCARDCONTEXT hContext;
|
||||||
MYPCSC_SCARDCONTEXT myHContext;
|
MYPCSC_SCARDCONTEXT myHContext;
|
||||||
|
|
||||||
in->p += 0x1C;
|
in_uint8s(in, 0x1C);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
@ -788,6 +788,7 @@ TS_SCardIsValidContext(STREAM in, STREAM out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,21 +802,21 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
MYPCSC_SCARDCONTEXT myHContext;
|
MYPCSC_SCARDCONTEXT myHContext;
|
||||||
SERVER_DWORD dataLength;
|
SERVER_DWORD dataLength;
|
||||||
MYPCSC_DWORD cchReaders = readerArraySize;
|
MYPCSC_DWORD cchReaders = readerArraySize;
|
||||||
unsigned char *plen1, *plen2, *pend;
|
size_t plen1, plen2, pend;
|
||||||
char *readers, *cur;
|
char *readers, *cur;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x2C;
|
in_uint8s(in, 0x2C);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
|
|
||||||
logger(SmartCard, Debug, "TS_SCardListReaders(), context: 0x%08x [0x%lx])",
|
logger(SmartCard, Debug, "TS_SCardListReaders(), context: 0x%08x [0x%lx])",
|
||||||
(unsigned) hContext, myHContext);
|
(unsigned) hContext, myHContext);
|
||||||
|
|
||||||
plen1 = out->p;
|
plen1 = s_tell(out);
|
||||||
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
||||||
out_uint32_le(out, 0x01760650);
|
out_uint32_le(out, 0x01760650);
|
||||||
plen2 = out->p;
|
plen2 = s_tell(out);
|
||||||
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
out_uint32_le(out, 0x00000000); /* Temp value for data length as 0x0 */
|
||||||
|
|
||||||
dataLength = 0;
|
dataLength = 0;
|
||||||
@ -865,14 +866,17 @@ TS_SCardListReaders(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
dataLength += outString(out, "\0", wide);
|
dataLength += outString(out, "\0", wide);
|
||||||
outRepos(out, dataLength);
|
outRepos(out, dataLength);
|
||||||
|
|
||||||
pend = out->p;
|
s_mark_end(out);
|
||||||
out->p = plen1;
|
|
||||||
|
pend = s_tell(out);
|
||||||
|
s_seek(out, plen1);
|
||||||
out_uint32_le(out, dataLength);
|
out_uint32_le(out, dataLength);
|
||||||
out->p = plen2;
|
s_seek(out, plen2);
|
||||||
out_uint32_le(out, dataLength);
|
out_uint32_le(out, dataLength);
|
||||||
out->p = pend;
|
s_seek(out, pend);
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -893,11 +897,11 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
MYPCSC_DWORD dwActiveProtocol;
|
MYPCSC_DWORD dwActiveProtocol;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x1C;
|
in_uint8s(in, 0x1C);
|
||||||
in_uint32_le(in, dwShareMode);
|
in_uint32_le(in, dwShareMode);
|
||||||
in_uint32_le(in, dwPreferredProtocol);
|
in_uint32_le(in, dwPreferredProtocol);
|
||||||
inReaderName(&lcHandle, in, &szReader, wide);
|
inReaderName(&lcHandle, in, &szReader, wide);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
@ -968,6 +972,7 @@ TS_SCardConnect(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
out_uint32_le(out, hCard);
|
out_uint32_le(out, hCard);
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -984,13 +989,13 @@ TS_SCardReconnect(STREAM in, STREAM out)
|
|||||||
SERVER_DWORD dwInitialization;
|
SERVER_DWORD dwInitialization;
|
||||||
MYPCSC_DWORD dwActiveProtocol;
|
MYPCSC_DWORD dwActiveProtocol;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwShareMode);
|
in_uint32_le(in, dwShareMode);
|
||||||
in_uint32_le(in, dwPreferredProtocol);
|
in_uint32_le(in, dwPreferredProtocol);
|
||||||
in_uint32_le(in, dwInitialization);
|
in_uint32_le(in, dwInitialization);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
|
|
||||||
|
|
||||||
@ -1016,6 +1021,7 @@ TS_SCardReconnect(STREAM in, STREAM out)
|
|||||||
|
|
||||||
out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
|
out_uint32_le(out, (SERVER_DWORD) dwActiveProtocol);
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,11 +1035,11 @@ TS_SCardDisconnect(STREAM in, STREAM out)
|
|||||||
MYPCSC_SCARDHANDLE myHCard;
|
MYPCSC_SCARDHANDLE myHCard;
|
||||||
SERVER_DWORD dwDisposition;
|
SERVER_DWORD dwDisposition;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwDisposition);
|
in_uint32_le(in, dwDisposition);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
@ -1078,6 +1084,7 @@ TS_SCardDisconnect(STREAM in, STREAM out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,12 +1171,12 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
long i;
|
long i;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x18;
|
in_uint8s(in, 0x18);
|
||||||
in_uint32_le(in, dwTimeout);
|
in_uint32_le(in, dwTimeout);
|
||||||
in_uint32_le(in, dwCount);
|
in_uint32_le(in, dwCount);
|
||||||
in->p += 0x08;
|
in_uint8s(in, 0x08);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
|
|
||||||
@ -1199,7 +1206,7 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
{
|
{
|
||||||
SERVER_DWORD dataLength;
|
SERVER_DWORD dataLength;
|
||||||
|
|
||||||
in->p += 0x08;
|
in_uint8s(in, 0x08);
|
||||||
in_uint32_le(in, dataLength);
|
in_uint32_le(in, dataLength);
|
||||||
inRepos(in,
|
inRepos(in,
|
||||||
inString(&lcHandle, in, (char **) &(cur->szReader),
|
inString(&lcHandle, in, (char **) &(cur->szReader),
|
||||||
@ -1257,10 +1264,11 @@ TS_SCardGetStatusChange(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
cur->dwEventState = swap32(cur->dwEventState);
|
cur->dwEventState = swap32(cur->dwEventState);
|
||||||
cur->cbAtr = swap32(cur->cbAtr);
|
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 *));
|
sizeof(SERVER_SCARD_READERSTATE_A) - 2 * sizeof(unsigned char *));
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1272,7 +1280,7 @@ TS_SCardCancel(STREAM in, STREAM out)
|
|||||||
SERVER_SCARDCONTEXT hContext;
|
SERVER_SCARDCONTEXT hContext;
|
||||||
MYPCSC_SCARDCONTEXT myHContext;
|
MYPCSC_SCARDCONTEXT myHContext;
|
||||||
|
|
||||||
in->p += 0x1C;
|
in_uint8s(in, 0x1C);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
@ -1291,6 +1299,7 @@ TS_SCardCancel(STREAM in, STREAM out)
|
|||||||
logger(SmartCard, Debug, "TS_SCardCancel(), success");
|
logger(SmartCard, Debug, "TS_SCardCancel(), success");
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1311,7 +1320,7 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
MYPCSC_LPSCARD_READERSTATE_A myRsArray;
|
MYPCSC_LPSCARD_READERSTATE_A myRsArray;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x2C;
|
in_uint8s(in, 0x2C);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
in_uint32_le(in, atrMaskCount);
|
in_uint32_le(in, atrMaskCount);
|
||||||
pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
|
pAtrMasks = SC_xmalloc(&lcHandle, atrMaskCount * sizeof(SCARD_ATRMASK_L));
|
||||||
@ -1421,11 +1430,12 @@ TS_SCardLocateCardsByATR(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
rsCur->dwEventState = swap32(rsCur->dwEventState);
|
rsCur->dwEventState = swap32(rsCur->dwEventState);
|
||||||
rsCur->cbAtr = swap32(rsCur->cbAtr);
|
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 *));
|
sizeof(SCARD_READERSTATE) - 2 * sizeof(unsigned char *));
|
||||||
}
|
}
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1437,7 +1447,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out)
|
|||||||
SERVER_SCARDCONTEXT hCard;
|
SERVER_SCARDCONTEXT hCard;
|
||||||
MYPCSC_SCARDCONTEXT myHCard;
|
MYPCSC_SCARDCONTEXT myHCard;
|
||||||
|
|
||||||
in->p += 0x30;
|
in_uint8s(in, 0x30);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), hcard: 0x%08x [0x%lx])",
|
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), hcard: 0x%08x [0x%lx])",
|
||||||
@ -1453,6 +1463,7 @@ TS_SCardBeginTransaction(STREAM in, STREAM out)
|
|||||||
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), success");
|
logger(SmartCard, Debug, "TS_SCardBeginTransaction(), success");
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1464,9 +1475,9 @@ TS_SCardEndTransaction(STREAM in, STREAM out)
|
|||||||
MYPCSC_SCARDCONTEXT myHCard;
|
MYPCSC_SCARDCONTEXT myHCard;
|
||||||
SERVER_DWORD dwDisposition = 0;
|
SERVER_DWORD dwDisposition = 0;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwDisposition);
|
in_uint32_le(in, dwDisposition);
|
||||||
in->p += 0x0C;
|
in_uint8s(in, 0x0C);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
|
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
@ -1485,6 +1496,7 @@ TS_SCardEndTransaction(STREAM in, STREAM out)
|
|||||||
logger(SmartCard, Debug, "TS_SCardEndTransaction(), success");
|
logger(SmartCard, Debug, "TS_SCardEndTransaction(), success");
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1533,9 +1545,9 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
|
|||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
|
|
||||||
in->p += 0x14;
|
in_uint8s(in, 0x14);
|
||||||
in_uint32_le(in, map[0]);
|
in_uint32_le(in, map[0]);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, map[1]);
|
in_uint32_le(in, map[1]);
|
||||||
pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
|
pioSendPci = SC_xmalloc(&lcHandle, sizeof(SERVER_SCARD_IO_REQUEST));
|
||||||
if (!pioSendPci)
|
if (!pioSendPci)
|
||||||
@ -1553,7 +1565,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
|
|||||||
if (srv_buf_len <= cbRecvLength)
|
if (srv_buf_len <= cbRecvLength)
|
||||||
cbRecvLength = srv_buf_len;
|
cbRecvLength = srv_buf_len;
|
||||||
|
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
|
|
||||||
@ -1697,6 +1709,7 @@ TS_SCardTransmit(STREAM in, STREAM out, uint32 srv_buf_len)
|
|||||||
outBufferFinish(out, (char *) recvBuf, cbRecvLength);
|
outBufferFinish(out, (char *) recvBuf, cbRecvLength);
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1714,12 +1727,12 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
char *readerName;
|
char *readerName;
|
||||||
unsigned char *atr;
|
unsigned char *atr;
|
||||||
|
|
||||||
in->p += 0x24;
|
in_uint8s(in, 0x24);
|
||||||
in_uint32_le(in, dwReaderLen);
|
in_uint32_le(in, dwReaderLen);
|
||||||
in_uint32_le(in, dwAtrLen);
|
in_uint32_le(in, dwAtrLen);
|
||||||
in->p += 0x0C;
|
in_uint8s(in, 0x0C);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
logger(SmartCard, Debug,
|
logger(SmartCard, Debug,
|
||||||
"TS_SCardStatus(), hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes",
|
"TS_SCardStatus(), hcard: 0x%08x [0x%08lx], reader len: %d bytes, atr len: %d bytes",
|
||||||
@ -1792,31 +1805,33 @@ TS_SCardStatus(STREAM in, STREAM out, RD_BOOL wide)
|
|||||||
else
|
else
|
||||||
dwState = 0x00000000;
|
dwState = 0x00000000;
|
||||||
|
|
||||||
void *p_len1 = out->p;
|
size_t p_len1 = s_tell(out);
|
||||||
out_uint32_le(out, dwReaderLen);
|
out_uint32_le(out, dwReaderLen);
|
||||||
out_uint32_le(out, 0x00020000);
|
out_uint32_le(out, 0x00020000);
|
||||||
out_uint32_le(out, dwState);
|
out_uint32_le(out, dwState);
|
||||||
out_uint32_le(out, dwProtocol);
|
out_uint32_le(out, dwProtocol);
|
||||||
out_uint8p(out, atr, dwAtrLen);
|
out_uint8a(out, atr, dwAtrLen);
|
||||||
if (dwAtrLen < 32)
|
if (dwAtrLen < 32)
|
||||||
{
|
{
|
||||||
out_uint8s(out, 32 - dwAtrLen);
|
out_uint8s(out, 32 - dwAtrLen);
|
||||||
}
|
}
|
||||||
out_uint32_le(out, dwAtrLen);
|
out_uint32_le(out, dwAtrLen);
|
||||||
|
|
||||||
void *p_len2 = out->p;
|
size_t p_len2 = s_tell(out);
|
||||||
out_uint32_le(out, dwReaderLen);
|
out_uint32_le(out, dwReaderLen);
|
||||||
dataLength = outString(out, readerName, wide);
|
dataLength = outString(out, readerName, wide);
|
||||||
dataLength += outString(out, "\0", wide);
|
dataLength += outString(out, "\0", wide);
|
||||||
outRepos(out, dataLength);
|
outRepos(out, dataLength);
|
||||||
void *psave = out->p;
|
s_mark_end(out);
|
||||||
out->p = p_len1;
|
size_t psave = s_tell(out);
|
||||||
|
s_seek(out, p_len1);
|
||||||
out_uint32_le(out, dataLength);
|
out_uint32_le(out, dataLength);
|
||||||
out->p = p_len2;
|
s_seek(out, p_len2);
|
||||||
out_uint32_le(out, dataLength);
|
out_uint32_le(out, dataLength);
|
||||||
out->p = psave;
|
s_seek(out, psave);
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1833,11 +1848,11 @@ TS_SCardState(STREAM in, STREAM out)
|
|||||||
char *readerName;
|
char *readerName;
|
||||||
unsigned char *atr;
|
unsigned char *atr;
|
||||||
|
|
||||||
in->p += 0x24;
|
in_uint8s(in, 0x24);
|
||||||
in_uint32_le(in, dwAtrLen);
|
in_uint32_le(in, dwAtrLen);
|
||||||
in->p += 0x0C;
|
in_uint8s(in, 0x0C);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
|
|
||||||
logger(SmartCard, Debug, "TS_SCardState(), hcard: 0x%08x [0x%08lx], atrlen: %d bytes",
|
logger(SmartCard, Debug, "TS_SCardState(), hcard: 0x%08x [0x%08lx], atrlen: %d bytes",
|
||||||
@ -1903,10 +1918,11 @@ TS_SCardState(STREAM in, STREAM out)
|
|||||||
out_uint32_le(out, dwAtrLen);
|
out_uint32_le(out, dwAtrLen);
|
||||||
out_uint32_le(out, 0x00000001);
|
out_uint32_le(out, 0x00000001);
|
||||||
out_uint32_le(out, dwAtrLen);
|
out_uint32_le(out, dwAtrLen);
|
||||||
out_uint8p(out, atr, dwAtrLen);
|
out_uint8a(out, atr, dwAtrLen);
|
||||||
outRepos(out, dwAtrLen);
|
outRepos(out, dwAtrLen);
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1928,9 +1944,9 @@ TS_SCardListReaderGroups(STREAM in, STREAM out)
|
|||||||
char *szGroups;
|
char *szGroups;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwGroups);
|
in_uint32_le(in, dwGroups);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
|
|
||||||
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
myHContext = _scard_handle_list_get_pcsc_handle(hContext);
|
||||||
@ -1976,6 +1992,7 @@ TS_SCardListReaderGroups(STREAM in, STREAM out)
|
|||||||
out_uint32_le(out, 0x00000000);
|
out_uint32_le(out, 0x00000000);
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -1992,11 +2009,11 @@ TS_SCardGetAttrib(STREAM in, STREAM out)
|
|||||||
unsigned char *pbAttr;
|
unsigned char *pbAttr;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwAttrId);
|
in_uint32_le(in, dwAttrId);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, dwAttrLen);
|
in_uint32_le(in, dwAttrLen);
|
||||||
in->p += 0x0C;
|
in_uint8s(in, 0x0C);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
myHCard = _scard_handle_list_get_pcsc_handle(hCard);
|
||||||
|
|
||||||
@ -2040,12 +2057,13 @@ TS_SCardGetAttrib(STREAM in, STREAM out)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_uint8p(out, pbAttr, dwAttrLen);
|
out_uint8a(out, pbAttr, dwAttrLen);
|
||||||
}
|
}
|
||||||
outRepos(out, dwAttrLen);
|
outRepos(out, dwAttrLen);
|
||||||
out_uint32_le(out, 0x00000000);
|
out_uint32_le(out, 0x00000000);
|
||||||
}
|
}
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2062,11 +2080,11 @@ TS_SCardSetAttrib(STREAM in, STREAM out)
|
|||||||
unsigned char *pbAttr;
|
unsigned char *pbAttr;
|
||||||
PMEM_HANDLE lcHandle = NULL;
|
PMEM_HANDLE lcHandle = NULL;
|
||||||
|
|
||||||
in->p += 0x20;
|
in_uint8s(in, 0x20);
|
||||||
in_uint32_le(in, dwAttrId);
|
in_uint32_le(in, dwAttrId);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, dwAttrLen);
|
in_uint32_le(in, dwAttrLen);
|
||||||
in->p += 0x0C;
|
in_uint8s(in, 0x0C);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
myHCard = scHandleToMyPCSC(hCard);
|
myHCard = scHandleToMyPCSC(hCard);
|
||||||
|
|
||||||
@ -2100,6 +2118,7 @@ TS_SCardSetAttrib(STREAM in, STREAM out)
|
|||||||
out_uint32_le(out, 0x00000000);
|
out_uint32_le(out, 0x00000000);
|
||||||
out_uint32_le(out, 0x00000000);
|
out_uint32_le(out, 0x00000000);
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2125,18 +2144,18 @@ TS_SCardControl(STREAM in, STREAM out)
|
|||||||
pInBuffer = NULL;
|
pInBuffer = NULL;
|
||||||
pOutBuffer = NULL;
|
pOutBuffer = NULL;
|
||||||
|
|
||||||
in->p += 0x14;
|
in_uint8s(in, 0x14);
|
||||||
in_uint32_le(in, map[0]);
|
in_uint32_le(in, map[0]);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, map[1]);
|
in_uint32_le(in, map[1]);
|
||||||
in_uint32_le(in, dwControlCode);
|
in_uint32_le(in, dwControlCode);
|
||||||
in_uint32_le(in, nInBufferSize);
|
in_uint32_le(in, nInBufferSize);
|
||||||
in_uint32_le(in, map[2]);
|
in_uint32_le(in, map[2]);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, nOutBufferSize);
|
in_uint32_le(in, nOutBufferSize);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hContext);
|
in_uint32_le(in, hContext);
|
||||||
in->p += 0x04;
|
in_uint8s(in, 0x04);
|
||||||
in_uint32_le(in, hCard);
|
in_uint32_le(in, hCard);
|
||||||
if (map[2] & INPUT_LINKED)
|
if (map[2] & INPUT_LINKED)
|
||||||
{
|
{
|
||||||
@ -2238,11 +2257,12 @@ TS_SCardControl(STREAM in, STREAM out)
|
|||||||
out_uint32_le(out, nBytesReturned);
|
out_uint32_le(out, nBytesReturned);
|
||||||
if (nBytesReturned > 0)
|
if (nBytesReturned > 0)
|
||||||
{
|
{
|
||||||
out_uint8p(out, pOutBuffer, nBytesReturned);
|
out_uint8a(out, pOutBuffer, nBytesReturned);
|
||||||
outRepos(out, nBytesReturned);
|
outRepos(out, nBytesReturned);
|
||||||
}
|
}
|
||||||
|
|
||||||
outForceAlignment(out, 8);
|
outForceAlignment(out, 8);
|
||||||
|
s_mark_end(out);
|
||||||
SC_xfreeallmemory(&lcHandle);
|
SC_xfreeallmemory(&lcHandle);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -2262,7 +2282,7 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
|
|||||||
{
|
{
|
||||||
UNUSED(handle);
|
UNUSED(handle);
|
||||||
SERVER_DWORD Result = 0x00000000;
|
SERVER_DWORD Result = 0x00000000;
|
||||||
unsigned char *psize, *pend, *pStatusCode;
|
size_t psize, pend, pStatusCode;
|
||||||
SERVER_DWORD addToEnd = 0;
|
SERVER_DWORD addToEnd = 0;
|
||||||
|
|
||||||
/* Processing request */
|
/* Processing request */
|
||||||
@ -2272,11 +2292,11 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
|
|||||||
/* Set CommonTypeHeader (MS-RPCE 2.2.6.1) */
|
/* Set CommonTypeHeader (MS-RPCE 2.2.6.1) */
|
||||||
out_uint32_le(out, 0x00081001); /* Header lines */
|
out_uint32_le(out, 0x00081001); /* Header lines */
|
||||||
out_uint32_le(out, 0xCCCCCCCC);
|
out_uint32_le(out, 0xCCCCCCCC);
|
||||||
psize = out->p;
|
psize = s_tell(out);
|
||||||
/* Set PrivateTypeHeader (MS-RPCE 2.2.6.2) */
|
/* Set PrivateTypeHeader (MS-RPCE 2.2.6.2) */
|
||||||
out_uint32_le(out, 0x00000000); /* Size of data portion */
|
out_uint32_le(out, 0x00000000); /* Size of data portion */
|
||||||
out_uint32_le(out, 0x00000000); /* Zero bytes (may be useful) */
|
out_uint32_le(out, 0x00000000); /* Zero bytes (may be useful) */
|
||||||
pStatusCode = out->p;
|
pStatusCode = s_tell(out);
|
||||||
out_uint32_le(out, 0x00000000); /* Status Code */
|
out_uint32_le(out, 0x00000000); /* Status Code */
|
||||||
|
|
||||||
switch (request)
|
switch (request)
|
||||||
@ -2412,22 +2432,25 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
|
|||||||
#if 0
|
#if 0
|
||||||
out_uint32_le(out, 0x00000000);
|
out_uint32_le(out, 0x00000000);
|
||||||
#endif
|
#endif
|
||||||
|
s_mark_end(out);
|
||||||
|
|
||||||
/* Setting modified variables */
|
/* Setting modified variables */
|
||||||
pend = out->p;
|
pend = s_tell(out);
|
||||||
/* setting data size */
|
/* setting data size */
|
||||||
out->p = psize;
|
s_seek(out, psize);
|
||||||
out_uint32_le(out, pend - psize - 16);
|
out_uint32_le(out, pend - psize - 16);
|
||||||
/* setting status code */
|
/* setting status code */
|
||||||
out->p = pStatusCode;
|
s_seek(out, pStatusCode);
|
||||||
out_uint32_le(out, Result);
|
out_uint32_le(out, Result);
|
||||||
/* finish */
|
/* finish */
|
||||||
out->p = pend;
|
s_seek(out, pend);
|
||||||
|
|
||||||
/* TODO: Check MS-RPCE 2.2.6.2 for alignment requirements (IIRC length must be integral multiple of 8) */
|
/* TODO: Check MS-RPCE 2.2.6.2 for alignment requirements (IIRC length must be integral multiple of 8) */
|
||||||
addToEnd = (pend - pStatusCode) % 16;
|
addToEnd = (pend - pStatusCode) % 16;
|
||||||
if (addToEnd < 16 && addToEnd > 0)
|
if (addToEnd < 16 && addToEnd > 0)
|
||||||
{
|
{
|
||||||
out_uint8s(out, addToEnd);
|
out_uint8s(out, addToEnd);
|
||||||
|
s_mark_end(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Result == SCARD_E_INSUFFICIENT_BUFFER) return RD_STATUS_BUFFER_TOO_SMALL;
|
if (Result == SCARD_E_INSUFFICIENT_BUFFER) return RD_STATUS_BUFFER_TOO_SMALL;
|
||||||
@ -2440,6 +2463,7 @@ scard_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out,
|
|||||||
static STREAM
|
static STREAM
|
||||||
duplicateStream(PMEM_HANDLE * handle, STREAM s, uint32 buffer_size, RD_BOOL isInputStream)
|
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));
|
STREAM d = SC_xmalloc(handle, sizeof(struct stream));
|
||||||
if (d != NULL)
|
if (d != NULL)
|
||||||
{
|
{
|
||||||
@ -2575,13 +2599,18 @@ SC_deviceControl(PSCThreadData data)
|
|||||||
RD_NTSTATUS status;
|
RD_NTSTATUS status;
|
||||||
size_t buffer_len = 0;
|
size_t buffer_len = 0;
|
||||||
status = scard_device_control(data->handle, data->request, data->in, data->out, data->srv_buf_len);
|
status = scard_device_control(data->handle, data->request, data->in, data->out, data->srv_buf_len);
|
||||||
buffer_len = (size_t) data->out->p - (size_t) data->out->data;
|
buffer_len = s_tell(data->out);
|
||||||
|
|
||||||
/* if iorequest belongs to another epoch, don't send response
|
/* if iorequest belongs to another epoch, don't send response
|
||||||
back to server due to it's considered as abandoned.
|
back to server due to it's considered as abandoned.
|
||||||
*/
|
*/
|
||||||
if (data->epoch == curEpoch)
|
if (data->epoch == curEpoch)
|
||||||
rdpdr_send_completion(data->device, data->id, status, buffer_len, data->out->data, buffer_len);
|
{
|
||||||
|
uint8 *buf;
|
||||||
|
s_seek(data->out, 0);
|
||||||
|
in_uint8p(data->out, buf, buffer_len);
|
||||||
|
rdpdr_send_completion(data->device, data->id, status, buffer_len, buf, buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
SC_destroyThreadData(data);
|
SC_destroyThreadData(data);
|
||||||
}
|
}
|
||||||
|
14
seamless.c
14
seamless.c
@ -376,17 +376,12 @@ seamless_process(STREAM s)
|
|||||||
{
|
{
|
||||||
unsigned int pkglen;
|
unsigned int pkglen;
|
||||||
char *buf;
|
char *buf;
|
||||||
struct stream packet = *s;
|
|
||||||
|
|
||||||
if (!s_check(s))
|
pkglen = s_remaining(s);
|
||||||
{
|
|
||||||
rdp_protocol_error("seamless_process(), stream is in unstable state", &packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
pkglen = s->end - s->p;
|
|
||||||
/* str_handle_lines requires null terminated strings */
|
/* str_handle_lines requires null terminated strings */
|
||||||
buf = xmalloc(pkglen + 1);
|
buf = xmalloc(pkglen + 1);
|
||||||
STRNCPY(buf, (char *) s->p, pkglen + 1);
|
in_uint8a(s, buf, pkglen);
|
||||||
|
buf[pkglen] = '\0';
|
||||||
str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
|
str_handle_lines(buf, &seamless_rest, seamless_line_handler, NULL);
|
||||||
|
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
@ -446,11 +441,12 @@ seamless_send(const char *command, const char *format, ...)
|
|||||||
len++;
|
len++;
|
||||||
|
|
||||||
s = channel_init(seamless_channel, 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);
|
logger(Core, Debug, "seamless_send(), sending '%s'", buf);
|
||||||
|
|
||||||
channel_send(s, seamless_channel);
|
channel_send(s, seamless_channel);
|
||||||
|
s_free(s);
|
||||||
|
|
||||||
return seamless_serial++;
|
return seamless_serial++;
|
||||||
}
|
}
|
||||||
|
123
secure.c
123
secure.c
@ -351,10 +351,12 @@ sec_send_to_channel(STREAM s, uint32 flags, uint16 channel)
|
|||||||
|
|
||||||
if (flags & SEC_ENCRYPT)
|
if (flags & SEC_ENCRYPT)
|
||||||
{
|
{
|
||||||
|
unsigned char *data;
|
||||||
flags &= ~SEC_ENCRYPT;
|
flags &= ~SEC_ENCRYPT;
|
||||||
datalen = s->end - s->p - 8;
|
datalen = s_remaining(s) - 8;
|
||||||
sec_sign(s->p, 8, g_sec_sign_key, g_rc4_key_len, s->p + 8, datalen);
|
inout_uint8p(s, data, datalen + 8);
|
||||||
sec_encrypt(s->p + 8, datalen);
|
sec_sign(data, 8, g_sec_sign_key, g_rc4_key_len, data + 8, datalen);
|
||||||
|
sec_encrypt(data + 8, datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
mcs_send_to_channel(s, channel);
|
mcs_send_to_channel(s, channel);
|
||||||
@ -384,11 +386,12 @@ sec_establish_key(void)
|
|||||||
s = sec_init(flags, length + 4);
|
s = sec_init(flags, length + 4);
|
||||||
|
|
||||||
out_uint32_le(s, length);
|
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);
|
out_uint8s(s, SEC_PADDING_SIZE);
|
||||||
|
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
sec_send(s, flags);
|
sec_send(s, flags);
|
||||||
|
s_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output connect initial data blob */
|
/* Output connect initial data blob */
|
||||||
@ -523,6 +526,10 @@ sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
|
|||||||
{
|
{
|
||||||
uint32 magic, modulus_len;
|
uint32 magic, modulus_len;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 8)) {
|
||||||
|
return False;
|
||||||
|
}
|
||||||
|
|
||||||
in_uint32_le(s, magic);
|
in_uint32_le(s, magic);
|
||||||
if (magic != SEC_RSA_MAGIC)
|
if (magic != SEC_RSA_MAGIC)
|
||||||
{
|
{
|
||||||
@ -541,13 +548,17 @@ sec_parse_public_key(STREAM s, uint8 * modulus, uint8 * exponent)
|
|||||||
return False;
|
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_uint8s(s, 8); /* modulus_bits, unknown */
|
||||||
in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
|
in_uint8a(s, exponent, SEC_EXPONENT_SIZE);
|
||||||
in_uint8a(s, modulus, modulus_len);
|
in_uint8a(s, modulus, modulus_len);
|
||||||
in_uint8s(s, SEC_PADDING_SIZE);
|
in_uint8s(s, SEC_PADDING_SIZE);
|
||||||
g_server_public_key_len = modulus_len;
|
g_server_public_key_len = modulus_len;
|
||||||
|
|
||||||
return s_check(s);
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a public signature structure */
|
/* 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_CERT *cacert, *server_cert;
|
||||||
RDSSL_RKEY *server_public_key;
|
RDSSL_RKEY *server_public_key;
|
||||||
uint16 tag, length;
|
uint16 tag, length;
|
||||||
uint8 *next_tag, *end;
|
size_t next_tag;
|
||||||
|
|
||||||
logger(Protocol, Debug, "%s()", __func__);
|
logger(Protocol, Debug, "%s()", __func__);
|
||||||
|
|
||||||
@ -604,10 +615,9 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
|
|||||||
in_uint8p(s, *server_random, random_len);
|
in_uint8p(s, *server_random, random_len);
|
||||||
|
|
||||||
/* RSA info */
|
/* RSA info */
|
||||||
end = s->p + rsa_info_len;
|
if (!s_check_rem(s, rsa_info_len))
|
||||||
if (end > s->end)
|
|
||||||
{
|
{
|
||||||
logger(Protocol, Error, "sec_parse_crypt_info(), end > s->end");
|
logger(Protocol, Error, "sec_parse_crypt_info(), !s_check_rem(s, rsa_info_len)");
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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");
|
"sec_parse_crypt_info(), We're going for the RDP4-style encryption");
|
||||||
in_uint8s(s, 8); /* unknown */
|
in_uint8s(s, 8); /* unknown */
|
||||||
|
|
||||||
while (s->p < end)
|
while (!s_check_end(s))
|
||||||
{
|
{
|
||||||
in_uint16_le(s, tag);
|
in_uint16_le(s, tag);
|
||||||
in_uint16_le(s, length);
|
in_uint16_le(s, length);
|
||||||
|
|
||||||
next_tag = s->p + length;
|
next_tag = s_tell(s) + length;
|
||||||
|
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
@ -654,12 +664,13 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
|
|||||||
tag);
|
tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p = next_tag;
|
s_seek(s, next_tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32 certcount;
|
uint32 certcount;
|
||||||
|
unsigned char *certdata;
|
||||||
|
|
||||||
logger(Protocol, Debug,
|
logger(Protocol, Debug,
|
||||||
"sec_parse_crypt_info(), We're going for the RDP5-style encryption");
|
"sec_parse_crypt_info(), We're going for the RDP5-style encryption");
|
||||||
@ -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 */
|
{ /* ignore all the certificates between the root and the signing CA */
|
||||||
uint32 ignorelen;
|
uint32 ignorelen;
|
||||||
RDSSL_CERT *ignorecert;
|
RDSSL_CERT *ignorecert;
|
||||||
|
unsigned char *ignoredata;
|
||||||
|
|
||||||
in_uint32_le(s, ignorelen);
|
in_uint32_le(s, ignorelen);
|
||||||
ignorecert = rdssl_cert_read(s->p, ignorelen);
|
in_uint8p(s, ignoredata, ignorelen);
|
||||||
in_uint8s(s, ignorelen);
|
ignorecert = rdssl_cert_read(ignoredata, ignorelen);
|
||||||
if (ignorecert == NULL)
|
if (ignorecert == NULL)
|
||||||
{ /* XXX: error out? */
|
{ /* XXX: error out? */
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
@ -697,10 +709,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
|
|||||||
http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
|
http://www.cs.auckland.ac.nz/~pgut001/pubs/x509guide.txt
|
||||||
*/
|
*/
|
||||||
in_uint32_le(s, cacert_len);
|
in_uint32_le(s, cacert_len);
|
||||||
|
in_uint8p(s, certdata, cacert_len);
|
||||||
logger(Protocol, Debug,
|
logger(Protocol, Debug,
|
||||||
"sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len);
|
"sec_parse_crypt_info(), server CA Certificate length is %d", cacert_len);
|
||||||
cacert = rdssl_cert_read(s->p, cacert_len);
|
cacert = rdssl_cert_read(certdata, cacert_len);
|
||||||
in_uint8s(s, cacert_len);
|
|
||||||
if (NULL == cacert)
|
if (NULL == cacert)
|
||||||
{
|
{
|
||||||
logger(Protocol, Error,
|
logger(Protocol, Error,
|
||||||
@ -708,10 +720,10 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
in_uint32_le(s, cert_len);
|
in_uint32_le(s, cert_len);
|
||||||
|
in_uint8p(s, certdata, cert_len);
|
||||||
logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d",
|
logger(Protocol, Debug, "sec_parse_crypt_info(), certificate length is %d",
|
||||||
cert_len);
|
cert_len);
|
||||||
server_cert = rdssl_cert_read(s->p, cert_len);
|
server_cert = rdssl_cert_read(certdata, cert_len);
|
||||||
in_uint8s(s, cert_len);
|
|
||||||
if (NULL == server_cert)
|
if (NULL == server_cert)
|
||||||
{
|
{
|
||||||
rdssl_cert_free(cacert);
|
rdssl_cert_free(cacert);
|
||||||
@ -805,7 +817,7 @@ void
|
|||||||
sec_process_mcs_data(STREAM s)
|
sec_process_mcs_data(STREAM s)
|
||||||
{
|
{
|
||||||
uint16 tag, length;
|
uint16 tag, length;
|
||||||
uint8 *next_tag;
|
size_t next_tag;
|
||||||
uint8 len;
|
uint8 len;
|
||||||
|
|
||||||
in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
|
in_uint8s(s, 21); /* header (T.124 ConferenceCreateResponse) */
|
||||||
@ -814,7 +826,7 @@ sec_process_mcs_data(STREAM s)
|
|||||||
in_uint8(s, len);
|
in_uint8(s, len);
|
||||||
logger(Protocol, Debug, "%s()", __func__);
|
logger(Protocol, Debug, "%s()", __func__);
|
||||||
|
|
||||||
while (s->p < s->end)
|
while (!s_check_end(s))
|
||||||
{
|
{
|
||||||
in_uint16_le(s, tag);
|
in_uint16_le(s, tag);
|
||||||
in_uint16_le(s, length);
|
in_uint16_le(s, length);
|
||||||
@ -822,7 +834,7 @@ sec_process_mcs_data(STREAM s)
|
|||||||
if (length <= 4)
|
if (length <= 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
next_tag = s->p + length - 4;
|
next_tag = s_tell(s) + length - 4;
|
||||||
|
|
||||||
switch (tag)
|
switch (tag)
|
||||||
{
|
{
|
||||||
@ -847,7 +859,7 @@ sec_process_mcs_data(STREAM s)
|
|||||||
logger(Protocol, Warning, "Unhandled response tag 0x%x", tag);
|
logger(Protocol, Warning, "Unhandled response tag 0x%x", tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->p = next_tag;
|
s_seek(s, next_tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -860,6 +872,8 @@ sec_recv(RD_BOOL * is_fastpath)
|
|||||||
uint16 channel;
|
uint16 channel;
|
||||||
STREAM s;
|
STREAM s;
|
||||||
struct stream packet;
|
struct stream packet;
|
||||||
|
size_t data_offset;
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
|
while ((s = mcs_recv(&channel, is_fastpath, &fastpath_hdr)) != NULL)
|
||||||
{
|
{
|
||||||
@ -873,35 +887,50 @@ sec_recv(RD_BOOL * is_fastpath)
|
|||||||
if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
|
if (fastpath_flags & FASTPATH_OUTPUT_ENCRYPTED)
|
||||||
{
|
{
|
||||||
if (!s_check_rem(s, 8)) {
|
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 */
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_encryption || (!g_licence_issued && !g_licence_error_result))
|
if (g_encryption || (!g_licence_issued && !g_licence_error_result))
|
||||||
{
|
{
|
||||||
|
data_offset = s_tell(s);
|
||||||
|
|
||||||
/* TS_SECURITY_HEADER */
|
/* TS_SECURITY_HEADER */
|
||||||
in_uint16_le(s, sec_flags);
|
in_uint16_le(s, sec_flags);
|
||||||
in_uint8s(s, 2); /* skip sec_flags_hi */
|
in_uint8s(s, 2); /* skip sec_flags_hi */
|
||||||
|
|
||||||
if (g_encryption)
|
if (g_encryption)
|
||||||
{
|
{
|
||||||
|
data_offset = s_tell(s);
|
||||||
|
|
||||||
if (sec_flags & SEC_ENCRYPT)
|
if (sec_flags & SEC_ENCRYPT)
|
||||||
{
|
{
|
||||||
if (!s_check_rem(s, 8)) {
|
if (!s_check_rem(s, 8)) {
|
||||||
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 */
|
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)
|
if (sec_flags & SEC_LICENSE_PKT)
|
||||||
{
|
{
|
||||||
|
s_seek(s, data_offset);
|
||||||
licence_process(s);
|
licence_process(s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -911,14 +940,18 @@ sec_recv(RD_BOOL * is_fastpath)
|
|||||||
uint8 swapbyte;
|
uint8 swapbyte;
|
||||||
|
|
||||||
if (!s_check_rem(s, 8)) {
|
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 */
|
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 */
|
/* Check for a redirect packet, starts with 00 04 */
|
||||||
if (s->p[0] == 0 && s->p[1] == 4)
|
if (data[0] == 0 && data[1] == 4)
|
||||||
{
|
{
|
||||||
/* for some reason the PDU and the length seem to be swapped.
|
/* for some reason the PDU and the length seem to be swapped.
|
||||||
This isn't good, but we're going to do a byte for byte
|
This isn't good, but we're going to do a byte for byte
|
||||||
@ -926,17 +959,17 @@ sec_recv(RD_BOOL * is_fastpath)
|
|||||||
where XX YY is the little endian length. We're going to
|
where XX YY is the little endian length. We're going to
|
||||||
use 04 00 as the PDU type, so after our swap this will look
|
use 04 00 as the PDU type, so after our swap this will look
|
||||||
like: XX YY 04 00 */
|
like: XX YY 04 00 */
|
||||||
swapbyte = s->p[0];
|
swapbyte = data[0];
|
||||||
s->p[0] = s->p[2];
|
data[0] = data[2];
|
||||||
s->p[2] = swapbyte;
|
data[2] = swapbyte;
|
||||||
|
|
||||||
swapbyte = s->p[1];
|
swapbyte = data[1];
|
||||||
s->p[1] = s->p[3];
|
data[1] = data[3];
|
||||||
s->p[3] = swapbyte;
|
data[3] = swapbyte;
|
||||||
|
|
||||||
swapbyte = s->p[2];
|
swapbyte = data[2];
|
||||||
s->p[2] = s->p[3];
|
data[2] = data[3];
|
||||||
s->p[3] = swapbyte;
|
data[3] = swapbyte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,8 +980,9 @@ sec_recv(RD_BOOL * is_fastpath)
|
|||||||
licence_process(s);
|
licence_process(s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
s->p -= 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s_seek(s, data_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel != MCS_GLOBAL_CHANNEL)
|
if (channel != MCS_GLOBAL_CHANNEL)
|
||||||
@ -968,25 +1002,24 @@ RD_BOOL
|
|||||||
sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
|
sec_connect(char *server, char *username, char *domain, char *password, RD_BOOL reconnect)
|
||||||
{
|
{
|
||||||
uint32 selected_proto;
|
uint32 selected_proto;
|
||||||
struct stream mcs_data;
|
STREAM mcs_data;
|
||||||
|
|
||||||
/* Start a MCS connect sequence */
|
/* Start a MCS connect sequence */
|
||||||
if (!mcs_connect_start(server, username, domain, password, reconnect, &selected_proto))
|
if (!mcs_connect_start(server, username, domain, password, reconnect, &selected_proto))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* We exchange some RDP data during the MCS-Connect */
|
/* We exchange some RDP data during the MCS-Connect */
|
||||||
mcs_data.size = 512;
|
mcs_data = s_alloc(512);
|
||||||
mcs_data.p = mcs_data.data = (uint8 *) xmalloc(mcs_data.size);
|
sec_out_mcs_connect_initial_pdu(mcs_data, selected_proto);
|
||||||
sec_out_mcs_connect_initial_pdu(&mcs_data, selected_proto);
|
|
||||||
|
|
||||||
/* finalize the MCS connect sequence */
|
/* finalize the MCS connect sequence */
|
||||||
if (!mcs_connect_finalize(&mcs_data))
|
if (!mcs_connect_finalize(mcs_data))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* sec_process_mcs_data(&mcs_data); */
|
/* sec_process_mcs_data(&mcs_data); */
|
||||||
if (g_encryption)
|
if (g_encryption)
|
||||||
sec_establish_key();
|
sec_establish_key();
|
||||||
xfree(mcs_data.data);
|
s_free(mcs_data);
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
ssl.c
14
ssl.c
@ -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);
|
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
|
void
|
||||||
rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
|
rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
|
||||||
uint8 * exponent)
|
uint8 * exponent)
|
||||||
|
27
stream.c
27
stream.c
@ -25,6 +25,31 @@
|
|||||||
|
|
||||||
extern char g_codepage[16];
|
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
|
void
|
||||||
s_realloc(STREAM s, unsigned int size)
|
s_realloc(STREAM s, unsigned int size)
|
||||||
{
|
{
|
||||||
@ -59,6 +84,8 @@ s_reset(STREAM s)
|
|||||||
void
|
void
|
||||||
s_free(STREAM s)
|
s_free(STREAM s)
|
||||||
{
|
{
|
||||||
|
if (s == NULL)
|
||||||
|
return;
|
||||||
free(s->data);
|
free(s->data);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
118
stream.h
118
stream.h
@ -41,8 +41,15 @@ typedef struct stream
|
|||||||
}
|
}
|
||||||
*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);
|
void s_realloc(STREAM s, unsigned int size);
|
||||||
|
/* Free STREAM object and its associated buffer */
|
||||||
void s_free(STREAM s);
|
void s_free(STREAM s);
|
||||||
|
/* Reset all internal offsets, but keep the allocated size */
|
||||||
void s_reset(STREAM s);
|
void s_reset(STREAM s);
|
||||||
|
|
||||||
void out_utf16s(STREAM s, const char *string);
|
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);
|
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; }
|
#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;
|
#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_mark_end(s) (s)->end = (s)->p;
|
||||||
#define s_check(s) ((s)->p <= (s)->end)
|
/* Return current read offset in the STREAM */
|
||||||
#define s_check_rem(s,n) (s_check(s) && (n <= (s)->end - (s)->p))
|
#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)
|
#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_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)
|
#if defined(L_ENDIAN) && !defined(NEED_ALIGN)
|
||||||
#define in_uint16_le(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; }
|
#define in_uint16_le(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; }
|
||||||
#define in_uint32_le(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; }
|
#define in_uint32_le(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; }
|
||||||
#define in_uint64_le(s,v) { v = *(uint64 *)((s)->p); (s)->p += 8; }
|
#define in_uint64_le(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; }
|
||||||
#define out_uint16_le(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; }
|
#define out_uint16_le(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; }
|
||||||
#define out_uint32_le(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; }
|
#define out_uint32_le(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; }
|
||||||
#define out_uint64_le(s,v) { *(uint64 *)((s)->p) = v; (s)->p += 8; }
|
#define out_uint64_le(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; }
|
||||||
#else
|
#else
|
||||||
#define in_uint16_le(s,v) { v = *((s)->p++); v += *((s)->p++) << 8; }
|
#define in_uint16_le(s,v) { s_assert_r(s, 2); v = *((s)->p++); v += *((s)->p++) << 8; }
|
||||||
#define in_uint32_le(s,v) { in_uint16_le(s,v) \
|
#define in_uint32_le(s,v) { s_assert_r(s, 4); in_uint16_le(s,v) \
|
||||||
v += *((s)->p++) << 16; v += *((s)->p++) << 24; }
|
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++) << 32; v += *((s)->p++) << 40; \
|
||||||
v += *((s)->p++) << 48; v += *((s)->p++) << 56; }
|
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_uint16_le(s,v) { s_assert_w(s, 2); *((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_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) { out_uint32_le(s, (v) & 0xffffffff); out_uint32_le(s, ((v) >> 32) & 0xffffffff); }
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Read/write an unsigned integer in big-endian order */
|
||||||
#if defined(B_ENDIAN) && !defined(NEED_ALIGN)
|
#if defined(B_ENDIAN) && !defined(NEED_ALIGN)
|
||||||
#define in_uint16_be(s,v) { v = *(uint16 *)((s)->p); (s)->p += 2; }
|
#define in_uint16_be(s,v) { s_assert_r(s, 2); v = *(uint16 *)((s)->p); (s)->p += 2; }
|
||||||
#define in_uint32_be(s,v) { v = *(uint32 *)((s)->p); (s)->p += 4; }
|
#define in_uint32_be(s,v) { s_assert_r(s, 4); v = *(uint32 *)((s)->p); (s)->p += 4; }
|
||||||
#define in_uint64_be(s,v) { v = *(uint64 *)((s)->p); (s)->p += 8; }
|
#define in_uint64_be(s,v) { s_assert_r(s, 8); v = *(uint64 *)((s)->p); (s)->p += 8; }
|
||||||
#define out_uint16_be(s,v) { *(uint16 *)((s)->p) = v; (s)->p += 2; }
|
#define out_uint16_be(s,v) { s_assert_w(s, 2); *(uint16 *)((s)->p) = v; (s)->p += 2; }
|
||||||
#define out_uint32_be(s,v) { *(uint32 *)((s)->p) = v; (s)->p += 4; }
|
#define out_uint32_be(s,v) { s_assert_w(s, 4); *(uint32 *)((s)->p) = v; (s)->p += 4; }
|
||||||
#define out_uint64_be(s,v) { *(uint64 *)((s)->p) = v; (s)->p += 8; }
|
#define out_uint64_be(s,v) { s_assert_w(s, 8); *(uint64 *)((s)->p) = v; (s)->p += 8; }
|
||||||
|
|
||||||
#define B_ENDIAN_PREFERRED
|
#define B_ENDIAN_PREFERRED
|
||||||
#define in_uint16(s,v) in_uint16_be(s,v)
|
#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)
|
#define out_uint64(s,v) out_uint64_be(s,v)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define in_uint16_be(s,v) { v = *((s)->p++); next_be(s,v); }
|
#define in_uint16_be(s,v) { s_assert_r(s, 2); 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_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) { in_uint32_be(s,v); next_be(s,v); next_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)->p++) = ((v) >> 8) & 0xff; *((s)->p++) = (v) & 0xff; }
|
#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) { out_uint16_be(s, ((v) >> 16) & 0xffff); out_uint16_be(s, (v) & 0xffff); }
|
#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) { out_uint32_be(s, ((v) >> 32) & 0xffffffff); out_uint32_be(s, (v) & 0xffffffff); }
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef B_ENDIAN_PREFERRED
|
#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)
|
#define out_uint64(s,v) out_uint64_le(s,v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define in_uint8(s,v) v = *((s)->p++);
|
/* Read a single unsigned byte in v from STREAM s */
|
||||||
#define in_uint8p(s,v,n) { v = (s)->p; (s)->p += n; }
|
#define in_uint8(s,v) { s_assert_r(s, 1); v = *((s)->p++); }
|
||||||
#define in_uint8a(s,v,n) { memcpy(v,(s)->p,n); (s)->p += n; }
|
/* Return a pointer in v to manually read n bytes from STREAM s */
|
||||||
#define in_uint8s(s,n) (s)->p += n;
|
#define in_uint8p(s,v,n) { s_assert_r(s, n); v = (s)->p; (s)->p += n; }
|
||||||
#define in_skip(s,n) in_uint8s(s,n)
|
/* Copy n bytes from STREAM s in to array v */
|
||||||
#define out_uint8(s,v) *((s)->p++) = v;
|
#define in_uint8a(s,v,n) { s_assert_r(s, n); memcpy(v,(s)->p,n); (s)->p += n; }
|
||||||
#define out_uint8p(s,v,n) { memcpy((s)->p,v,n); (s)->p += n; }
|
/* Skip reading n bytes in STREAM s */
|
||||||
#define out_uint8a(s,v,n) out_uint8p(s,v,n);
|
#define in_uint8s(s,n) { s_assert_r(s, n); (s)->p += n; }
|
||||||
#define out_uint8s(s,n) { memset((s)->p,0,n); (s)->p += n; }
|
/* Write a single unsigned byte from v to STREAM s */
|
||||||
#define out_stream(s, v) out_uint8p(s, (v)->data, s_length((v)))
|
#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 */
|
#endif /* _STREAM_H */
|
||||||
|
122
tcp.c
122
tcp.c
@ -58,12 +58,6 @@
|
|||||||
#define INADDR_NONE ((unsigned long) -1)
|
#define INADDR_NONE ((unsigned long) -1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_SCARD
|
|
||||||
#define STREAM_COUNT 8
|
|
||||||
#else
|
|
||||||
#define STREAM_COUNT 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IPv6
|
#ifdef IPv6
|
||||||
static struct addrinfo *g_server_address = NULL;
|
static struct addrinfo *g_server_address = NULL;
|
||||||
#else
|
#else
|
||||||
@ -75,7 +69,6 @@ static RD_BOOL g_ssl_initialized = False;
|
|||||||
static int g_sock;
|
static int g_sock;
|
||||||
static RD_BOOL g_run_ui = False;
|
static RD_BOOL g_run_ui = False;
|
||||||
static struct stream g_in;
|
static struct stream g_in;
|
||||||
static struct stream g_out[STREAM_COUNT];
|
|
||||||
int g_tcp_port_rdp = TCP_PORT_RDP;
|
int g_tcp_port_rdp = TCP_PORT_RDP;
|
||||||
|
|
||||||
extern RD_BOOL g_exit_mainloop;
|
extern RD_BOOL g_exit_mainloop;
|
||||||
@ -109,28 +102,16 @@ tcp_can_send(int sck, int millis)
|
|||||||
STREAM
|
STREAM
|
||||||
tcp_init(uint32 maxlen)
|
tcp_init(uint32 maxlen)
|
||||||
{
|
{
|
||||||
static int cur_stream_id = 0;
|
return s_alloc(maxlen);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send TCP transport data packet */
|
/* Send TCP transport data packet */
|
||||||
void
|
void
|
||||||
tcp_send(STREAM s)
|
tcp_send(STREAM s)
|
||||||
{
|
{
|
||||||
int length = s->end - s->data;
|
size_t before;
|
||||||
int sent, total = 0;
|
int length, sent;
|
||||||
|
unsigned char *data;
|
||||||
|
|
||||||
if (g_network_error == True)
|
if (g_network_error == True)
|
||||||
return;
|
return;
|
||||||
@ -139,10 +120,16 @@ tcp_send(STREAM s)
|
|||||||
scard_lock(SCARD_LOCK_TCP);
|
scard_lock(SCARD_LOCK_TCP);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (total < length)
|
s_seek(s, 0);
|
||||||
|
|
||||||
|
while (!s_check_end(s))
|
||||||
{
|
{
|
||||||
|
before = s_tell(s);
|
||||||
|
length = s_remaining(s);
|
||||||
|
in_uint8p(s, data, length);
|
||||||
|
|
||||||
if (g_ssl_initialized) {
|
if (g_ssl_initialized) {
|
||||||
sent = gnutls_record_send(g_tls_session, s->data + total, length - total);
|
sent = gnutls_record_send(g_tls_session, data, length);
|
||||||
if (sent <= 0) {
|
if (sent <= 0) {
|
||||||
if (gnutls_error_is_fatal(sent)) {
|
if (gnutls_error_is_fatal(sent)) {
|
||||||
#ifdef WITH_SCARD
|
#ifdef WITH_SCARD
|
||||||
@ -159,7 +146,7 @@ tcp_send(STREAM s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sent = send(g_sock, s->data + total, length - total, 0);
|
sent = send(g_sock, data, length, 0);
|
||||||
if (sent <= 0)
|
if (sent <= 0)
|
||||||
{
|
{
|
||||||
if (sent == -1 && TCP_BLOCKS)
|
if (sent == -1 && TCP_BLOCKS)
|
||||||
@ -179,7 +166,9 @@ tcp_send(STREAM s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total += sent;
|
|
||||||
|
/* Everything might not have been sent */
|
||||||
|
s_seek(s, before + sent);
|
||||||
}
|
}
|
||||||
#ifdef WITH_SCARD
|
#ifdef WITH_SCARD
|
||||||
scard_unlock(SCARD_LOCK_TCP);
|
scard_unlock(SCARD_LOCK_TCP);
|
||||||
@ -190,7 +179,8 @@ tcp_send(STREAM s)
|
|||||||
STREAM
|
STREAM
|
||||||
tcp_recv(STREAM s, uint32 length)
|
tcp_recv(STREAM s, uint32 length)
|
||||||
{
|
{
|
||||||
uint32 new_length, end_offset, p_offset;
|
size_t before;
|
||||||
|
unsigned char *data;
|
||||||
int rcvd = 0;
|
int rcvd = 0;
|
||||||
|
|
||||||
if (g_network_error == True)
|
if (g_network_error == True)
|
||||||
@ -199,27 +189,14 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
{
|
{
|
||||||
/* read into "new" stream */
|
/* read into "new" stream */
|
||||||
if (length > g_in.size)
|
s_realloc(&g_in, length);
|
||||||
{
|
s_reset(&g_in);
|
||||||
g_in.data = (uint8 *) xrealloc(g_in.data, length);
|
|
||||||
g_in.size = length;
|
|
||||||
}
|
|
||||||
g_in.end = g_in.p = g_in.data;
|
|
||||||
s = &g_in;
|
s = &g_in;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* append to existing stream */
|
/* append to existing stream */
|
||||||
new_length = (s->end - s->data) + length;
|
s_realloc(s, s_length(s) + length);
|
||||||
if (new_length > s->size)
|
|
||||||
{
|
|
||||||
p_offset = s->p - s->data;
|
|
||||||
end_offset = s->end - s->data;
|
|
||||||
s->data = (uint8 *) xrealloc(s->data, new_length);
|
|
||||||
s->size = new_length;
|
|
||||||
s->p = s->data + p_offset;
|
|
||||||
s->end = s->data + end_offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (length > 0)
|
while (length > 0)
|
||||||
@ -235,8 +212,15 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
before = s_tell(s);
|
||||||
|
s_seek(s, s_length(s));
|
||||||
|
|
||||||
|
out_uint8p(s, data, length);
|
||||||
|
|
||||||
|
s_seek(s, before);
|
||||||
|
|
||||||
if (g_ssl_initialized) {
|
if (g_ssl_initialized) {
|
||||||
rcvd = gnutls_record_recv(g_tls_session, s->end, length);
|
rcvd = gnutls_record_recv(g_tls_session, data, length);
|
||||||
|
|
||||||
if (rcvd < 0) {
|
if (rcvd < 0) {
|
||||||
if (gnutls_error_is_fatal(rcvd)) {
|
if (gnutls_error_is_fatal(rcvd)) {
|
||||||
@ -251,7 +235,7 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rcvd = recv(g_sock, s->end, length, 0);
|
rcvd = recv(g_sock, data, length, 0);
|
||||||
if (rcvd < 0)
|
if (rcvd < 0)
|
||||||
{
|
{
|
||||||
if (rcvd == -1 && TCP_BLOCKS)
|
if (rcvd == -1 && TCP_BLOCKS)
|
||||||
@ -273,6 +257,7 @@ tcp_recv(STREAM s, uint32 length)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Should probably have a macro for this
|
||||||
s->end += rcvd;
|
s->end += rcvd;
|
||||||
length -= rcvd;
|
length -= rcvd;
|
||||||
}
|
}
|
||||||
@ -349,9 +334,6 @@ tcp_tls_connect(void)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
int type;
|
|
||||||
int status;
|
|
||||||
gnutls_datum_t out;
|
|
||||||
gnutls_certificate_credentials_t xcred;
|
gnutls_certificate_credentials_t xcred;
|
||||||
|
|
||||||
/* Initialize TLS session */
|
/* Initialize TLS session */
|
||||||
@ -422,8 +404,8 @@ fail:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get public key from server of TLS 1.x connection */
|
/* Get public key from server of TLS 1.x connection */
|
||||||
RD_BOOL
|
STREAM
|
||||||
tcp_tls_get_server_pubkey(STREAM s)
|
tcp_tls_get_server_pubkey()
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int list_size;
|
unsigned int list_size;
|
||||||
@ -436,8 +418,7 @@ tcp_tls_get_server_pubkey(STREAM s)
|
|||||||
int pk_size;
|
int pk_size;
|
||||||
uint8_t pk_data[1024];
|
uint8_t pk_data[1024];
|
||||||
|
|
||||||
s->data = s->p = NULL;
|
STREAM s = NULL;
|
||||||
s->size = 0;
|
|
||||||
|
|
||||||
cert_list = gnutls_certificate_get_peers(g_tls_session, &list_size);
|
cert_list = gnutls_certificate_get_peers(g_tls_session, &list_size);
|
||||||
|
|
||||||
@ -489,11 +470,10 @@ tcp_tls_get_server_pubkey(STREAM s)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->size = pk_size;
|
s = s_alloc(pk_size);
|
||||||
s->data = s->p = xmalloc(s->size);
|
out_uint8a(s, pk_data, pk_size);
|
||||||
memcpy((void *)s->data, (void *)pk_data, pk_size);
|
s_mark_end(s);
|
||||||
s->p = s->data;
|
s_seek(s, 0);
|
||||||
s->end = s->p + s->size;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if ((e.size != 0) && (e.data)) {
|
if ((e.size != 0) && (e.data)) {
|
||||||
@ -504,7 +484,7 @@ out:
|
|||||||
free(m.data);
|
free(m.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (s->size != 0);
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Helper function to determine if rdesktop should resolve hostnames again or not */
|
/* Helper function to determine if rdesktop should resolve hostnames again or not */
|
||||||
@ -530,7 +510,6 @@ tcp_connect(char *server)
|
|||||||
{
|
{
|
||||||
socklen_t option_len;
|
socklen_t option_len;
|
||||||
uint32 option_value;
|
uint32 option_value;
|
||||||
int i;
|
|
||||||
char buf[NI_MAXHOST];
|
char buf[NI_MAXHOST];
|
||||||
|
|
||||||
#ifdef IPv6
|
#ifdef IPv6
|
||||||
@ -681,12 +660,6 @@ tcp_connect(char *server)
|
|||||||
g_in.size = 4096;
|
g_in.size = 4096;
|
||||||
g_in.data = (uint8 *) xmalloc(g_in.size);
|
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 */
|
/* After successful connect: update the last server name */
|
||||||
if (g_last_server_name)
|
if (g_last_server_name)
|
||||||
xfree(g_last_server_name);
|
xfree(g_last_server_name);
|
||||||
@ -698,8 +671,6 @@ tcp_connect(char *server)
|
|||||||
void
|
void
|
||||||
tcp_disconnect(void)
|
tcp_disconnect(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
if (g_ssl_initialized) {
|
if (g_ssl_initialized) {
|
||||||
(void)gnutls_bye(g_tls_session, GNUTLS_SHUT_WR);
|
(void)gnutls_bye(g_tls_session, GNUTLS_SHUT_WR);
|
||||||
gnutls_deinit(g_tls_session);
|
gnutls_deinit(g_tls_session);
|
||||||
@ -715,13 +686,6 @@ tcp_disconnect(void)
|
|||||||
g_in.size = 0;
|
g_in.size = 0;
|
||||||
xfree(g_in.data);
|
xfree(g_in.data);
|
||||||
g_in.data = NULL;
|
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 *
|
char *
|
||||||
@ -755,16 +719,8 @@ tcp_is_connected()
|
|||||||
void
|
void
|
||||||
tcp_reset_state(void)
|
tcp_reset_state(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Clear the incoming stream */
|
/* Clear the incoming stream */
|
||||||
s_reset(&g_in);
|
s_reset(&g_in);
|
||||||
|
|
||||||
/* Clear the outgoing stream(s) */
|
|
||||||
for (i = 0; i < STREAM_COUNT; i++)
|
|
||||||
{
|
|
||||||
s_reset(&g_out[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -46,23 +46,13 @@ xfree(void *mem)
|
|||||||
free(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)
|
Ensure(ASN1, can_create_empty_sequence)
|
||||||
{
|
{
|
||||||
struct stream *s, *empty;
|
struct stream *s, *empty;
|
||||||
uint8_t expected_data[] = {0x30, 0x00};
|
uint8_t expected_data[] = {0x30, 0x00};
|
||||||
|
|
||||||
s = stream_new(100);
|
s = s_alloc(100);
|
||||||
empty = stream_new(100);
|
empty = s_alloc(100);
|
||||||
|
|
||||||
ber_out_sequence(s, empty);
|
ber_out_sequence(s, empty);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
@ -76,7 +66,7 @@ Ensure(ASN1, can_create_empty_sequence_using_null)
|
|||||||
struct stream *s;
|
struct stream *s;
|
||||||
uint8_t expected_data[] = {0x30, 0x00};
|
uint8_t expected_data[] = {0x30, 0x00};
|
||||||
|
|
||||||
s = stream_new(100);
|
s = s_alloc(100);
|
||||||
|
|
||||||
ber_out_sequence(s, NULL);
|
ber_out_sequence(s, NULL);
|
||||||
s_mark_end(s);
|
s_mark_end(s);
|
||||||
@ -90,8 +80,8 @@ Ensure(ASN1, can_create_sequence_of_two_integers)
|
|||||||
struct stream *s, *content;
|
struct stream *s, *content;
|
||||||
uint8_t expected_data[] = {0x30, 0x08, 0x02, 0x02, 0x00, 0xbe, 0x02, 0x02, 0x00, 0xef};
|
uint8_t expected_data[] = {0x30, 0x08, 0x02, 0x02, 0x00, 0xbe, 0x02, 0x02, 0x00, 0xef};
|
||||||
|
|
||||||
s = stream_new(100);
|
s = s_alloc(100);
|
||||||
content = stream_new(100);
|
content = s_alloc(100);
|
||||||
|
|
||||||
ber_out_integer(content, 0xbe);
|
ber_out_integer(content, 0xbe);
|
||||||
ber_out_integer(content, 0xef);
|
ber_out_integer(content, 0xef);
|
||||||
@ -109,8 +99,8 @@ Ensure(ASN1, can_create_sequence_of_one_integer)
|
|||||||
struct stream *s, *content;
|
struct stream *s, *content;
|
||||||
uint8_t expected_data[] = {0x30, 0x04, 0x02, 0x02, 0x00, 0xbe};
|
uint8_t expected_data[] = {0x30, 0x04, 0x02, 0x02, 0x00, 0xbe};
|
||||||
|
|
||||||
s = stream_new(100);
|
s = s_alloc(100);
|
||||||
content = stream_new(100);
|
content = s_alloc(100);
|
||||||
|
|
||||||
ber_out_integer(content, 0xbe);
|
ber_out_integer(content, 0xbe);
|
||||||
s_mark_end(content);
|
s_mark_end(content);
|
||||||
|
@ -52,15 +52,6 @@ xfree(void *mem)
|
|||||||
free(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 */
|
/* Test function */
|
||||||
Ensure(MCS, should_produce_valid_packet_for_McsSendCJrq)
|
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};
|
uint8_t content[] = {0x38, 0x00, 0x2A, 0x00, 0x0D};
|
||||||
|
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
s = stream_new(5);
|
s = s_alloc(5);
|
||||||
|
|
||||||
chan_id = 13;
|
chan_id = 13;
|
||||||
g_mcs_userid = 42;
|
g_mcs_userid = 42;
|
||||||
@ -89,7 +80,7 @@ Ensure(MCS, should_produce_valid_packet_for_McsSendDPU)
|
|||||||
struct stream *s;
|
struct stream *s;
|
||||||
uint8_t content[] = {0x30, 0x06, 0x02, 0x02, 0x00, reason, 0x30, 0x00};
|
uint8_t content[] = {0x30, 0x06, 0x02, 0x02, 0x00, reason, 0x30, 0x00};
|
||||||
|
|
||||||
s = stream_new(8);
|
s = s_alloc(8);
|
||||||
|
|
||||||
expect(logger);
|
expect(logger);
|
||||||
expect(iso_init, will_return(s));
|
expect(iso_init, will_return(s));
|
||||||
|
@ -412,17 +412,6 @@ Ensure(Resize, UsingRDPEDISPHonoursServerSessionWidthConstraintMustBeEven)
|
|||||||
free(s.data);
|
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)
|
void get_width_and_height_from_mcs_connect_initial(int *width, int *height)
|
||||||
{
|
{
|
||||||
STREAM s;
|
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 */
|
/* Rewind and extract the requested session size */
|
||||||
s_reset(s);
|
s_reset(s);
|
||||||
in_skip(s, 31);
|
in_uint8s(s, 31);
|
||||||
in_uint16_le(s, *width); /* desktopWidth */
|
in_uint16_le(s, *width); /* desktopWidth */
|
||||||
in_uint16_le(s, *height); /* desktopHeight */
|
in_uint16_le(s, *height); /* desktopHeight */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user