Return STREAM objects from data generating functions

Use a consistent style of returning a new STREAM object from functions
that output data, rather than requiring an existing structure to be
passed in. This generally makes the memory management more straight
forward and allows us to do more proper bounds checking of everything.

This also adds some new STREAM macros to make it easier to manage
them without poking around in the internal structure.
This commit is contained in:
Pierre Ossman 2019-04-09 13:25:50 +02:00
parent 655c3d56df
commit 489c43f382
13 changed files with 179 additions and 111 deletions

179
cssp.c
View File

@ -139,13 +139,14 @@ 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; inbuf.value = in->data;
inbuf.length = s_length(in); inbuf.length = s_length(in);
@ -157,35 +158,36 @@ 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_uint8a(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; inbuf.value = in->data;
inbuf.length = s_length(in); inbuf.length = s_length(in);
@ -196,17 +198,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_uint8a(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;
} }
@ -585,10 +587,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;
@ -596,7 +598,7 @@ 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 // verify ASN.1 header
if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED)) if (s->p[0] != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
@ -604,7 +606,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
logger(Protocol, Error, logger(Protocol, Error,
"cssp_read_tsrequest(), expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x", "cssp_read_tsrequest(), expected BER_TAG_SEQUENCE|BER_TAG_CONSTRUCTED, got %x",
s->p[0]); s->p[0]);
return False; return NULL;
} }
// peek at first 4 bytes to get full message length // peek at first 4 bytes to get full message length
@ -615,7 +617,7 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
else if (s->p[1] == 0x82) else if (s->p[1] == 0x82)
length = (s->p[2] << 8) | s->p[3]; length = (s->p[2] << 8) | s->p[3];
else else
return False; return NULL;
// receive the remainings of message // receive the remainings of message
s = tcp_recv(s, length); s = tcp_recv(s, length);
@ -624,12 +626,12 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
// parse the response and into nego token // parse the response and into nego token
if (!ber_in_header(s, &tagval, &length) || if (!ber_in_header(s, &tagval, &length) ||
tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED)) tagval != (BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED))
return False; return NULL;
// 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))
{ {
@ -639,23 +641,23 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
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))
{ {
@ -663,29 +665,29 @@ cssp_read_tsrequest(STREAM token, STREAM pubkey)
&packet); &packet);
} }
s_realloc(token, length); out = s_alloc(length);
s_reset(token); out_uint8a(out, s->p, length);
out_uint8a(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_uint8a(out, s->p, length);
pubkey->size = length; s_mark_end(out);
s_seek(out, 0);
} }
return True; return out;
} }
RD_BOOL RD_BOOL
@ -702,9 +704,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))
@ -728,16 +735,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;
@ -758,6 +768,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)
@ -782,39 +797,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_uint8a(&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;
@ -825,37 +845,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;
} }

View File

@ -227,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 */

View File

@ -641,7 +641,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;
@ -675,7 +675,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;
} }
@ -740,7 +740,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;
} }

View File

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

View File

@ -376,7 +376,7 @@ 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();

View File

@ -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;
} }

View File

@ -167,7 +167,7 @@ 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();

View File

@ -410,7 +410,7 @@ oss_play(void)
return; return;
packet = rdpsnd_queue_current_packet(); packet = rdpsnd_queue_current_packet();
out = &packet->s; out = packet->s;
len = s_remaining(out); len = s_remaining(out);

View File

@ -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)

View File

@ -254,7 +254,7 @@ sgi_play(void)
return; return;
packet = rdpsnd_queue_current_packet(); packet = rdpsnd_queue_current_packet();
out = (STREAM) (void *) &(packet->s); out = packet->s;
len = s_remaining(out); len = s_remaining(out);

View File

@ -37,6 +37,19 @@ s_alloc(unsigned int size)
return s; 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)
{ {
@ -71,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);
} }

View File

@ -43,6 +43,8 @@ typedef struct stream
/* Return a newly allocated STREAM object of the specified size */ /* Return a newly allocated STREAM object of the specified size */
STREAM s_alloc(unsigned int 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 */ /* 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 */ /* Free STREAM object and its associated buffer */
@ -60,6 +62,10 @@ size_t in_ansi_string(STREAM s, char *string, size_t len);
#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; }
#define s_pop_layer(s,h) (s)->p = (s)->h; #define s_pop_layer(s,h) (s)->p = (s)->h;
#define s_mark_end(s) (s)->end = (s)->p; #define s_mark_end(s) (s)->end = (s)->p;
/* Return current read offset in the STREAM */
#define s_tell(s) (size_t)((s)->p - (s)->data)
/* Set current read offset in the STREAM */
#define s_seek(s,o) (s)->p = (s)->data; s_assert_r(s,o); (s)->p += o;
/* Returns number of bytes that can still be read from STREAM */ /* Returns number of bytes that can still be read from STREAM */
#define s_remaining(s) (size_t)((s)->end - (s)->p) #define s_remaining(s) (size_t)((s)->end - (s)->p)
#define s_check_rem(s,n) (((s)->p <= (s)->end) && ((size_t)n <= s_remaining(s))) #define s_check_rem(s,n) (((s)->p <= (s)->end) && ((size_t)n <= s_remaining(s)))

18
tcp.c
View File

@ -399,8 +399,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;
@ -413,8 +413,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);
@ -466,11 +465,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)) {
@ -481,7 +479,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 */