chansrv: Use streams for dynamic channel processing
Change the dynamic channel processing to use streams rather than a data pointer and a length. This mirrors an earlier commit for xrdp. The reason for the change is to make it easier to check for buffer overflows using standard stream features.
This commit is contained in:
+9
-15
@@ -429,10 +429,10 @@ audin_close_response(int chan_id)
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
audin_data_fragment(int chan_id, char *data, int bytes)
|
||||
audin_data_fragment(int chan_id, struct stream *s)
|
||||
{
|
||||
int rv;
|
||||
|
||||
int bytes = s_rem(s);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "audin_data_fragment:");
|
||||
if (!s_check_rem(g_in_s, bytes))
|
||||
{
|
||||
@@ -440,7 +440,7 @@ audin_data_fragment(int chan_id, char *data, int bytes)
|
||||
bytes, (int) (g_in_s->end - g_in_s->p));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(g_in_s, data, bytes);
|
||||
out_uint8a(g_in_s, s->p, bytes);
|
||||
if (g_in_s->p == g_in_s->end)
|
||||
{
|
||||
g_in_s->p = g_in_s->data;
|
||||
@@ -454,7 +454,7 @@ audin_data_fragment(int chan_id, char *data, int bytes)
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
audin_data_first(int chan_id, char *data, int bytes, int total_bytes)
|
||||
audin_data_first(int chan_id, struct stream *s, int total_bytes)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "audin_data_first:");
|
||||
if (g_in_s != NULL)
|
||||
@@ -465,25 +465,19 @@ audin_data_first(int chan_id, char *data, int bytes, int total_bytes)
|
||||
make_stream(g_in_s);
|
||||
init_stream(g_in_s, total_bytes);
|
||||
g_in_s->end = g_in_s->data + total_bytes;
|
||||
return audin_data_fragment(chan_id, data, bytes);
|
||||
return audin_data_fragment(chan_id, s);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
audin_data(int chan_id, char *data, int bytes)
|
||||
audin_data(int chan_id, struct stream *s)
|
||||
{
|
||||
struct stream ls;
|
||||
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "audin_data:", data, bytes);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "audin_data:", s->p, s_rem(s));
|
||||
if (g_in_s == NULL)
|
||||
{
|
||||
g_memset(&ls, 0, sizeof(ls));
|
||||
ls.data = data;
|
||||
ls.p = ls.data;
|
||||
ls.end = ls.p + bytes;
|
||||
return audin_process_msg(chan_id, &ls);
|
||||
return audin_process_msg(chan_id, s);
|
||||
}
|
||||
return audin_data_fragment(chan_id, data, bytes);
|
||||
return audin_data_fragment(chan_id, s);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
+22
-38
@@ -100,8 +100,8 @@ struct chansrv_drdynvc
|
||||
int pad0;
|
||||
int (*open_response)(int chan_id, int creation_status);
|
||||
int (*close_response)(int chan_id);
|
||||
int (*data_first)(int chan_id, char *data, int bytes, int total_bytes);
|
||||
int (*data)(int chan_id, char *data, int bytes);
|
||||
int (*data_first)(int chan_id, struct stream *s, int total_bytes);
|
||||
int (*data)(int chan_id, struct stream *s);
|
||||
struct trans *xrdp_api_trans;
|
||||
};
|
||||
|
||||
@@ -657,32 +657,24 @@ static int
|
||||
process_message_drdynvc_data_first(struct stream *s)
|
||||
{
|
||||
struct chansrv_drdynvc *drdynvc;
|
||||
int chan_id;
|
||||
int bytes;
|
||||
uint32_t chan_id;
|
||||
int total_bytes;
|
||||
char *data;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_drdynvc_data_first:");
|
||||
if (!s_check_rem(s, 12))
|
||||
if (!s_check_rem(s, 8))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chan_id);
|
||||
in_uint32_le(s, bytes);
|
||||
in_uint32_le(s, total_bytes);
|
||||
if (!s_check_rem(s, bytes))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8p(s, data, bytes);
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
if (chan_id > 255)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
drdynvc = g_drdynvcs + chan_id;
|
||||
if (drdynvc->data_first != NULL)
|
||||
{
|
||||
if (drdynvc->data_first(chan_id, data, bytes, total_bytes) != 0)
|
||||
if (drdynvc->data_first(chan_id, s, total_bytes) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -697,9 +689,7 @@ static int
|
||||
process_message_drdynvc_data(struct stream *s)
|
||||
{
|
||||
struct chansrv_drdynvc *drdynvc;
|
||||
int chan_id;
|
||||
int bytes;
|
||||
char *data;
|
||||
uint32_t chan_id;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "process_message_drdynvc_data:");
|
||||
if (!s_check_rem(s, 8))
|
||||
@@ -707,16 +697,10 @@ process_message_drdynvc_data(struct stream *s)
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, chan_id);
|
||||
in_uint32_le(s, bytes);
|
||||
if (!s_check_rem(s, bytes))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8p(s, data, bytes);
|
||||
drdynvc = g_drdynvcs + chan_id;
|
||||
if (drdynvc->data != NULL)
|
||||
{
|
||||
if (drdynvc->data(chan_id, data, bytes) != 0)
|
||||
if (drdynvc->data(chan_id, s) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -1136,24 +1120,24 @@ my_api_close_response(int chan_id)
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
my_api_data_first(int chan_id, char *data, int bytes, int total_bytes)
|
||||
my_api_data_first(int chan_id, struct stream *s, int total_bytes)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
|
||||
struct stream *out_s;
|
||||
int bytes = s_rem(s);
|
||||
//g_writeln("my_api_data_first: bytes %d total_bytes %d", bytes, total_bytes);
|
||||
trans = get_api_trans_from_chan_id(chan_id);
|
||||
if (trans == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s = trans_get_out_s(trans, bytes);
|
||||
if (s == NULL)
|
||||
out_s = trans_get_out_s(trans, bytes);
|
||||
if (out_s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(s, data, bytes);
|
||||
s_mark_end(s);
|
||||
out_uint8a(out_s, s->p, bytes);
|
||||
s_mark_end(out_s);
|
||||
if (trans_write_copy(trans) != 0)
|
||||
{
|
||||
return 1;
|
||||
@@ -1163,24 +1147,24 @@ my_api_data_first(int chan_id, char *data, int bytes, int total_bytes)
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
my_api_data(int chan_id, char *data, int bytes)
|
||||
my_api_data(int chan_id, struct stream *s)
|
||||
{
|
||||
struct trans *trans;
|
||||
struct stream *s;
|
||||
struct stream *out_s;
|
||||
int bytes = s_rem(s);
|
||||
|
||||
//g_writeln("my_api_data: bytes %d", bytes);
|
||||
trans = get_api_trans_from_chan_id(chan_id);
|
||||
if (trans == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
s = trans_get_out_s(trans, bytes);
|
||||
if (s == NULL)
|
||||
out_s = trans_get_out_s(trans, bytes);
|
||||
if (out_s == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(s, data, bytes);
|
||||
s_mark_end(s);
|
||||
out_uint8a(out_s, s->p, bytes);
|
||||
s_mark_end(out_s);
|
||||
if (trans_write_copy(trans) != 0)
|
||||
{
|
||||
return 1;
|
||||
|
||||
@@ -62,8 +62,8 @@ struct chansrv_drdynvc_procs
|
||||
{
|
||||
int (*open_response)(int chan_id, int creation_status);
|
||||
int (*close_response)(int chan_id);
|
||||
int (*data_first)(int chan_id, char *data, int bytes, int total_bytes);
|
||||
int (*data)(int chan_id, char *data, int bytes);
|
||||
int (*data_first)(int chan_id, struct stream *s, int total_bytes);
|
||||
int (*data)(int chan_id, struct stream *s);
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
+4
-4
@@ -2148,7 +2148,7 @@ xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id,
|
||||
int bytes = s_rem(s);
|
||||
|
||||
// Size of PDU sent to chansrv
|
||||
int pdu_size = 8 + 8 + 4 + 4 + 4 + bytes;
|
||||
int pdu_size = 8 + 8 + 4 + 4 + bytes;
|
||||
wm = id->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
out_s = trans_get_out_s(trans, pdu_size);
|
||||
@@ -2162,8 +2162,8 @@ xrdp_mm_drdynvc_data_first(struct xrdp_process *id, int chan_id,
|
||||
out_uint32_le(out_s, pdu_size - 8);
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(out_s, chansrv_chan_id);
|
||||
out_uint32_le(out_s, bytes);
|
||||
out_uint32_le(out_s, total_bytes);
|
||||
// Caller works out 'bytes' value from incoming stream length
|
||||
out_uint8p(out_s, s->p, bytes);
|
||||
s_mark_end(out_s);
|
||||
return trans_write_copy(trans);
|
||||
@@ -2181,7 +2181,7 @@ xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, struct stream *s)
|
||||
int bytes = s_rem(s);
|
||||
|
||||
// Size of PDU sent to chansrv
|
||||
int pdu_size = 8 + 8 + 4 + 4 + bytes;
|
||||
int pdu_size = 8 + 8 + 4 + bytes;
|
||||
wm = id->wm;
|
||||
trans = wm->mm->chan_trans;
|
||||
out_s = trans_get_out_s(trans, pdu_size);
|
||||
@@ -2195,7 +2195,7 @@ xrdp_mm_drdynvc_data(struct xrdp_process *id, int chan_id, struct stream *s)
|
||||
out_uint32_le(out_s, pdu_size - 8);
|
||||
chansrv_chan_id = wm->mm->xr2cr_cid_map[chan_id];
|
||||
out_uint32_le(out_s, chansrv_chan_id);
|
||||
out_uint32_le(out_s, bytes);
|
||||
// Caller works out 'bytes' value from incoming stream length
|
||||
out_uint8p(out_s, s->p, bytes);
|
||||
s_mark_end(out_s);
|
||||
return trans_write_copy(trans);
|
||||
|
||||
Reference in New Issue
Block a user