/*****************************************************************************/ /* returns error */ /* This sends data out to the secure layer. */ int
xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id, int total_data_len, int flags)
{ struct mcs_channel_item *channel;
if (channel == NULL)
{
LOG(LOG_LEVEL_ERROR, "Request to send a message to non-existent channel_id %d",
channel_id); return1;
}
if (channel->disabled)
{
LOG(LOG_LEVEL_DEBUG, "Request to send a message to the disabled channel %s (%d)",
channel->name, channel_id); return0; /* not an error */
}
/*****************************************************************************/ /* returns error */ /* this will inform the callback, whatever it is that some channel data is
ready. the default for this is a call to xrdp_wm.c. */ staticint
xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s, int channel_id, int total_data_len, int flags)
{ struct xrdp_session *session; int rv; int size;
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
{
LOG(LOG_LEVEL_ERROR, "drdynvc_process_data: drdynvc_get_chan_id failed"); return1;
}
bytes = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA " "ChannelId %d, (re-assembled) Length %d, Data (omitted from the log)",
chan_id, bytes);
session = self->sec_layer->rdp_layer->session; if (chan_id > 255)
{
LOG(LOG_LEVEL_ERROR, "Received DYNVC_DATA PDU for an invalid " "channel id. channel id %d", chan_id); return1;
}
drdynvc = self->drdynvcs + chan_id; if (drdynvc->data != NULL)
{ return drdynvc->data(session->id, chan_id, s->p, bytes);
}
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): " "callback 'data' is NULL",
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
chan_id); return0;
}
/*****************************************************************************/ /** *Processa[MS-RDPBCGR]2.2.6.1VirtualChannelPDUandre-assemblethe *datachunksasneeded.
*/ staticint
xrdp_channel_process_drdynvc(struct xrdp_channel *self, struct mcs_channel_item *channel, struct stream *s)
{ int total_length; int length; int flags; int cmd; int rv; struct stream *ls;
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] CHANNEL_PDU_HEADER"))
{ return1;
}
in_uint32_le(s, total_length); /* length */
in_uint32_le(s, flags); /* flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER " "length %d, flags 0x%8.8x", total_length, flags);
ls = NULL; switch (flags & 3)
{ case0: /* not first chunk and not last chunk */
length = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (middle) " "length %d", length); if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " "the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s)); return1;
}
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */ return0; case1: /* CHANNEL_FLAG_FIRST */
free_stream(self->s);
make_stream(self->s);
init_stream(self->s, total_length);
length = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first) " "length %d", length); if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " "the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s)); return1;
}
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */ return0; case2: /* CHANNEL_FLAG_LAST */
length = (int) (s->end - s->p);
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (last) " "length %d", length); if (length > s_rem_out(self->s))
{
LOG(LOG_LEVEL_ERROR, "[MS-RDPBCGR] Data chunk length is bigger than " "the remaining chunk buffer size. length %d, remaining %d",
length, s_rem_out(self->s)); return1;
}
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
in_uint8s(s, length); /* virtualChannelData */
ls = self->s; break; case3: /* CHANNEL_FLAG_FIRST and CHANNEL_FLAG_LAST */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] data chunk (first and last) " "length %d", total_length);
ls = s; break; default:
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] data chunk with " "unknown flag 0x%8.8x", (int) (flags & 3)); return1;
} if (ls == NULL)
{
LOG(LOG_LEVEL_ERROR, "BUG: ls must not be NULL"); return1;
}
in_uint8(ls, cmd); /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPEDYC] " "cbId %d, Sp %d, Cmd 0x%2.2x",
(cmd & 0x03), (cmd & 0x0c) >> 2, (cmd & 0xf0) >> 4);
rv = 1; switch (cmd & 0xf0)
{ case CMD_DVC_CAPABILITY:
rv = drdynvc_process_capability_response(self, cmd, s); break; case CMD_DVC_OPEN_CHANNEL:
rv = drdynvc_process_open_channel_response(self, cmd, s); break; case CMD_DVC_CLOSE_CHANNEL:
rv = drdynvc_process_close_channel_response(self, cmd, s); break; case CMD_DVC_DATA_FIRST:
rv = drdynvc_process_data_first(self, cmd, s); break; case CMD_DVC_DATA:
rv = drdynvc_process_data(self, cmd, s); break; default:
LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPEDYC] with " "unknown command 0x%2.2x", cmd); break;
} return rv;
}
/*****************************************************************************/ /* Process a static ([MS-RDPBCGR] 2.2.6) or dynamic (MS-RDPEDYC 2.2.3) *virtualchannelmessage.
* returns error */ /* This is called from the secure layer to process an incoming non global channelpacket. 'chanid'passedinhereisthemcschannelidsoitMCS_GLOBAL_CHANNEL
plus something. */ int
xrdp_channel_process(struct xrdp_channel *self, struct stream *s, int chanid)
{ int length; int flags; int rv; int channel_id; struct mcs_channel_item *channel;
/* this assumes that the channels are in order of chanid(mcs channel id) buttheyshouldbe,seexrdp_sec_process_mcs_data_channels thefirstchannelshouldbeMCS_GLOBAL_CHANNEL+1,second
one should be MCS_GLOBAL_CHANNEL + 2, and so on */
channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1;
channel = xrdp_channel_get_item(self, channel_id); if (channel == NULL)
{
LOG(LOG_LEVEL_ERROR, "Received a message for an unknown channel id. channel id %d",
chanid); return1;
} if (channel->disabled)
{
LOG(LOG_LEVEL_WARNING, "Received a message for the disabled channel %s (%d)",
channel->name, chanid); return0; /* not an error */
} if (channel_id == self->drdynvc_channel_id)
{ return xrdp_channel_process_drdynvc(self, channel, s);
}
rv = 0;
in_uint32_le(s, length); /* length */
in_uint32_le(s, flags); /* flags */
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] CHANNEL_PDU_HEADER " "length %d, flags 0x%8.8x", length, flags);
rv = xrdp_channel_call_callback(self, s, channel_id, length, flags); return rv;
}
/*****************************************************************************/ /* Send a [MS-RDPEDYC] DYNVC_CAPS_VERSION2 message */ staticint
xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
{ struct stream *s; int flags; int total_data_len; int channel_id; char *phold;
/*****************************************************************************/ int
xrdp_channel_drdynvc_start(struct xrdp_channel *self)
{ int rv = 0;
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d",
self->drdynvc_channel_id); if (self->drdynvc_channel_id != -1)
{
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
} else
{ int index; int count; struct mcs_channel_item *ci; struct mcs_channel_item *dci;
dci = NULL;
count = self->mcs_layer->channel_list->count; for (index = 0; index < count; index++)
{
ci = (struct mcs_channel_item *)
list_get_item(self->mcs_layer->channel_list, index); if (ci != NULL)
{ if (g_strcasecmp(ci->name, DRDYNVC_SVC_CHANNEL_NAME) == 0)
{
dci = ci; break;
}
}
} if (dci == NULL)
{
LOG(LOG_LEVEL_WARNING, "Static channel '%s' not found.",
DRDYNVC_SVC_CHANNEL_NAME);
rv = -1;
} elseif (dci->disabled)
{
LOG(LOG_LEVEL_WARNING, "Static channel '%s' is disabled.",
DRDYNVC_SVC_CHANNEL_NAME);
rv = -1;
} else
{
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
LOG_DEVEL(LOG_LEVEL_DEBUG, DRDYNVC_SVC_CHANNEL_NAME "Initializing Dynamic Virtual Channel with channel id %d",
self->drdynvc_channel_id);
xrdp_channel_drdynvc_send_capability_request(self);
}
}
if (rv != 0)
{
LOG(LOG_LEVEL_WARNING, "Dynamic channels will not be available");
} return rv;
}
/*****************************************************************************/ /* *Senda[MS-RDPEDYC]DYNVC_CREATE_REQmessagetorequestthecreationofachannel.
*/ int
xrdp_channel_drdynvc_open(struct xrdp_channel *self, constchar *name, int flags, struct xrdp_drdynvc_procs *procs, int *chan_id)
{ struct stream *s; int ChId; int cbChId; int chan_pri; int static_channel_id; int name_length; int total_data_len; int static_flags; char *cmd_ptr;
make_stream(s);
init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_open: xrdp_channel_init failed");
free_stream(s); return1;
}
cmd_ptr = s->p;
out_uint8(s, 0); /* set later */
ChId = 1; while (self->drdynvcs[ChId].status != XRDP_DRDYNVC_STATUS_CLOSED)
{
ChId++; if (ChId > 255)
{
LOG(LOG_LEVEL_ERROR, "Attempting to create a new channel when the maximum " "number of channels have already been created. " "XRDP only supports 255 open channels.");
free_stream(s); return1;
}
}
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
name_length = g_strlen(name);
out_uint8a(s, name, name_length + 1); /* ChannelName */
chan_pri = 0; /* cbId (low 2 bits), Pri (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_OPEN_CHANNEL | ((chan_pri << 2) & 0x0c) | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
/*****************************************************************************/ /* *Senda[MS-RDPEDYC]DYNVC_CLOSEmessagetorequesttheclosingofachannel.
*/ int
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
{ struct stream *s; int ChId; int cbChId; int static_channel_id; int total_data_len; int static_flags; char *cmd_ptr;
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to close an invalid channel id. " "channel id %d", chan_id); return1;
} if ((self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN) &&
(self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN_SENT))
{ /* not open */
LOG(LOG_LEVEL_ERROR, "Attempting to close a channel that is not open. " "channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return1;
}
make_stream(s);
init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_close: xrdp_channel_init failed");
free_stream(s); return1;
}
cmd_ptr = s->p;
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */ /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_CLOSE_CHANNEL | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
/*****************************************************************************/ /* *Senda[MS-RDPEDYC]DYNVC_DATA_FIRSTmessage.
*/ int
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id, constchar *data, int data_bytes, int total_data_bytes)
{ struct stream *s; int ChId; int cbChId; int cbTotalDataSize; int static_channel_id; int total_data_len; int static_flags; char *cmd_ptr;
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid " "channel id. channel id %d", chan_id); return1;
} if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that " "is not open. channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return1;
} if (data_bytes > 1590)
{
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. " "data_bytes %d", chan_id, data_bytes); return1;
}
make_stream(s);
init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_data_first: xrdp_channel_init failed");
free_stream(s); return1;
}
cmd_ptr = s->p;
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes); /* Length */
out_uint8p(s, data, data_bytes); /* Data */ /* cbId (low 2 bits), Len (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_DATA_FIRST | (cbTotalDataSize << 2) | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_LAST;
s_mark_end(s);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA_FIRST " "cbId %d, Len %d, Cmd 0x%2.2x, ChannelId %d, Length %d",
cbChId, cbTotalDataSize, CMD_DVC_DATA_FIRST, ChId, total_data_bytes);
total_data_len = (int) (s->end - cmd_ptr); if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_data_first: xrdp_channel_send failed");
free_stream(s); return1;
}
free_stream(s); return0;
}
/*****************************************************************************/ /* *Senda[MS-RDPEDYC]DYNVC_DATAmessage.
*/ int
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id, constchar *data, int data_bytes)
{ struct stream *s; int ChId; int cbChId; int static_channel_id; int total_data_len; int static_flags; char *cmd_ptr;
if ((chan_id < 0) || (chan_id > 255))
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to an invalid " "channel id. channel id %d", chan_id); return1;
} if (self->drdynvcs[chan_id].status != XRDP_DRDYNVC_STATUS_OPEN)
{
LOG(LOG_LEVEL_ERROR, "Attempting to send data to a channel that " "is not open. channel id %d, channel status %s",
chan_id,
XRDP_DRDYNVC_STATUS_TO_STR(self->drdynvcs[chan_id].status)); return1;
} if (data_bytes > 1590)
{
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. " "data_bytes %d", chan_id, data_bytes); return1;
}
make_stream(s);
init_stream(s, 8192); if (xrdp_channel_init(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_data: xrdp_channel_init failed");
free_stream(s); return1;
}
cmd_ptr = s->p;
out_uint8(s, 0); /* set later */
ChId = chan_id;
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
out_uint8p(s, data, data_bytes); /* Data */ /* cbId (low 2 bits), Sp (2 bits), Cmd (hi 4 bits) */
cmd_ptr[0] = CMD_DVC_DATA | cbChId;
static_channel_id = self->drdynvc_channel_id;
static_flags = XR_CHANNEL_FLAG_FIRST | XR_CHANNEL_FLAG_LAST;
s_mark_end(s);
total_data_len = (int) (s->end - cmd_ptr);
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_DATA " "cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
cbChId, CMD_DVC_DATA_FIRST, ChId); if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
static_flags) != 0)
{
LOG(LOG_LEVEL_ERROR, "xrdp_channel_drdynvc_data: xrdp_channel_send failed");
free_stream(s); return1;
}
free_stream(s); return0;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-07-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.