Add detailed logging to libxrdp (#1742)
* Added s_rem(s) for getting the remaining bytes in a stream * Added s_rem_out() macro * Fixed 15bpp pointer error checking * Combined the 512 and 2048 bit certificate sending code paths * Other detailed comments and logging added following MS-RDPBCGR
This commit is contained in:
parent
42150c5c4f
commit
0ec471b02d
17
common/log.h
17
common/log.h
@ -22,6 +22,7 @@
|
||||
#include <pthread.h>
|
||||
|
||||
#include "arch.h"
|
||||
#include "defines.h"
|
||||
#include "list.h"
|
||||
|
||||
/* logging buffer size */
|
||||
@ -95,7 +96,7 @@ enum logReturns
|
||||
* @param ... the arguments for the printf format c-string
|
||||
*/
|
||||
#define LOG_DEVEL(log_level, args...) \
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
|
||||
|
||||
/**
|
||||
* @brief Logging macro for messages that are for a systeam administrator to
|
||||
@ -109,7 +110,7 @@ enum logReturns
|
||||
* @param ... the arguments for the printf format c-string
|
||||
*/
|
||||
#define LOG(log_level, args...) \
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args);
|
||||
log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
|
||||
|
||||
/**
|
||||
* @brief Logging macro for logging the contents of a byte array using a hex
|
||||
@ -124,12 +125,16 @@ enum logReturns
|
||||
* @param length, the length of the byte array to log
|
||||
*/
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) \
|
||||
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length);
|
||||
log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
|
||||
|
||||
#else
|
||||
#define LOG_DEVEL(log_level, args...)
|
||||
#define LOG(log_level, args...) log_message(log_level, args);
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length)
|
||||
#define LOG(log_level, args...) log_message(log_level, args)
|
||||
|
||||
/* Since log_message() returns a value ensure that the elided versions of
|
||||
* LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value
|
||||
*/
|
||||
#define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK)
|
||||
#define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -369,6 +369,15 @@
|
||||
#define PDUTYPE_DATAPDU 0x7
|
||||
#define PDUTYPE_SERVER_REDIR_PKT 0xA
|
||||
|
||||
#define PDUTYPE_TO_STR(pdu_type) \
|
||||
((pdu_type) == PDUTYPE_DEMANDACTIVEPDU ? "PDUTYPE_DEMANDACTIVEPDU" : \
|
||||
(pdu_type) == PDUTYPE_CONFIRMACTIVEPDU ? "PDUTYPE_CONFIRMACTIVEPDU" : \
|
||||
(pdu_type) == PDUTYPE_DEACTIVATEALLPDU ? "PDUTYPE_DEACTIVATEALLPDU" : \
|
||||
(pdu_type) == PDUTYPE_DATAPDU ? "PDUTYPE_DATAPDU" : \
|
||||
(pdu_type) == PDUTYPE_SERVER_REDIR_PKT ? "PDUTYPE_SERVER_REDIR_PKT" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
/* Share Data Header: pduType2 (2.2.8.1.1.1.2) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_DATA_PDU_UPDATE 2 /* PDUTYPE2_UPDATE */
|
||||
@ -378,6 +387,9 @@
|
||||
#define RDP_DATA_PDU_SYNCHRONISE 31
|
||||
#define PDUTYPE2_REFRESH_RECT 33
|
||||
#define RDP_DATA_PDU_PLAY_SOUND 34
|
||||
#define PDUTYPE2_SUPPRESS_OUTPUT 35
|
||||
#define PDUTYPE2_SHUTDOWN_REQUEST 36
|
||||
#define PDUTYPE2_SHUTDOWN_DENIED 37
|
||||
#define RDP_DATA_PDU_LOGON 38
|
||||
#define RDP_DATA_PDU_FONT2 39
|
||||
#define RDP_DATA_PDU_DISCONNECT 47
|
||||
@ -457,6 +469,14 @@
|
||||
#define RDP_UPDATE_PALETTE 2
|
||||
#define RDP_UPDATE_SYNCHRONIZE 3
|
||||
|
||||
#define GRAPHICS_UPDATE_TYPE_TO_STR(type) \
|
||||
((type) == RDP_UPDATE_ORDERS ? "RDP_UPDATE_ORDERS" : \
|
||||
(type) == RDP_UPDATE_BITMAP ? "RDP_UPDATE_BITMAP" : \
|
||||
(type) == RDP_UPDATE_PALETTE ? "RDP_UPDATE_PALETTE" : \
|
||||
(type) == RDP_UPDATE_SYNCHRONIZE ? "RDP_UPDATE_SYNCHRONIZE" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
/* Server Pointer Update PDU: messageType (2.2.9.1.1.4) */
|
||||
/* TODO: to be renamed */
|
||||
#define RDP_POINTER_SYSTEM 1 /* TS_PTRMSGTYPE_SYSTEM */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define PARSE_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "log.h"
|
||||
|
||||
#if defined(L_ENDIAN)
|
||||
#elif defined(B_ENDIAN)
|
||||
@ -54,17 +55,63 @@ struct stream
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check(s) ((s)->p <= (s)->end)
|
||||
#define s_check(s) s_check_rem(s, 0)
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_rem(s, n) ((s)->p + (n) <= (s)->end)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are at least n bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_rem_and_log(s, n, msg_prefix) \
|
||||
( s_check_rem((s), (n)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Not enough bytes in the stream: expected %d, remaining %d", \
|
||||
(msg_prefix), (n), s_rem(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_rem_out(s, n) ((s)->p + (n) <= (s)->data + (s)->size)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are at least n bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_rem_out_and_log(s, n, msg_prefix) \
|
||||
( s_check_rem_out((s), (n)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Not enough bytes in the stream: expected %d, remaining %d", \
|
||||
(msg_prefix), (n), s_rem_out(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_check_end(s) ((s)->p == (s)->end)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* @returns true if there are exactly 0 bytes remaining in the stream,
|
||||
* else false and logs an error message
|
||||
*/
|
||||
#define s_check_end_and_log(s, msg_prefix) \
|
||||
( s_check_end((s)) ? \
|
||||
1 : \
|
||||
LOG(LOG_LEVEL_ERROR, \
|
||||
"%s Expected to be at the end of the stream, " \
|
||||
"but there are %d bytes remaining", \
|
||||
(msg_prefix), s_rem(s)) \
|
||||
&& 0 )
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_rem(s) ((int) ((s)->end - (s)->p))
|
||||
|
||||
/******************************************************************************/
|
||||
#define s_rem_out(s) ((int) ((s)->data + (s)->size - (s)->p))
|
||||
|
||||
/******************************************************************************/
|
||||
#define make_stream(s) \
|
||||
(s) = (struct stream*)g_malloc(sizeof(struct stream), 1)
|
||||
|
@ -95,8 +95,8 @@
|
||||
* not yet sorted out
|
||||
*/
|
||||
|
||||
#define MCS_CONNECT_INITIAL 0x7f65
|
||||
#define MCS_CONNECT_RESPONSE 0x7f66
|
||||
#define MCS_CONNECT_INITIAL 0x7f65 /* MCS BER: big endian, class=application (0x4000), constructed (0x2000), tag number > 30 (0x1f00), tag number=101 (0x0065) */
|
||||
#define MCS_CONNECT_RESPONSE 0x7f66 /* MCS BER: application 102 */
|
||||
|
||||
#define BER_TAG_BOOLEAN 1
|
||||
#define BER_TAG_INTEGER 2
|
||||
|
@ -132,19 +132,19 @@ libxrdp_force_read(struct trans *trans)
|
||||
|
||||
if (trans_force_read(trans, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: header read error");
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: header read error");
|
||||
return NULL;
|
||||
}
|
||||
bytes = libxrdp_get_pdu_bytes(s->data);
|
||||
if (bytes < 4 || bytes > s->size)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: bad header length %d", bytes);
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: bad header length %d", bytes);
|
||||
return NULL;
|
||||
}
|
||||
if (trans_force_read(trans, bytes - 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "libxrdp_force_read: Can't read PDU");
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_force_read: Can't read PDU");
|
||||
return NULL;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -234,12 +234,16 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
dead_lock_counter++;
|
||||
break;
|
||||
case PDUTYPE_CONFIRMACTIVEPDU:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
|
||||
"[MS-RDPBCGR] PDUTYPE_CONFIRMACTIVEPDU");
|
||||
xrdp_caps_process_confirm_active(rdp, s);
|
||||
break;
|
||||
case PDUTYPE_DATAPDU:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Processing received "
|
||||
"[MS-RDPBCGR] PDUTYPE_DATAPDU");
|
||||
if (xrdp_rdp_process_data(rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_rdp_process_data failed");
|
||||
cont = 0;
|
||||
term = 1;
|
||||
}
|
||||
@ -247,13 +251,13 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
case 2: /* FASTPATH_INPUT_EVENT */
|
||||
if (xrdp_fastpath_process_input_event(rdp->sec_layer->fastpath_layer, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_data: xrdp_fastpath_process_input_event failed");
|
||||
cont = 0;
|
||||
term = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_ERROR, "unknown in libxrdp_process_data: code= %d", code);
|
||||
LOG(LOG_LEVEL_WARNING, "unknown code = %d (ignored)", code);
|
||||
dead_lock_counter++;
|
||||
break;
|
||||
}
|
||||
@ -262,8 +266,9 @@ libxrdp_process_data(struct xrdp_session *session, struct stream *s)
|
||||
{
|
||||
/*This situation can happen and this is a workaround*/
|
||||
cont = 0;
|
||||
LOG(LOG_LEVEL_ERROR, "Serious programming error: we were locked in a deadly loop");
|
||||
LOG(LOG_LEVEL_ERROR, "Remaining: %d", (int) (s->end - s->next_packet));
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Serious programming error: we were locked in a deadly loop. "
|
||||
"Remaining bytes: %d", (int) (s->end - s->next_packet));
|
||||
s->next_packet = 0;
|
||||
}
|
||||
|
||||
@ -292,7 +297,9 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_palette sending palette");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending palette (%s)",
|
||||
((session->client_info->use_fast_path & 1) ?
|
||||
"fastpath" : "slowpath"));
|
||||
|
||||
/* clear orders */
|
||||
libxrdp_orders_force_send(session);
|
||||
@ -301,25 +308,25 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_palette: slowpath");
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
}
|
||||
|
||||
/* TS_UPDATE_PALETTE_DATA */
|
||||
out_uint16_le(s, RDP_UPDATE_PALETTE);
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, 256); /* # of colors */
|
||||
out_uint16_le(s, 0);
|
||||
out_uint16_le(s, RDP_UPDATE_PALETTE); /* updateType */
|
||||
out_uint16_le(s, 0); /* pad2Octets */
|
||||
out_uint16_le(s, 256); /* # of colors (low-bytes) */
|
||||
out_uint16_le(s, 0); /* # of colors (high-bytes) */
|
||||
|
||||
/* paletteEntries */
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
color = palette[i];
|
||||
@ -331,15 +338,24 @@ libxrdp_send_palette(struct xrdp_session *session, int *palette)
|
||||
s_mark_end(s);
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_UPDATE_PALETTE "
|
||||
"paletteUpdateData = { updateType %d (UPDATETYPE_PALETTE), "
|
||||
"pad2Octets <ignored>, numberColors 256, "
|
||||
"paletteEntries <omitted from log> }", RDP_UPDATE_PALETTE);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_PALETTE) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_palette: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_PALETTE_DATA "
|
||||
"updateType %d (UPDATETYPE_PALETTE), pad2Octets <ignored>, "
|
||||
"numberColors 256, paletteEntries <omitted from log>",
|
||||
RDP_UPDATE_PALETTE);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
}
|
||||
@ -364,14 +380,12 @@ libxrdp_send_bell(struct xrdp_session *session)
|
||||
{
|
||||
struct stream *s = (struct stream *)NULL;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_bell sending bell signal");
|
||||
/* see MS documentation: Server play sound PDU, TS_PLAY_SOUND_PDU_DATA */
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
if (xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_init_data failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -384,6 +398,7 @@ libxrdp_send_bell(struct xrdp_session *session)
|
||||
|
||||
if (xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s, RDP_DATA_PDU_PLAY_SOUND) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_bell: xrdp_rdp_send_data failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -461,7 +476,7 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
total_bufsize = 0;
|
||||
num_updates = 0;
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP);
|
||||
out_uint16_le(s, RDP_UPDATE_BITMAP); /* updateType */
|
||||
p_num_updates = s->p;
|
||||
out_uint8s(s, 2); /* num_updates set later */
|
||||
|
||||
@ -564,6 +579,11 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
|
||||
p_num_updates[0] = num_updates;
|
||||
p_num_updates[1] = num_updates >> 8;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
|
||||
"updateType %d (UPDATETYPE_BITMAP), numberRectangles %d, "
|
||||
"rectangles <omitted from log>",
|
||||
RDP_UPDATE_BITMAP, num_updates);
|
||||
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
|
||||
@ -668,6 +688,10 @@ libxrdp_send_bitmap(struct xrdp_session *session, int width, int height,
|
||||
}
|
||||
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_UPDATE_BITMAP_DATA "
|
||||
"updateType %d (UPDATETYPE_BITMAP), numberRectangles 1, "
|
||||
"rectangles <omitted from log>",
|
||||
RDP_UPDATE_BITMAP);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_UPDATE);
|
||||
i = i + lines_sending;
|
||||
@ -692,7 +716,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
int j;
|
||||
int data_bytes;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_send_pointer sending cursor");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "sending cursor");
|
||||
if (bpp == 0)
|
||||
{
|
||||
bpp = 24;
|
||||
@ -702,14 +726,17 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
{
|
||||
if (bpp != 24)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error client does not support "
|
||||
"new cursors and bpp is %d", bpp);
|
||||
LOG(LOG_LEVEL_ERROR, "Send pointer: client does not support "
|
||||
"new cursors. The only valid bpp is 24, received %d", bpp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if ((bpp == 15) && (bpp != 16) && (bpp != 24) && (bpp != 32))
|
||||
|
||||
if ((bpp != 16) && (bpp != 24) && (bpp != 32))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: error");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Send pointer: invalid bpp value. Expected 16 or 24 or 32, "
|
||||
"received %d", bpp);
|
||||
return 1;
|
||||
}
|
||||
make_stream(s);
|
||||
@ -720,6 +747,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -731,7 +759,7 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
else
|
||||
{
|
||||
data_bytes = ((bpp + 7) / 8) * 32 * 32;
|
||||
out_uint16_le(s, bpp);
|
||||
out_uint16_le(s, bpp); /* TS_FP_POINTERATTRIBUTE -> newPointerUpdateData.xorBpp */
|
||||
}
|
||||
}
|
||||
else /* slowpath */
|
||||
@ -743,25 +771,34 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
out_uint16_le(s, RDP_POINTER_COLOR);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
data_bytes = 3072;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_COLOR), pad2Octets <ignored>",
|
||||
RDP_POINTER_COLOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint16_le(s, RDP_POINTER_POINTER);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
out_uint16_le(s, bpp);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_POINTER), pad2Octets <ignored>",
|
||||
RDP_POINTER_POINTER);
|
||||
|
||||
out_uint16_le(s, bpp); /* TS_POINTERATTRIBUTE -> xorBpp */
|
||||
data_bytes = ((bpp + 7) / 8) * 32 * 32;
|
||||
}
|
||||
}
|
||||
|
||||
/* the TS_COLORPOINTERATTRIBUTE field which is shared by
|
||||
all of the pointer attribute PDU types */
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
out_uint16_le(s, x); /* hotSpot.xPos */
|
||||
out_uint16_le(s, y); /* hotSpot.yPos */
|
||||
out_uint16_le(s, 32); /* width */
|
||||
out_uint16_le(s, 32); /* height */
|
||||
out_uint16_le(s, 128); /* lengthAndMask */
|
||||
out_uint16_le(s, data_bytes); /* lengthXorMask */
|
||||
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
out_uint16_le(s, x);
|
||||
out_uint16_le(s, y);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 32);
|
||||
out_uint16_le(s, 128);
|
||||
out_uint16_le(s, data_bytes);
|
||||
|
||||
/* xorMaskData */
|
||||
switch (bpp)
|
||||
{
|
||||
//case 15: /* coverity: this is logically dead code */
|
||||
@ -804,25 +841,42 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
break;
|
||||
}
|
||||
|
||||
out_uint8a(s, mask, 128); /* mask */
|
||||
out_uint8a(s, mask, 128); /* andMaskData */
|
||||
out_uint8(s, 0); /* pad */
|
||||
s_mark_end(s);
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
if ((session->client_info->pointer_flags & 1) == 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_COLORPOINTERATTRIBUTE "
|
||||
"cachedPointerUpdateData = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
cache_idx, x, y, data_bytes);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_COLOR) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_POINTERATTRIBUTE "
|
||||
"newPointerUpdateData.xorBpp %d, "
|
||||
"newPointerUpdateData.colorPtrAttr = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
bpp, cache_idx, x, y, data_bytes);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_POINTER) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -830,6 +884,26 @@ libxrdp_send_pointer(struct xrdp_session *session, int cache_idx,
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((session->client_info->pointer_flags & 1) == 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_COLORPOINTERATTRIBUTE "
|
||||
"cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log>",
|
||||
cache_idx, x, y, data_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_POINTERATTRIBUTE "
|
||||
"xorBpp %d, colorPtrAttr = { cacheIndex %d, "
|
||||
"hotSpot.xPos %d, hotSpot.yPos %d, width 32, "
|
||||
"height 32, lengthAndMask 128, lengthXorMask %d, "
|
||||
"xorMaskData <omitted from log>, "
|
||||
"andMaskData <omitted from log> }",
|
||||
bpp, cache_idx, x, y, data_bytes);
|
||||
}
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_POINTER);
|
||||
}
|
||||
@ -843,26 +917,26 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_set_pointer sending cursor index");
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: fastpath");
|
||||
if (xrdp_rdp_init_fastpath((struct xrdp_rdp *)session->rdp, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_init_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_pointer: slowpath");
|
||||
xrdp_rdp_init_data((struct xrdp_rdp *)session->rdp, s);
|
||||
out_uint16_le(s, RDP_POINTER_CACHED);
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_POINTER_PDU "
|
||||
"messageType %d (TS_PTRMSGTYPE_CACHED), pad2Octets <ignored>",
|
||||
RDP_POINTER_CACHED);
|
||||
}
|
||||
|
||||
out_uint16_le(s, cache_idx); /* cache_idx */
|
||||
@ -870,15 +944,20 @@ libxrdp_set_pointer(struct xrdp_session *session, int cache_idx)
|
||||
|
||||
if (session->client_info->use_fast_path & 1) /* fastpath output supported */
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FP_CACHEDPOINTERATTRIBUTE "
|
||||
"cachedPointerUpdateData.cacheIndex %d", cache_idx);
|
||||
if (xrdp_rdp_send_fastpath((struct xrdp_rdp *)session->rdp, s,
|
||||
FASTPATH_UPDATETYPE_CACHED) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_set_pointer: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_CACHEDPOINTERATTRIBUTE "
|
||||
"cacheIndex %d", cache_idx);
|
||||
xrdp_rdp_send_data((struct xrdp_rdp *)session->rdp, s,
|
||||
RDP_DATA_PDU_POINTER);
|
||||
}
|
||||
@ -1086,12 +1165,14 @@ libxrdp_reset(struct xrdp_session *session,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this will send any lingering orders */
|
||||
if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_orders_reset failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1103,12 +1184,14 @@ libxrdp_reset(struct xrdp_session *session,
|
||||
session->check_for_app_input = 0;
|
||||
if (xrdp_rdp_send_deactivate((struct xrdp_rdp *)session->rdp) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_rdp_send_deactivate failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this should do the resizing */
|
||||
if (xrdp_caps_send_demand_active((struct xrdp_rdp *)session->rdp) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: xrdp_caps_send_demand_active failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1178,24 +1261,26 @@ libxrdp_query_channel(struct xrdp_session *session, int index,
|
||||
|
||||
if (index < 0 || index >= count)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel out of range %d", index);
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel: Channel index out of range. "
|
||||
"max channel index %d, received channel index %d",
|
||||
count, index);
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
list_get_item(mcs->channel_list, index);
|
||||
|
||||
if (channel_item == 0)
|
||||
if (channel_item == NULL)
|
||||
{
|
||||
/* this should not happen */
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is 0");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - channel item is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel_name != 0)
|
||||
{
|
||||
g_strncpy(channel_name, channel_item->name, 8);
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_query_channel - Channel %d name %s", index, channel_name);
|
||||
LOG(LOG_LEVEL_DEBUG, "libxrdp_query_channel - Channel %d name %s", index, channel_name);
|
||||
}
|
||||
|
||||
if (channel_flags != 0)
|
||||
@ -1265,6 +1350,7 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
|
||||
if (xrdp_channel_init(chan, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1272,10 +1358,12 @@ libxrdp_send_to_channel(struct xrdp_session *session, int channel_id,
|
||||
/* here we make a copy of the data */
|
||||
out_uint8a(s, data, data_len);
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] Virtual Channel PDU "
|
||||
"data <omitted from log>");
|
||||
|
||||
if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: error, server channel data NOT sent to client channel");
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_send_to_channel: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1297,15 +1385,20 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
mcs = rdp->sec_layer->mcs_layer;
|
||||
if (mcs->channel_list == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Channel list is NULL");
|
||||
return 1;
|
||||
}
|
||||
channel_item = (struct mcs_channel_item *)
|
||||
list_get_item(mcs->channel_list, channel_id);
|
||||
if (channel_item == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Channel item is NULL");
|
||||
return 1;
|
||||
}
|
||||
channel_item->disabled = is_disabled;
|
||||
LOG(LOG_LEVEL_DEBUG, "%s channel %d (%s)",
|
||||
(is_disabled ? "Disabling" : "Enabling"), channel_item->chanid,
|
||||
channel_item->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1526,6 +1619,7 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_surface:");
|
||||
if ((session->client_info->use_fast_path & 1) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
|
||||
return 1;
|
||||
}
|
||||
max_bytes = session->client_info->max_fastpath_frag_bytes;
|
||||
@ -1539,10 +1633,16 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
cmd_bytes = 10 + 12;
|
||||
if (data_bytes + rdp_bytes + sec_bytes + cmd_bytes > max_bytes)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Too much data to send via fastpath. "
|
||||
"Max fastpath bytes %d, received bytes %d",
|
||||
max_bytes, (data_bytes + rdp_bytes + sec_bytes + cmd_bytes));
|
||||
return 1;
|
||||
}
|
||||
if (sec_bytes + rdp_bytes + cmd_bytes > pad_bytes)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Too much header to send via fastpath. "
|
||||
"Max fastpath header bytes %d, received bytes %d",
|
||||
pad_bytes, (rdp_bytes + sec_bytes + cmd_bytes));
|
||||
return 1;
|
||||
}
|
||||
g_memset(&ls, 0, sizeof(ls));
|
||||
@ -1558,6 +1658,13 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
out_uint16_le(s, destTop);
|
||||
out_uint16_le(s, destRight);
|
||||
out_uint16_le(s, destBottom);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_SURFCMD_STREAM_SURF_BITS "
|
||||
"cmdType 0x%4.4x (CMDTYPE_STREAM_SURFACE_BITS), destLeft %d, "
|
||||
"destTop %d, destRight %d, destBottom %d, "
|
||||
"bitmapData <see TS_BITMAP_DATA_EX>",
|
||||
CMDTYPE_STREAM_SURFACE_BITS, destLeft, destTop, destRight,
|
||||
destBottom);
|
||||
|
||||
/* TS_BITMAP_DATA_EX */
|
||||
out_uint8(s, bpp);
|
||||
out_uint8(s, 0);
|
||||
@ -1566,9 +1673,17 @@ libxrdp_fastpath_send_surface(struct xrdp_session *session,
|
||||
out_uint16_le(s, width);
|
||||
out_uint16_le(s, height);
|
||||
out_uint32_le(s, data_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding field bitmapData [MS-RDPBCGR] TS_BITMAP_DATA_EX "
|
||||
"bpp %d, flags 0x00, reserved 0, codecID %d, width %d, "
|
||||
"height %d, bitmapDataLength %d, exBitmapDataHeader <not present>, "
|
||||
"bitmapData <omitted from log>",
|
||||
bpp, codecID, width, height, data_bytes);
|
||||
|
||||
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
|
||||
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_fastpath_send_surface: xrdp_rdp_send_fastpath failed");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -1585,10 +1700,12 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_fastpath_send_frame_marker:");
|
||||
if ((session->client_info->use_fast_path & 1) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending data via fastpath is disabled");
|
||||
return 1;
|
||||
}
|
||||
if (session->client_info->use_frame_acks == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Fastpath frame acks is disabled");
|
||||
return 1;
|
||||
}
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
@ -1599,9 +1716,15 @@ libxrdp_fastpath_send_frame_marker(struct xrdp_session *session,
|
||||
out_uint16_le(s, frame_action);
|
||||
out_uint32_le(s, frame_id);
|
||||
s_mark_end(s);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPBCGR] TS_FRAME_MARKER "
|
||||
"cmdType 0x0004 (CMDTYPE_FRAME_MARKER), frameAction 0x%4.4x, "
|
||||
"frameId %d", frame_action, frame_id);
|
||||
|
||||
/* 4 = FASTPATH_UPDATETYPE_SURFCMDS */
|
||||
if (xrdp_rdp_send_fastpath(rdp, s, 4) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_fastpath_send_frame_marker: xrdp_rdp_send_fastpath failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -1616,7 +1739,6 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "libxrdp_send_session_info:");
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
return xrdp_rdp_send_session_info(rdp, data, data_bytes);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "file.h"
|
||||
#include "libxrdpinc.h"
|
||||
#include "xrdp_client_info.h"
|
||||
#include "log.h"
|
||||
|
||||
|
||||
/* iso */
|
||||
@ -549,9 +550,9 @@ xrdp_codec_jpeg_compress(void *handle,
|
||||
int cy, /* height of area to compress */
|
||||
int quality, /* higher numbers compress less */
|
||||
char *out_data, /* dest for jpg image */
|
||||
int *io_len /* length of out_data and on return */
|
||||
/* len of compressed data */
|
||||
);
|
||||
int *io_len /* length of out_data and on return
|
||||
len of compressed data */
|
||||
);
|
||||
|
||||
void *
|
||||
xrdp_jpeg_init(void);
|
||||
@ -559,7 +560,7 @@ int
|
||||
xrdp_jpeg_deinit(void *handle);
|
||||
|
||||
/* xrdp_channel.c */
|
||||
struct xrdp_channel*
|
||||
struct xrdp_channel *
|
||||
xrdp_channel_create(struct xrdp_sec *owner, struct xrdp_mcs *mcs_layer);
|
||||
void
|
||||
xrdp_channel_delete(struct xrdp_channel *self);
|
||||
|
@ -77,7 +77,8 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 10 + 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_general: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 12, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -103,6 +104,9 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process [MS-RDPBCGR] TS_ORDER_CAPABILITYSET (2.2.7.1.3) message.
|
||||
*/
|
||||
static int
|
||||
xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
@ -112,10 +116,10 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
int ex_flags;
|
||||
int cap_flags;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "order capabilities");
|
||||
if (len < 20 + 2 + 2 + 2 + 2 + 2 + 2 + 32 + 2 + 2 + 4 + 4 + 4 + 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_order: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 84, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 20); /* Terminal desc, pad */
|
||||
@ -127,33 +131,53 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
in_uint16_le(s, cap_flags); /* Capability flags */
|
||||
in_uint8a(s, order_caps, 32); /* Orders supported */
|
||||
g_memcpy(self->client_info.orders, order_caps, 32);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "dest blt-0 %d", order_caps[0]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "pat blt-1 %d", order_caps[1]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "screen blt-2 %d", order_caps[2]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "memblt-3-13 %d %d", order_caps[3], order_caps[13]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "triblt-4-14 %d %d", order_caps[4], order_caps[14]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "line-8 %d", order_caps[8]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "line-9 %d", order_caps[9]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "rect-10 %d", order_caps[10]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "desksave-11 %d", order_caps[11]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon-20 %d", order_caps[20]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polygon2-21 %d", order_caps[21]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "polyline-22 %d", order_caps[22]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse-25 %d", order_caps[25]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "ellipse2-26 %d", order_caps[26]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "text2-27 %d", order_caps[27]);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "order_caps dump", order_caps, 32);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: terminalDescriptor (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveXGranularity (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveYGranularity (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: maximumOrderLevel (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: numberFonts (ignored as per protocol spec)");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderFlags 0x%4.4x", cap_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 0: DstBlt %d", order_caps[0]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 1: PatBlt %d", order_caps[1]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 2: ScrBlt %d", order_caps[2]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 3,13: MemBlt %d %d", order_caps[3], order_caps[13]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 4,14: Mem3Blt %d %d", order_caps[4], order_caps[14]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 5-6: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 7: DrawNineGrid %d", order_caps[7]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 8: LineTo %d", order_caps[8]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 9: MultiDrawNineGrid %d", order_caps[9]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 10: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 11: SaveBitmap %d", order_caps[11]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 12-14: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 15: MultiDstBlt %d", order_caps[15]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 16: MultiPatBlt %d", order_caps[16]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 17: MultiScrBlt %d", order_caps[17]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 18: MultiOpaqueRect %d", order_caps[18]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 19: FastIndex %d", order_caps[19]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 20: PolygonSC %d", order_caps[20]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 21: PolygonCB %d", order_caps[21]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 22: Polyline %d", order_caps[22]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 23: unused index");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 24: FastGlyph %d", order_caps[24]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 25: EllipseSC %d", order_caps[25]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 26: EllipseCB %d", order_caps[26]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 27: GlyphIndex %d", order_caps[27]);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupport index 28-31: unused index");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: order_caps", order_caps, 32);
|
||||
|
||||
in_uint8s(s, 2); /* Text capability flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: textFlags (ignored as per protocol spec)");
|
||||
/* read extended order support flags */
|
||||
in_uint16_le(s, ex_flags); /* Ex flags */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: orderSupportExFlags 0x%4.4x", ex_flags);
|
||||
|
||||
if (cap_flags & 0x80) /* ORDER_FLAGS_EXTRA_SUPPORT */
|
||||
{
|
||||
self->client_info.order_flags_ex = ex_flags;
|
||||
if (ex_flags & XR_ORDERFLAGS_EX_CACHE_BITMAP_REV3_SUPPORT)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: bitmap cache v3 supported");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: bitmap cache v3 supported");
|
||||
self->client_info.bitmap_cache_version |= 4;
|
||||
}
|
||||
}
|
||||
@ -161,15 +185,15 @@ xrdp_caps_process_order(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
in_uint32_le(s, i); /* desktop cache size, usually 0x38400 */
|
||||
self->client_info.desktop_cache = i;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "desktop cache size %d", i);
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
in_uint8s(s, 4); /* Unknown */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "TS_ORDER_CAPABILITYSET: desktopSaveSize %d", i);
|
||||
in_uint8s(s, 4); /* Pad */
|
||||
in_uint8s(s, 4); /* Pad */
|
||||
|
||||
/* check if libpainter should be used for drawing, instead of orders */
|
||||
if (!(order_caps[TS_NEG_DSTBLT_INDEX] && order_caps[TS_NEG_PATBLT_INDEX] &&
|
||||
order_caps[TS_NEG_SCRBLT_INDEX] && order_caps[TS_NEG_MEMBLT_INDEX]))
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_order: not enough orders supported by client, using painter.");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Client Capability: not enough orders supported by client, using painter.");
|
||||
self->client_info.no_orders_supported = 1;
|
||||
}
|
||||
|
||||
@ -186,7 +210,8 @@ xrdp_caps_process_bmpcache(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 24 + 2 + 2 + 2 + 2 + 2 + 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 36, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 1;
|
||||
@ -229,7 +254,8 @@ xrdp_caps_process_bmpcache2(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 2 + 2 + 4 + 4 + 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_bmpcache2: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 16, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
self->client_info.bitmap_cache_version |= 2;
|
||||
@ -271,7 +297,8 @@ xrdp_caps_process_cache_v3_codec_id(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (len < 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_cache_v3_codec_id: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 1, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, codec_id);
|
||||
@ -421,13 +448,24 @@ xrdp_caps_process_rail(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
|
||||
if (len < 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_rail: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 4, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, i32);
|
||||
self->client_info.rail_support_level = i32;
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_rail: rail_support_level %d",
|
||||
self->client_info.rail_support_level);
|
||||
LOG(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - CAPSTYPE_RAIL "
|
||||
"RailSupportLevel 0x%8.8x (%s%s%s%s%s%s%s%s)",
|
||||
self->client_info.rail_support_level,
|
||||
(self->client_info.rail_support_level & 0x01) ? "TS_RAIL_LEVEL_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x02) ? "TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x04) ? "TS_RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x08) ? "TS_RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x10) ? "TS_RAIL_LEVEL_SERVER_TO_CLIENT_IME_SYNC_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x20) ? "TS_RAIL_LEVEL_HIDE_MINIMIZED_APPS_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x40) ? "TS_RAIL_LEVEL_WINDOW_CLOAKING_SUPPORTED " : "",
|
||||
(self->client_info.rail_support_level & 0x80) ? "TS_RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED " : ""
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -448,8 +486,8 @@ xrdp_caps_process_window(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
self->client_info.wnd_num_icon_caches = i32;
|
||||
in_uint16_le(s, i32);
|
||||
self->client_info.wnd_num_icon_cache_entries = i32;
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d "
|
||||
"wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_process_capset_window wnd_support_level %d, "
|
||||
"wnd_num_icon_caches %d, wnd_num_icon_cache_entries %d",
|
||||
self->client_info.wnd_support_level,
|
||||
self->client_info.wnd_num_icon_caches,
|
||||
self->client_info.wnd_num_icon_cache_entries);
|
||||
@ -593,6 +631,7 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
logging in debug mode */
|
||||
UNUSED_VAR(cmdFlags);
|
||||
#endif
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_process_surface_cmds:");
|
||||
in_uint32_le(s, cmdFlags);
|
||||
in_uint8s(s, 4); /* reserved */
|
||||
@ -601,6 +640,9 @@ xrdp_caps_process_surface_cmds(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU (2.2.1.13.2.1) message.
|
||||
*/
|
||||
int
|
||||
xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
{
|
||||
@ -612,7 +654,6 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
int len;
|
||||
char *p;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_process_confirm_active");
|
||||
in_uint8s(s, 4); /* rdp_shareid */
|
||||
in_uint8s(s, 2); /* userid */
|
||||
in_uint16_le(s, source_len); /* sizeof RDP_SOURCE */
|
||||
@ -620,118 +661,169 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
in_uint8s(s, source_len);
|
||||
in_uint16_le(s, num_caps);
|
||||
in_uint8s(s, 2); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
|
||||
"shareID (ignored), originatorID (ignored), lengthSourceDescriptor %d, "
|
||||
"lengthCombinedCapabilities %d, sourceDescriptor (ignored), "
|
||||
"numberCapabilities %d", source_len, cap_len, num_caps);
|
||||
|
||||
if ((cap_len < 0) || (cap_len > 1024 * 1024))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU "
|
||||
"lengthCombinedCapabilities %d is too long (> %d)",
|
||||
cap_len, 1024 * 1024);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (index = 0; index < num_caps; index++)
|
||||
{
|
||||
p = s->p;
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4,
|
||||
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error 1");
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, type);
|
||||
in_uint16_le(s, len);
|
||||
if ((len < 4) || !s_check_rem(s, len - 4))
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType %d, lengthCapability %d", type, len);
|
||||
if (len < 4)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Protocol error [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"lengthCapability must be greater than 3, received %d", len);
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem_and_log(s, len - 4,
|
||||
"Parsing [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_process_confirm_active: error: len %d, "
|
||||
"remaining %d", len, (int) (s->end - s->p));
|
||||
return 1;
|
||||
}
|
||||
len -= 4;
|
||||
switch (type)
|
||||
{
|
||||
case CAPSTYPE_GENERAL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GENERAL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_GENERAL");
|
||||
xrdp_caps_process_general(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAP:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAP");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAP - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_ORDER:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ORDER");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_ORDER");
|
||||
xrdp_caps_process_order(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAPCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BMPCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAPCACHE");
|
||||
xrdp_caps_process_bmpcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_CONTROL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_CONTROL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_CONTROL - Ignored");
|
||||
break;
|
||||
case 6:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = 6");
|
||||
xrdp_caps_process_cache_v3_codec_id(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_ACTIVATION:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_ACTIVAION");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_ACTIVATION - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_POINTER:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_POINTER");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_POINTER");
|
||||
xrdp_caps_process_pointer(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_SHARE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SHARE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_SHARE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_COLORCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_COLORCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_COLORCACHE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_SOUND:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_SOUND");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_SOUND - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_INPUT:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_INPUT");
|
||||
xrdp_caps_process_input(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_FONT:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_FONT");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_FONT - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_BRUSH:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BRUSH");
|
||||
xrdp_caps_process_brushcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_GLYPHCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_GLYPHCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_GLYPHCACHE");
|
||||
xrdp_caps_process_glyphcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_OFFSCREENCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_OFFSCREENCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_OFFSCREENCACHE");
|
||||
xrdp_caps_process_offscreen_bmpcache(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_BITMAPCACHE_REV2:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_BITMAPCACHE_REV2");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAPCACHE_REV2");
|
||||
xrdp_caps_process_bmpcache2(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_VIRTUALCHANNEL:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_VIRTUALCHANNEL");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_VIRTUALCHANNEL - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_DRAWNINGRIDCACHE:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWNINGRIDCACHE");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_DRAWNINGRIDCACHE - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_DRAWGDIPLUS:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "CAPSTYPE_DRAWGDIPLUS");
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_DRAWGDIPLUS - Ignored");
|
||||
break;
|
||||
case CAPSTYPE_RAIL:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_RAIL");
|
||||
xrdp_caps_process_rail(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_WINDOW:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_WINDOW");
|
||||
xrdp_caps_process_window(self, s, len);
|
||||
break;
|
||||
case CAPSSETTYPE_MULTIFRAGMENTUPDATE:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSSETTYPE_MULTIFRAGMENTUPDATE");
|
||||
xrdp_caps_process_multifragmentupdate(self, s, len);
|
||||
break;
|
||||
case CAPSETTYPE_SURFACE_COMMANDS:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSETTYPE_SURFACE_COMMANDS");
|
||||
xrdp_caps_process_surface_cmds(self, s, len);
|
||||
break;
|
||||
case CAPSSETTYPE_BITMAP_CODECS:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSSETTYPE_BITMAP_CODECS");
|
||||
xrdp_caps_process_codecs(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_FRAME_ACKNOWLEDGE:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_FRAME_ACKNOWLEDGE");
|
||||
xrdp_caps_process_frame_ack(self, s, len);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_WARNING, "unknown in xrdp_caps_process_confirm_active %d", type);
|
||||
LOG(LOG_LEVEL_WARNING, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = %d is unknown - Ignored", type);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -741,7 +833,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
if (self->client_info.no_orders_supported &&
|
||||
(self->client_info.offscreen_support_level != 0))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_confirm_active: not enough orders "
|
||||
LOG(LOG_LEVEL_WARNING, "Client Capability: not enough orders "
|
||||
"supported by client, client wants off screen bitmap but "
|
||||
"offscreen bitmaps disabled");
|
||||
self->client_info.offscreen_support_level = 0;
|
||||
@ -749,7 +841,7 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
self->client_info.offscreen_cache_entries = 0;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out xrdp_caps_process_confirm_active");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Completed processing received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
@ -771,10 +863,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "in xrdp_caps_send_demand_active");
|
||||
|
||||
if (xrdp_rdp_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -797,6 +889,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSTYPE_SHARE_LEN);
|
||||
out_uint16_le(s, self->mcs_channel);
|
||||
out_uint16_be(s, 0xb5e2); /* 0x73e1 */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_SHARE "
|
||||
"channel ID = 0x%x", self->mcs_channel);
|
||||
|
||||
/* Output general capability set */
|
||||
caps_count++;
|
||||
@ -820,6 +915,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0); /* Compression level */
|
||||
out_uint8(s, 1); /* refreshRectSupport */
|
||||
out_uint8(s, 1); /* suppressOutputSupport */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_GENERAL TODO");
|
||||
|
||||
/* Output bitmap capability set */
|
||||
caps_count++;
|
||||
@ -837,11 +934,15 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* unknown */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_BITMAP TODO");
|
||||
|
||||
/* Output font capability set */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_FONT);
|
||||
out_uint16_le(s, CAPSTYPE_FONT_LEN);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_FONT");
|
||||
|
||||
/* Output order capability set */
|
||||
caps_count++;
|
||||
@ -895,6 +996,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, 0x0f4240); /* desk save */
|
||||
out_uint32_le(s, 1); /* ? */
|
||||
out_uint32_le(s, 0); /* ? */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_ORDER "
|
||||
"TODO");
|
||||
|
||||
/* Output bmpcodecs capability set */
|
||||
caps_count++;
|
||||
@ -912,6 +1016,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0x01); /* fAllowDynamicFidelity */
|
||||
out_uint8(s, 0x01); /* fAllowSubsampling */
|
||||
out_uint8(s, 0x03); /* colorLossLevel */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"NSCODEC "
|
||||
"fAllowDynamicFidelity = 0x01,"
|
||||
"fAllowSubsampling = 0x01,"
|
||||
"colorLossLevel = 0x03");
|
||||
#if defined(XRDP_RFXCODEC) || defined(XRDP_NEUTRINORDP)
|
||||
/* remotefx */
|
||||
codec_caps_count++;
|
||||
@ -919,12 +1028,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 4); /* codecPropertiesLength */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"REMOTEFX");
|
||||
/* image remotefx */
|
||||
codec_caps_count++;
|
||||
out_uint8a(s, XR_CODEC_GUID_IMAGE_REMOTEFX, 16);
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 4); /* codecPropertiesLength */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"IMAGE_REMOTEFX");
|
||||
#endif
|
||||
/* jpeg */
|
||||
codec_caps_count++;
|
||||
@ -932,6 +1045,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint8(s, 0); /* codec id, client sets */
|
||||
out_uint16_le(s, 1); /* codecPropertiesLength */
|
||||
out_uint8(s, 75); /* jpeg compression ratio */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"JPEG: "
|
||||
"jpeg compression ratio = 75");
|
||||
/* calculate and set size and count */
|
||||
codec_caps_size = (int)(s->p - codec_caps_size_ptr);
|
||||
codec_caps_size += 2; /* 2 bytes for CAPSTYPE_BMPCODECS above */
|
||||
@ -945,6 +1061,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSTYPE_COLORCACHE_LEN);
|
||||
out_uint16_le(s, 6); /* cache size */
|
||||
out_uint16_le(s, 0); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_COLORCACHE: "
|
||||
"colorTableCacheSize = 6");
|
||||
|
||||
/* Output pointer capability set */
|
||||
caps_count++;
|
||||
@ -953,8 +1072,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 1); /* Colour pointer */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
out_uint16_le(s, 0x19); /* Cache size */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_POINTER: "
|
||||
"colorPointerFlag = true"
|
||||
"colorPointerCacheSize = 0x19"
|
||||
"pointerCacheSize = 0x19");
|
||||
|
||||
/* Output input capability set */
|
||||
/* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/b3bc76ae-9ee5-454f-b197-ede845ca69cc */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_INPUT);
|
||||
out_uint16_le(s, CAPSTYPE_INPUT_LEN);
|
||||
@ -970,6 +1095,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
}
|
||||
out_uint16_le(s, flags);
|
||||
out_uint8s(s, 82);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_INPUT: "
|
||||
"inputFlags = 0x%x", flags);
|
||||
|
||||
if (self->client_info.rail_enable) /* MS-RDPERP 3.3.5.1.4 */
|
||||
{
|
||||
@ -980,6 +1108,10 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, 3); /* See: https://msdn.microsoft.com/en-us/library/cc242518.aspx
|
||||
TS_RAIL_LEVEL_SUPPORTED
|
||||
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_RAIL: "
|
||||
"RailSupportLevel = "
|
||||
"TS_RAIL_LEVEL_SUPPORTED | TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED");
|
||||
|
||||
/* Window List Capability Set */
|
||||
caps_count++;
|
||||
@ -988,6 +1120,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint32_le(s, TS_WINDOW_LEVEL_SUPPORTED_EX);
|
||||
out_uint8(s, 3); /* NumIconCaches */
|
||||
out_uint16_le(s, 12); /* NumIconCacheEntries */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_WINDOW: "
|
||||
"WndSupportLevel = TS_WINDOW_LEVEL_SUPPORTED_EX, "
|
||||
"NumIconCaches = 3,"
|
||||
"NumIconCacheEntries = 12");
|
||||
}
|
||||
|
||||
/* 6 - bitmap cache v3 codecid */
|
||||
@ -995,6 +1132,8 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, 0x0006);
|
||||
out_uint16_le(s, 5);
|
||||
out_uint8(s, 0); /* client sets */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"0x0006 = 0");
|
||||
|
||||
if (self->client_info.use_fast_path & FASTPATH_OUTPUT_SUPPORTED) /* fastpath output on */
|
||||
{
|
||||
@ -1003,12 +1142,16 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE);
|
||||
out_uint16_le(s, CAPSSETTYPE_MULTIFRAGMENTUPDATE_LEN);
|
||||
out_uint32_le(s, 3 * 1024 * 1024); /* 3MB */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSSETTYPE_MULTIFRAGMENTUPDATE = 3MB");
|
||||
|
||||
/* frame acks */
|
||||
caps_count++;
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE);
|
||||
out_uint16_le(s, CAPSTYPE_FRAME_ACKNOWLEDGE_LEN);
|
||||
out_uint32_le(s, 2); /* 2 frames in flight */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSTYPE_FRAME_ACKNOWLEDGE = 2 frames");
|
||||
|
||||
/* surface commands */
|
||||
caps_count++;
|
||||
@ -1018,6 +1161,9 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
SURFCMDS_FRAMEMARKER |
|
||||
SURFCMDS_STREAMSUFRACEBITS)); /* cmdFlags */
|
||||
out_uint32_le(s, 0); /* reserved */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: Server Capability "
|
||||
"CAPSETTYPE_SURFACE_COMMANDS = "
|
||||
"SURFCMDS_SETSURFACEBITS | SURFCMDS_FRAMEMARKER | SURFCMDS_STREAMSUFRACEBITS");
|
||||
}
|
||||
|
||||
out_uint8s(s, 4); /* pad */
|
||||
@ -1033,12 +1179,14 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
caps_count_ptr[2] = caps_count >> 16;
|
||||
caps_count_ptr[3] = caps_count >> 24;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: sending PDUTYPE_DEMANDACTIVEPDU "
|
||||
"message with the server's capabilities");
|
||||
if (xrdp_rdp_send(self, s, PDUTYPE_DEMANDACTIVEPDU) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_caps_send_demand_active: xrdp_rdp_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "out (1) xrdp_caps_send_demand_active");
|
||||
|
||||
/* send Monitor Layout PDU for dual monitor */
|
||||
if (self->client_info.monitorCount > 0 &&
|
||||
|
@ -43,6 +43,19 @@
|
||||
#define XRDP_DRDYNVC_STATUS_OPEN 2
|
||||
#define XRDP_DRDYNVC_STATUS_CLOSE_SENT 3
|
||||
|
||||
#define XRDP_DRDYNVC_STATUS_TO_STR(status) \
|
||||
((status) == XRDP_DRDYNVC_STATUS_CLOSED ? "CLOSED" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_OPEN_SENT ? "OPEN_SENT" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_OPEN ? "OPEN" : \
|
||||
(status) == XRDP_DRDYNVC_STATUS_CLOSE_SENT ? "CLOSE_SENT" : \
|
||||
"unknown" \
|
||||
)
|
||||
|
||||
#define XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id) \
|
||||
(xrdp_channel_get_item((self), (chan_id)) != NULL \
|
||||
? xrdp_channel_get_item((self), (chan_id))->name \
|
||||
: "unknown")
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns pointer or nil on error */
|
||||
static struct mcs_channel_item *
|
||||
@ -52,7 +65,7 @@ xrdp_channel_get_item(struct xrdp_channel *self, int channel_id)
|
||||
|
||||
if (self->mcs_layer->channel_list == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_get_item - No channel initialized");
|
||||
LOG(LOG_LEVEL_WARNING, "Channel list is NULL, returning NULL");
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
@ -95,6 +108,7 @@ xrdp_channel_init(struct xrdp_channel *self, struct stream *s)
|
||||
{
|
||||
if (xrdp_sec_init(self->sec_layer, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_init: xrdp_sec_init failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -115,13 +129,17 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
|
||||
if (channel == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - no such channel");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Request to send a message to non-existent channel_id %d",
|
||||
channel_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (channel->disabled)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_channel_send, channel disabled");
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"Request to send a message to the disabled channel %s (%d)",
|
||||
channel->name, channel_id);
|
||||
return 0; /* not an error */
|
||||
}
|
||||
|
||||
@ -145,10 +163,12 @@ xrdp_channel_send(struct xrdp_channel *self, struct stream *s, int channel_id,
|
||||
// }
|
||||
|
||||
out_uint32_le(s, flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] CHANNEL_PDU_HEADER "
|
||||
"length %d, flags 0x%8.8x", total_data_len, flags);
|
||||
|
||||
if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send - failure sending data");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_send: xrdp_sec_send failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -183,18 +203,28 @@ xrdp_channel_call_callback(struct xrdp_channel *self, struct stream *s,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session->callback is nil");
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "session->callback is NULL");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_TRACE, "in xrdp_channel_call_callback, session is nil");
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "session is NULL");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Write a variable length unsigned int (1, 2, or 4 bytes) to the stream.
|
||||
*
|
||||
* The number of bytes written is the minimum number of bytes needed to
|
||||
* represent the value.
|
||||
*
|
||||
* @param s the stream to write to
|
||||
* @param val the value to write
|
||||
* @return the DYNVC cbId length code for the number of bytes written (see [MS-RDPEDYC] 2.2.2.1)
|
||||
*/
|
||||
static int
|
||||
drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
{
|
||||
@ -220,6 +250,17 @@ drdynvc_insert_uint_124(struct stream *s, uint32_t val)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Read a variable length unsigned int (1, 2, or 4 bytes) from the stream.
|
||||
*
|
||||
* The number of bytes read is determined by the cbId bit field flag in the
|
||||
* cmd argument (see [MS-RDPEDYC] 2.2.2.1).
|
||||
*
|
||||
* @param s [in] the stream to read from
|
||||
* @param cmd [in] the cmd byte which contains the cbId bit field flag
|
||||
* @param chan_id_p [out] a pointer to the value read from the stream
|
||||
* @return error code
|
||||
*/
|
||||
static int
|
||||
drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
{
|
||||
@ -229,7 +270,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
cbChId = cmd & 0x03;
|
||||
if (cbChId == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -237,7 +278,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
else if (cbChId == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -245,7 +286,7 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] channel id"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -256,6 +297,9 @@ drdynvc_get_chan_id(struct stream *s, char cmd, uint32_t *chan_id_p)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CAPS_RSP message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -264,18 +308,22 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
int cap_version;
|
||||
int rv;
|
||||
|
||||
/* skip padding */
|
||||
in_uint8s(s, 1);
|
||||
/* read client's version */
|
||||
in_uint16_le(s, cap_version);
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
if (!s_check_rem_and_log(s, 3, "Parsing [MS-RDPEDYC] DYNVC_CAPS_RSP"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "drdynvc_process_capability_response: incompatible DVC "
|
||||
"version %d detected", cap_version);
|
||||
return 1;
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO, "drdynvc_process_capability_response: DVC version %d selected",
|
||||
cap_version);
|
||||
in_uint8s(s, 1); /* skip padding */
|
||||
in_uint16_le(s, cap_version); /* Version */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CAPS_RSP "
|
||||
"version %d", cap_version);
|
||||
|
||||
if ((cap_version != 2) && (cap_version != 3))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Dynamic Virtual Channel version %d is not supported",
|
||||
cap_version);
|
||||
return 1;
|
||||
}
|
||||
self->drdynvc_state = 1;
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
rv = session->callback(session->id, 0x5558, 0, 0, 0, 0);
|
||||
@ -283,6 +331,9 @@ drdynvc_process_capability_response(struct xrdp_channel *self,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CREATE_RSP message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -292,22 +343,27 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP failed");
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_CREATE_RSP"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!s_check_rem(s, 4))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, creation_status);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_open_channel_response: chan_id 0x%x "
|
||||
"creation_status %d", chan_id, creation_status);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
in_uint32_le(s, creation_status); /* CreationStatus */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP "
|
||||
"ChannelId %d, CreationStatus %d", chan_id, creation_status);
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_CREATE_RSP for an "
|
||||
"invalid channel id. Max allowed 255, received %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
if (creation_status == 0)
|
||||
{
|
||||
@ -317,14 +373,26 @@ drdynvc_process_open_channel_response(struct xrdp_channel *self,
|
||||
{
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Dynamic Virtual Channel %s (%d) updated: status = %s",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
|
||||
if (drdynvc->open_response != NULL)
|
||||
{
|
||||
return drdynvc->open_response(session->id, chan_id, creation_status);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'open_response' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_CLOSE message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_close_channel_response(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -333,26 +401,45 @@ drdynvc_process_close_channel_response(struct xrdp_channel *self,
|
||||
uint32_t chan_id;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"drdynvc_process_close_channel_response: drdynvc_get_chan_id failed");
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_close_channel_response: chan_id 0x%x", chan_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_CLOSE "
|
||||
"ChannelId %d", chan_id);
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received message for an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
drdynvc->status = XRDP_DRDYNVC_STATUS_CLOSED;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Dynamic Virtual Channel %s (%d) updated: status = %s",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id,
|
||||
XRDP_DRDYNVC_STATUS_TO_STR(drdynvc->status));
|
||||
|
||||
if (drdynvc->close_response != NULL)
|
||||
{
|
||||
return drdynvc->close_response(session->id, chan_id);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'close_response' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -364,40 +451,47 @@ drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
int total_bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST failed");
|
||||
return 1;
|
||||
}
|
||||
len = (cmd >> 2) & 0x03;
|
||||
if (len == 0)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, total_bytes);
|
||||
in_uint8(s, total_bytes); /* Length */
|
||||
}
|
||||
else if (len == 1)
|
||||
{
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, total_bytes);
|
||||
in_uint16_le(s, total_bytes); /* Length */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!s_check_rem(s, 4))
|
||||
if (!s_check_rem_and_log(s, 4, "Parsing [MS-RDPEDYC] DYNVC_DATA_FIRST"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_bytes);
|
||||
in_uint32_le(s, total_bytes); /* Length */
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data_first: bytes %d total_bytes %d", bytes, total_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST "
|
||||
"ChannelId %d, Length %d, Data (omitted from the log)",
|
||||
chan_id, total_bytes);
|
||||
|
||||
session = self->sec_layer->rdp_layer->session;
|
||||
if (chan_id > 255)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPEDYC] DYNVC_DATA_FIRST for an "
|
||||
"invalid channel id. Max allowed 255, received %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
@ -406,10 +500,17 @@ drdynvc_process_data_first(struct xrdp_channel *self,
|
||||
return drdynvc->data_first(session->id, chan_id, s->p,
|
||||
bytes, total_bytes);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Dynamic Virtual Channel %s (%d): "
|
||||
"callback 'data_first' is NULL",
|
||||
XRDP_DRDYNVC_CHANNEL_ID_TO_NAME(self, chan_id),
|
||||
chan_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process a [MS-RDPEDYC] DYNVC_DATA message.
|
||||
*/
|
||||
static int
|
||||
drdynvc_process_data(struct xrdp_channel *self,
|
||||
int cmd, struct stream *s)
|
||||
@ -419,15 +520,20 @@ drdynvc_process_data(struct xrdp_channel *self,
|
||||
int bytes;
|
||||
struct xrdp_drdynvc *drdynvc;
|
||||
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0)
|
||||
if (drdynvc_get_chan_id(s, cmd, &chan_id) != 0) /* ChannelId */
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "drdynvc_process_data: drdynvc_get_chan_id failed");
|
||||
return 1;
|
||||
}
|
||||
bytes = (int) (s->end - s->p);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "drdynvc_process_data: bytes %d", bytes);
|
||||
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 message for an invalid "
|
||||
"channel id. channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
drdynvc = self->drdynvcs + chan_id;
|
||||
@ -435,10 +541,18 @@ drdynvc_process_data(struct xrdp_channel *self,
|
||||
{
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Process a [MS-RDPBCGR] 2.2.6.1 Virtual Channel PDU and re-assemble the
|
||||
* data chunks as needed.
|
||||
*/
|
||||
static int
|
||||
xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
struct mcs_channel_item *channel,
|
||||
@ -451,61 +565,82 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
int rv;
|
||||
struct stream *ls;
|
||||
|
||||
if (!s_check_rem(s, 8))
|
||||
if (!s_check_rem_and_log(s, 8, "Parsing [MS-RDPBCGR] CHANNEL_PDU_HEADER"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint32_le(s, total_length);
|
||||
in_uint32_le(s, flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: total_length %d flags 0x%8.8x",
|
||||
total_length, flags);
|
||||
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)
|
||||
{
|
||||
case 0:
|
||||
case 0: /* not first chunk and not last chunk */
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
return 0;
|
||||
case 1:
|
||||
case 1: /* CHANNEL_FLAG_FIRST */
|
||||
free_stream(self->s);
|
||||
make_stream(self->s);
|
||||
init_stream(self->s, total_length);
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
return 0;
|
||||
case 2:
|
||||
case 2: /* CHANNEL_FLAG_LAST */
|
||||
length = (int) (s->end - s->p);
|
||||
if (!s_check_rem_out(self->s, length))
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
out_uint8a(self->s, s->p, length);
|
||||
in_uint8s(s, length);
|
||||
out_uint8a(self->s, s->p, length); /* append data to chunk buffer */
|
||||
in_uint8s(s, length); /* virtualChannelData */
|
||||
ls = self->s;
|
||||
break;
|
||||
case 3:
|
||||
case 3: /* 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, "xrdp_channel_process_drdynvc: error");
|
||||
LOG(LOG_LEVEL_ERROR, "Received [MS-RDPBCGR] data chunk with "
|
||||
"unknown flag 0x%8.8x", (int) (flags & 3));
|
||||
return 1;
|
||||
}
|
||||
if (ls == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "BUG: ls must not be NULL");
|
||||
return 1;
|
||||
}
|
||||
in_uint8(ls, cmd); /* read command */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: cmd 0x%x", cmd);
|
||||
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)
|
||||
{
|
||||
@ -525,16 +660,17 @@ xrdp_channel_process_drdynvc(struct xrdp_channel *self,
|
||||
rv = drdynvc_process_data(self, cmd, s);
|
||||
break;
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: got unknown "
|
||||
"command 0x%x", cmd);
|
||||
LOG(LOG_LEVEL_ERROR, "Received header [MS-RDPEDYC] with "
|
||||
"unknown command 0x%2.2x", cmd);
|
||||
break;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_process_drdynvc: rv %d", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process a static ([MS-RDPBCGR] 2.2.6) or dynamic (MS-RDPEDYC 2.2.3)
|
||||
* virtual channel message.
|
||||
* returns error */
|
||||
/* This is called from the secure layer to process an incoming non global
|
||||
channel packet.
|
||||
'chanid' passed in here is the mcs channel id so it MCS_GLOBAL_CHANNEL
|
||||
@ -557,12 +693,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
channel = xrdp_channel_get_item(self, channel_id);
|
||||
if (channel == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_channel_process, channel not found");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Received a message for an unknown channel id. channel id %d",
|
||||
chanid);
|
||||
return 1;
|
||||
}
|
||||
if (channel->disabled)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_channel_process, channel disabled");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Received a message for the disabled channel %s (%d)",
|
||||
channel->name, chanid);
|
||||
return 0; /* not an error */
|
||||
}
|
||||
if (channel_id == self->drdynvc_channel_id)
|
||||
@ -570,14 +710,16 @@ xrdp_channel_process(struct xrdp_channel *self, struct stream *s,
|
||||
return xrdp_channel_process_drdynvc(self, channel, s);
|
||||
}
|
||||
rv = 0;
|
||||
in_uint32_le(s, length);
|
||||
in_uint32_le(s, flags);
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* drdynvc */
|
||||
/* Send a [MS-RDPEDYC] DYNVC_CAPS_VERSION2 message */
|
||||
static int
|
||||
xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
{
|
||||
@ -592,11 +734,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
init_stream(s, 8192);
|
||||
if (xrdp_channel_init(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_init failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
phold = s->p;
|
||||
out_uint8(s, 0x50); /* insert cmd */
|
||||
out_uint8(s, 0x50); /* insert cbId (2 bits), Sp (2 bits), cmd (4 bits) */
|
||||
out_uint8(s, 0x00); /* insert padding */
|
||||
out_uint16_le(s, 2); /* insert version */
|
||||
/* channel priority unused for now */
|
||||
@ -609,8 +753,13 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
total_data_len = (int) (s->end - phold);
|
||||
flags = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
channel_id = self->drdynvc_channel_id;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CAPS_VERSION2 "
|
||||
"cbId 0, Sp 0, Cmd 0x05, Version 2, PriorityCharge0 0, "
|
||||
"PriorityCharge1 0, PriorityCharge2 0, PriorityCharge3 0");
|
||||
if (xrdp_channel_send(self, s, channel_id, total_data_len, flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_send_capability_request: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -627,7 +776,7 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_channel_drdynvc_start:");
|
||||
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
@ -645,12 +794,24 @@ xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
if (dci != NULL)
|
||||
{
|
||||
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Initializing Dynamic Virtual Channel with channel id %d",
|
||||
self->drdynvc_channel_id);
|
||||
xrdp_channel_drdynvc_send_capability_request(self);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Dynamic Virtual Channel named 'drdynvc' not found, "
|
||||
"channel not initialized");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_CREATE_REQ message to request the creation of a channel.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
@ -670,33 +831,46 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId); /* ChannelId */
|
||||
name_length = g_strlen(name);
|
||||
out_uint8a(s, name, name_length + 1);
|
||||
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 = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CREATE_REQ "
|
||||
"cbId %d, Pri %d, Cmd 0x%2.2x, ChannelId %d, ChannelName [%s]",
|
||||
cbChId, chan_pri, CMD_DVC_OPEN_CHANNEL, ChId, name);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Sending [MS-RDPEDYC] DYNVC_CREATE_REQ failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -711,6 +885,9 @@ xrdp_channel_drdynvc_open(struct xrdp_channel *self, const char *name,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_CLOSE message to request the closing of a channel.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
{
|
||||
@ -724,33 +901,48 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
|
||||
if ((chan_id < 0) || (chan_id > 255))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Attempting to close an invalid channel id. "
|
||||
"channel id %d", chan_id);
|
||||
return 1;
|
||||
}
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
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 = CHANNEL_FLAG_FIRST | CHANNEL_FLAG_LAST;
|
||||
s_mark_end(s);
|
||||
total_data_len = (int) (s->end - cmd_ptr);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [MS-RDPEDYC] DYNVC_CLOSE "
|
||||
"cbId %d, Sp 0, Cmd 0x%2.2x, ChannelId %d",
|
||||
cbChId, CMD_DVC_OPEN_CHANNEL, ChId);
|
||||
if (xrdp_channel_send(self, s, static_channel_id, total_data_len,
|
||||
static_flags) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_channel_drdynvc_open: xrdp_channel_send failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -760,6 +952,9 @@ xrdp_channel_drdynvc_close(struct xrdp_channel *self, int chan_id)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_DATA_FIRST message.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes,
|
||||
@ -776,37 +971,53 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
|
||||
"data_bytes %d", chan_id, data_bytes);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
cbTotalDataSize = drdynvc_insert_uint_124(s, total_data_bytes);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
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 = CHANNEL_FLAG_FIRST | 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);
|
||||
return 1;
|
||||
}
|
||||
@ -815,6 +1026,9 @@ xrdp_channel_drdynvc_data_first(struct xrdp_channel *self, int chan_id,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [MS-RDPEDYC] DYNVC_DATA message.
|
||||
*/
|
||||
int
|
||||
xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
const char *data, int data_bytes)
|
||||
@ -829,36 +1043,52 @@ xrdp_channel_drdynvc_data(struct xrdp_channel *self, int chan_id,
|
||||
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
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));
|
||||
return 1;
|
||||
}
|
||||
if (data_bytes > 1590)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Payload for channel id %d is is too big. "
|
||||
"data_bytes %d", chan_id, data_bytes);
|
||||
return 1;
|
||||
}
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
cmd_ptr = s->p;
|
||||
out_uint8(s, 0);
|
||||
out_uint8(s, 0); /* set later */
|
||||
ChId = chan_id;
|
||||
cbChId = drdynvc_insert_uint_124(s, ChId);
|
||||
out_uint8p(s, data, data_bytes);
|
||||
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 = CHANNEL_FLAG_FIRST | 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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -30,12 +30,11 @@ xrdp_fastpath_create(struct xrdp_sec *owner, struct trans *trans)
|
||||
{
|
||||
struct xrdp_fastpath *self;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_create");
|
||||
self = (struct xrdp_fastpath *)g_malloc(sizeof(struct xrdp_fastpath), 1);
|
||||
self->sec_layer = owner;
|
||||
self->trans = trans;
|
||||
self->session = owner->rdp_layer->session;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_create");
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -63,13 +62,13 @@ int
|
||||
xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
{
|
||||
int fp_hdr;
|
||||
int len = 0; /* unused */
|
||||
int len = 0;
|
||||
int byte;
|
||||
char *holdp;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " in xrdp_fastpath_recv");
|
||||
|
||||
holdp = s->p;
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -84,7 +83,7 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
byte &= ~(0x80);
|
||||
len = (byte << 8);
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_PDU length2"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -97,7 +96,10 @@ xrdp_fastpath_recv(struct xrdp_fastpath *self, struct stream *s)
|
||||
len = byte;
|
||||
}
|
||||
s->next_packet = holdp + len;
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, " out xrdp_fastpath_recv");
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [MS-RDPBCGR] TS_FP_INPUT_PDU "
|
||||
"fpInputHeader.action (ignored), fpInputHeader.numEvents %d, "
|
||||
"fpInputHeader.flags 0x%1.1x, length %d",
|
||||
self->numEvents, self->secFlags, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -134,6 +136,10 @@ xrdp_fastpath_session_callback(struct xrdp_fastpath *self, int msg,
|
||||
self->session->callback(self->session->id, msg,
|
||||
param1, param2, param3, param4);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING, "Bug: session is NULL");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -163,11 +169,14 @@ xrdp_fastpath_process_EVENT_SCANCODE(struct xrdp_fastpath *self,
|
||||
int code;
|
||||
flags = 0;
|
||||
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8(s, code); /* keyCode (1 byte) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_KEYBOARD_EVENT "
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"keyCode %d", eventFlags, code);
|
||||
|
||||
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
|
||||
{
|
||||
@ -205,13 +214,16 @@ xrdp_fastpath_process_EVENT_MOUSE(struct xrdp_fastpath *self,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2 + 2 + 2))
|
||||
if (!s_check_rem_and_log(s, 2 + 2 + 2, "Parsing [MS-RDPBCGR] TS_FP_POINTER_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
in_uint16_le(s, xPos); /* xPos (2 bytes) */
|
||||
in_uint16_le(s, yPos); /* yPos (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTER_EVENT "
|
||||
"eventHeader.eventFlags 0x00, eventHeader.eventCode (ignored), "
|
||||
"pointerFlags 0x%4.4x, xPos %d, yPos %d", pointerFlags, xPos, yPos);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSE,
|
||||
xPos, yPos, pointerFlags, 0);
|
||||
@ -235,13 +247,18 @@ xrdp_fastpath_process_EVENT_MOUSEX(struct xrdp_fastpath *self,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_check_rem(s, 2 + 2 + 2))
|
||||
if (!s_check_rem_and_log(s, 2 + 2 + 2,
|
||||
"Parsing [MS-RDPBCGR] TS_FP_POINTERX_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, pointerFlags); /* pointerFlags (2 bytes) */
|
||||
in_uint16_le(s, xPos); /* xPos (2 bytes) */
|
||||
in_uint16_le(s, yPos); /* yPos (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_POINTERX_EVENT "
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"pointerFlags 0x%4.4x, xPos %d, yPos %d",
|
||||
eventFlags, pointerFlags, xPos, yPos);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_MOUSEX,
|
||||
xPos, yPos, pointerFlags, 0);
|
||||
@ -263,6 +280,10 @@ xrdp_fastpath_process_EVENT_SYNC(struct xrdp_fastpath *self,
|
||||
* status of the keyboard toggle keys.
|
||||
*/
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_SYNC_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), ",
|
||||
eventFlags);
|
||||
|
||||
xrdp_fastpath_session_callback(self, RDP_INPUT_SYNCHRONIZE,
|
||||
eventFlags, 0, 0, 0);
|
||||
|
||||
@ -279,11 +300,16 @@ xrdp_fastpath_process_EVENT_UNICODE(struct xrdp_fastpath *self,
|
||||
int code;
|
||||
|
||||
flags = 0;
|
||||
if (!s_check_rem(s, 2))
|
||||
if (!s_check_rem_and_log(s, 2, "Parsing [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint16_le(s, code); /* unicode (2 byte) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_UNICODE_KEYBOARD_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode (ignored), "
|
||||
"unicodeCode %d",
|
||||
eventFlags, code);
|
||||
|
||||
if (eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE)
|
||||
{
|
||||
flags |= KBD_FLAG_UP;
|
||||
@ -315,7 +341,7 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
/* process fastpath input events */
|
||||
for (i = 0; i < self->numEvents; i++)
|
||||
{
|
||||
if (!s_check_rem(s, 1))
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [MS-RDPBCGR] TS_FP_INPUT_EVENT eventHeader"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -323,6 +349,9 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
|
||||
eventFlags = (eventHeader & 0x1F);
|
||||
eventCode = (eventHeader >> 5);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received [MS-RDPBCGR] TS_FP_INPUT_EVENT"
|
||||
"eventHeader.eventFlags 0x%2.2x, eventHeader.eventCode 0x%1.1x",
|
||||
eventFlags, eventCode);
|
||||
|
||||
switch (eventCode)
|
||||
{
|
||||
@ -367,8 +396,8 @@ xrdp_fastpath_process_input_event(struct xrdp_fastpath *self,
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_fastpath_process_input_event: unknown "
|
||||
"eventCode %d", eventCode);
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_fastpath_process_input_event: "
|
||||
"unknown eventCode %d", eventCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,11 @@
|
||||
* limitations under the License.
|
||||
*
|
||||
* iso layer
|
||||
*
|
||||
* Note: [ITU-T X.224] and [ISO/IEC 8073] are essentially two specifications
|
||||
* of the same protocol (see [ITU-T X.224] Appendix I – Differences between
|
||||
* ITU-T Rec. X.224 (1993) and ISO/IEC 8073:1992). The RDP protocol
|
||||
* specification [MS-RDPBCGR] makes reference to the [ITU-T X.224] specificaiton.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
@ -36,11 +41,9 @@ xrdp_iso_create(struct xrdp_mcs *owner, struct trans *trans)
|
||||
{
|
||||
struct xrdp_iso *self;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_create");
|
||||
self = (struct xrdp_iso *) g_malloc(sizeof(struct xrdp_iso), 1);
|
||||
self->mcs_layer = owner;
|
||||
self->trans = trans;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_create");
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -77,8 +80,10 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
!g_file_readable(client_info->key_file))
|
||||
{
|
||||
/* certificate or privkey is not readable */
|
||||
LOG(LOG_LEVEL_WARNING, "No readable certificates or "
|
||||
"private keys, cannot accept TLS connections");
|
||||
LOG(LOG_LEVEL_ERROR, "Cannot accept TLS connections because "
|
||||
"certificate or private key file is not readable. "
|
||||
"certificate file: [%s], private key file: [%s]",
|
||||
client_info->certificate, client_info->key_file);
|
||||
self->failureCode = SSL_CERT_NOT_ON_SERVER;
|
||||
rv = 1; /* error */
|
||||
}
|
||||
@ -89,6 +94,8 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Server requires TLS for security, "
|
||||
"but the client did not request TLS.");
|
||||
self->failureCode = SSL_REQUIRED_BY_SERVER;
|
||||
rv = 1; /* error */
|
||||
}
|
||||
@ -116,40 +123,52 @@ xrdp_iso_negotiate_security(struct xrdp_iso *self)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process a [MS-RDPBCGR] RDP_NEG_REQ message.
|
||||
* returns error
|
||||
*/
|
||||
static int
|
||||
xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int flags;
|
||||
int len;
|
||||
|
||||
if (!s_check_rem(s, 7))
|
||||
if (!s_check_rem_and_log(s, 7, "Parsing [MS-RDPBCGR] RDP_NEG_REQ"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: unexpected end-of-record");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, flags);
|
||||
/* The type field has already been read to determine that this function
|
||||
should be called */
|
||||
in_uint8(s, flags); /* flags */
|
||||
if (flags != 0x0 && flags != 0x8 && flags != 0x1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, flags: %x", flags);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unsupported [MS-RDPBCGR] RDP_NEG_REQ flags: 0x%2.2x", flags);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint16_le(s, len);
|
||||
in_uint16_le(s, len); /* length */
|
||||
if (len != 8)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, length: %x", len);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Protocol error: [MS-RDPBCGR] RDP_NEG_REQ length must be 8, "
|
||||
"received %d", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint32_le(s, self->requestedProtocol);
|
||||
in_uint32_le(s, self->requestedProtocol); /* requestedProtocols */
|
||||
|
||||
/* TODO: why is requestedProtocols flag value bigger than 0xb invalid? */
|
||||
if (self->requestedProtocol > 0xb)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_process_rdpNegReq: error, requestedProtocol: %x",
|
||||
self->requestedProtocol);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unknown requested protocol flag [MS-RDPBCGR] RDP_NEG_REQ, "
|
||||
"requestedProtocol 0x%8.8x", self->requestedProtocol);
|
||||
return 1;
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received struct [MS-RDPBCGR] RDP_NEG_REQ "
|
||||
"flags 0x%2.2x, length 8, requestedProtocol 0x%8.8x",
|
||||
flags, self->requestedProtocol);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -163,6 +182,10 @@ xrdp_iso_process_rdp_neg_req(struct xrdp_iso *self, struct stream *s)
|
||||
* On exit, the TPKT header and the fixed part of the PDU header will have been
|
||||
* removed from the stream.
|
||||
*
|
||||
* @param self
|
||||
* @param s [in]
|
||||
* @param code [out]
|
||||
* @param len [out]
|
||||
* Returns error
|
||||
*****************************************************************************/
|
||||
static int
|
||||
@ -175,83 +198,110 @@ xrdp_iso_recv_msg(struct xrdp_iso *self, struct stream *s, int *code, int *len)
|
||||
|
||||
if (s != self->trans->in_s)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_iso_recv_msg error logic");
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Bug: the input stream is not the same stream as the "
|
||||
"transport input stream");
|
||||
}
|
||||
|
||||
/* TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
|
||||
if (!s_check_rem(s, 6))
|
||||
/* [ITU-T T.123] TPKT header is 4 bytes, then first 2 bytes of the X.224 CR-TPDU */
|
||||
if (!s_check_rem_and_log(s, 6,
|
||||
"Parsing [ITU-T T.123] TPKT header and [ITU-T X.224] TPDU header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8(s, ver);
|
||||
in_uint8s(s, 3); /* Skip reserved field, plus length */
|
||||
in_uint8(s, *len);
|
||||
in_uint8(s, *code);
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
in_uint8(s, ver); /* version */
|
||||
in_uint8s(s, 3); /* Skip reserved field (1 byte), plus length (2 bytes) */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T T.123] TPKT "
|
||||
"version %d, length (ignored)", ver);
|
||||
|
||||
/* [ITU-T X.224] TPDU header */
|
||||
in_uint8(s, *len); /* LI (length indicator) */
|
||||
in_uint8(s, *code); /* TPDU code */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Received header [ITU-T X.224] TPDU "
|
||||
"length indicator %d, TDPU code 0x%2.2x", *len, *code);
|
||||
|
||||
if (ver != 3)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: bad ver");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unsupported [ITU-T T.123] TPKT header version: %d", ver);
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T T.123] TPKT header", s->data, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*len == 255)
|
||||
{
|
||||
/* X.224 13.2.1 - reserved value */
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv_msg: reserved length encountered");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "header", s->data, 4);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"[ITU-T X.224] TPDU header: unsupported use of reserved length value");
|
||||
LOG_DEVEL_HEXDUMP(LOG_LEVEL_ERROR, "[ITU-T X.224] TPDU header", s->data + 4, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*code == ISO_PDU_DT)
|
||||
{
|
||||
/* Data PDU : X.224 13.7 */
|
||||
if (!s_check_rem(s, 1))
|
||||
/* Data PDU : X.224 13.7 class 0 */
|
||||
if (!s_check_rem_and_log(s, 1, "Parsing [ITU-T X.224] DT-TPDU (Data) header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 1);
|
||||
in_uint8s(s, 1); /* EOT (End of TSDU Mark) (upper 1 bit) and
|
||||
TPDU-NR (Data TPDU Number) (lower 7 bits) */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other supported PDUs : X.224 13.x */
|
||||
if (!s_check_rem(s, 5))
|
||||
/* Other supported X.224 class 0 PDUs all have 5 bytes remaining
|
||||
in the fixed header :
|
||||
CR Connection request (13.3)
|
||||
CC Connection confirm (13.4)
|
||||
DR Disconnect request (13.5) */
|
||||
if (!s_check_rem_and_log(s, 5, "Parsing [ITU-T X.224] Other PDU header"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
in_uint8s(s, 5);
|
||||
in_uint8s(s, 5); /* DST-REF (2 bytes)
|
||||
SRC-REF (2 bytes)
|
||||
[CR, CC] CLASS OPTION (1 byte) or [DR] REASON (1 byte) */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Process the header of a [ITU-T X.224] DT-TPDU (Data) message.
|
||||
*
|
||||
* returns error
|
||||
*/
|
||||
int
|
||||
xrdp_iso_recv(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int code;
|
||||
int len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_recv");
|
||||
|
||||
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv xrdp_iso_recv_msg return non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv: xrdp_iso_recv_msg failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (code != ISO_PDU_DT || len != 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, " out xrdp_iso_recv code != ISO_PDU_DT or length != 2");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_recv only supports processing "
|
||||
"[ITU-T X.224] DT-TPDU (Data) headers. Received TPDU header: "
|
||||
"length indicator %d, TDPU code 0x%2.2x", len, code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_recv");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Send a [ITU-T X.224] CC-TPDU (Connection Confirm) message with
|
||||
* [ITU-T T.123] TPKT header.
|
||||
*
|
||||
* returns error
|
||||
*/
|
||||
static int
|
||||
xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
{
|
||||
@ -266,35 +316,44 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
init_stream(s, 8192);
|
||||
|
||||
holdp = s->p;
|
||||
/* tpkt */
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
out_uint8(s, 3); /* version */
|
||||
out_uint8(s, 0); /* pad */
|
||||
out_uint8(s, 0); /* reserved (padding) */
|
||||
len_ptr = s->p;
|
||||
out_uint16_be(s, 0); /* length, set later */
|
||||
/* iso */
|
||||
|
||||
/* [ITU-T X.224] CC-TPDU */
|
||||
len_indicator_ptr = s->p;
|
||||
out_uint8(s, 0); /* length indicator, set later */
|
||||
out_uint8(s, 0); /* length indicator, set later */
|
||||
out_uint8(s, ISO_PDU_CC); /* Connection Confirm PDU */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0x1234);
|
||||
out_uint8(s, 0);
|
||||
/* rdpNegData */
|
||||
out_uint16_be(s, 0); /* DST-REF */
|
||||
out_uint16_be(s, 0x1234); /* SRC-REF */
|
||||
out_uint8(s, 0); /* CLASS OPTION */
|
||||
|
||||
/* [MS-RDPBCGR] 2.2.1.2 rdpNegData */
|
||||
if (self->rdpNegData)
|
||||
{
|
||||
if (self->failureCode)
|
||||
{
|
||||
out_uint8(s, RDP_NEG_FAILURE);
|
||||
out_uint8(s, 0); /* no flags */
|
||||
out_uint16_le(s, 8); /* must be 8 */
|
||||
out_uint32_le(s, self->failureCode); /* failure code */
|
||||
/* [MS-RDPBCGR] RDP_NEG_FAILURE */
|
||||
out_uint8(s, RDP_NEG_FAILURE); /* type*/
|
||||
out_uint8(s, 0); /* flags (none) */
|
||||
out_uint16_le(s, 8); /* length (must be 8) */
|
||||
out_uint32_le(s, self->failureCode); /* failureCode */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_FAILURE "
|
||||
"flags 0, length 8, failureCode 0x%8.8x", self->failureCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_uint8(s, RDP_NEG_RSP);
|
||||
/* [MS-RDPBCGR] RDP_NEG_RSP */
|
||||
out_uint8(s, RDP_NEG_RSP); /* type*/
|
||||
//TODO: hardcoded flags
|
||||
out_uint8(s, EXTENDED_CLIENT_DATA_SUPPORTED); /* flags */
|
||||
out_uint16_le(s, 8); /* must be 8 */
|
||||
out_uint32_le(s, self->selectedProtocol); /* selected protocol */
|
||||
out_uint16_le(s, 8); /* length (must be 8) */
|
||||
out_uint32_le(s, self->selectedProtocol); /* selectedProtocol */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding structure [MS-RDPBCGR] RDP_NEG_RSP "
|
||||
"flags 0, length 8, selectedProtocol 0x%8.8x",
|
||||
self->selectedProtocol);
|
||||
}
|
||||
}
|
||||
s_mark_end(s);
|
||||
@ -305,8 +364,15 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
len_ptr[1] = len;
|
||||
len_indicator_ptr[0] = len_indicator;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
|
||||
"version 3, length %d", len);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) "
|
||||
"length indicator %d, DST-REF 0, SRC-REF 0, CLASS OPTION 0",
|
||||
len_indicator);
|
||||
|
||||
if (trans_write_copy_s(self->trans, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Sending [ITU-T X.224] CC-TPDU (Connection Confirm) failed");
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
@ -317,7 +383,7 @@ xrdp_iso_send_cc(struct xrdp_iso *self)
|
||||
/*****************************************************************************
|
||||
* Process an X.224 connection request PDU
|
||||
*
|
||||
* See MS-RDPCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
|
||||
* See MS-RDPBCGR v20190923 sections 2.2.1.1 and 3.3.5.3.1.
|
||||
*
|
||||
* From the latter, in particular:-
|
||||
* - The length embedded in the TPKT header MUST be examined for
|
||||
@ -339,22 +405,26 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
struct stream *s;
|
||||
int expected_pdu_len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_incoming");
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: receive connection request");
|
||||
s = libxrdp_force_read(self->trans);
|
||||
if (s == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (xrdp_iso_recv_msg(self, s, &code, &len) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_recv_msg returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: CR-TPDU (Connection Request) failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (code != ISO_PDU_CR)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming only supports processing "
|
||||
"[ITU-T X.224] CR-TPDU (Connection Request) headers. "
|
||||
"Received TPDU header: length indicator %d, TDPU code 0x%2.2x",
|
||||
len, code);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -369,38 +439,47 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
expected_pdu_len = (s->end - s->p) + 6;
|
||||
if (len != expected_pdu_len)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: X.224 CR-TPDU length exp %d got %d",
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Invalid length indicator in [ITU-T X.224] CR-TPDU (Connection Request). "
|
||||
"expected %d, received %d",
|
||||
expected_pdu_len, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* process connection request */
|
||||
/* process connection request [MS-RDPBCGR] 2.2.1.1 */
|
||||
while (s_check_rem(s, 1))
|
||||
{
|
||||
in_uint8(s, cc_type);
|
||||
in_uint8(s, cc_type); /* type or 'C' */
|
||||
switch (cc_type)
|
||||
{
|
||||
default:
|
||||
LOG_DEVEL(LOG_LEVEL_WARNING,
|
||||
"Ignoring unknown structure type in [ITU-T X.224] CR-TPDU (Connection Request). "
|
||||
"type 0x%2.2x", cc_type);
|
||||
break;
|
||||
case RDP_NEG_REQ: /* rdpNegReq 1 */
|
||||
self->rdpNegData = 1;
|
||||
if (xrdp_iso_process_rdp_neg_req(self, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_process_rdpNegReq returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"[ITU-T X.224] Connection Sequence: failed");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case RDP_CORRELATION_INFO: /* rdpCorrelationInfo 6 */
|
||||
// TODO
|
||||
if (!s_check_rem(s, 1 + 2 + 16 + 16))
|
||||
if (!s_check_rem_and_log(s, 1 + 2 + 16 + 16,
|
||||
"Parsing [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO"))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: short correlation info");
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 1 + 2 + 16 + 16);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"Received struct [MS-RDPBCGR] RDP_NEG_CORRELATION_INFO "
|
||||
"(all fields ignored)");
|
||||
break;
|
||||
case 'C': /* Cookie */
|
||||
case 'C': /* Cookie or routingToken */
|
||||
/* The routingToken and cookie fields are both ASCII
|
||||
* strings starting with the word 'Cookie: ' and
|
||||
* ending with CR+LF. We ignore both, so we do
|
||||
@ -417,6 +496,9 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
}
|
||||
}
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"Received struct [MS-RDPBCGR] routingToken or cookie "
|
||||
"(ignored)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -425,13 +507,14 @@ xrdp_iso_incoming(struct xrdp_iso *self)
|
||||
rv = xrdp_iso_negotiate_security(self);
|
||||
|
||||
/* send connection confirm back to client */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: send connection confirmation");
|
||||
if (xrdp_iso_send_cc(self) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_incoming: xrdp_iso_send_cc returned non zero");
|
||||
LOG(LOG_LEVEL_ERROR, "[ITU-T X.224] Connection Sequence: send connection confirmation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_incoming");
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "[ITU-T X.224] Connection Sequence: completed");
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -446,27 +529,39 @@ xrdp_iso_init(struct xrdp_iso *self, struct stream *s)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns error */
|
||||
/* Sends a message with the [ITU-T T.123] TPKT header (T.123 section 8) and
|
||||
* [ITU-T X.224] DT-TPDU (Data) header (X.224 section 13)
|
||||
* returns error
|
||||
*/
|
||||
int
|
||||
xrdp_iso_send(struct xrdp_iso *self, struct stream *s)
|
||||
{
|
||||
int len;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " in xrdp_iso_send");
|
||||
s_pop_layer(s, iso_hdr);
|
||||
len = (int) (s->end - s->p);
|
||||
out_uint8(s, 3);
|
||||
out_uint8(s, 0);
|
||||
out_uint16_be(s, len);
|
||||
out_uint8(s, 2);
|
||||
out_uint8(s, ISO_PDU_DT);
|
||||
out_uint8(s, 0x80);
|
||||
/* [ITU-T T.123] TPKT header */
|
||||
out_uint8(s, 3); /* version */
|
||||
out_uint8(s, 0); /* reserved (padding) */
|
||||
out_uint16_be(s, len); /* length */
|
||||
|
||||
/* [ITU-T X.224] DT-TPDU (Data) header */
|
||||
out_uint8(s, 2); /* LI (length indicator) */
|
||||
out_uint8(s, ISO_PDU_DT); /* TPDU code */
|
||||
out_uint8(s, 0x80); /* EOT (End of TSDU Mark) (upper 1 bit) and
|
||||
TPDU-NR (Data TPDU Number) (lower 7 bits) */
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T T.123] TPKT "
|
||||
"version 3, length %d", len);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [ITU-T X.224] DT-TPDU (Data) "
|
||||
"length indicator 2, TPDU code 0x%2.2x, EOT 1, TPDU-NR 0x00",
|
||||
ISO_PDU_DT);
|
||||
|
||||
if (trans_write_copy_s(self->trans, s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_iso_send: trans_write_copy_s failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, " out xrdp_iso_send");
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -969,6 +969,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
|
||||
{
|
||||
/* compressed data longer than uncompressed data */
|
||||
/* give up */
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Compression algorithim produced a compressed "
|
||||
"buffer which is larger than the uncompressed buffer. "
|
||||
"compression ratio %f, flags 0x%x",
|
||||
(float) len / (float) opb_index, enc->flags);
|
||||
enc->historyOffset = 0;
|
||||
g_memset(hash_table, 0, enc->buf_len * 2);
|
||||
g_memset(enc->historyBuffer, 0, enc->buf_len);
|
||||
@ -982,10 +986,10 @@ compress_rdp_5(struct xrdp_mppc_enc *enc, tui8 *srcData, int len)
|
||||
enc->flags |= enc->flagsHold;
|
||||
enc->flagsHold = 0;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "\n");
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "compression ratio: %f", (float) len / (float) enc->bytes_in_opb);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Compression successful. compression ratio %f, "
|
||||
"flags 0x%x, bytes_in_opb %d, historyOffset %d, uncompressed len %d",
|
||||
(float) len / (float) enc->bytes_in_opb, enc->flags,
|
||||
enc->bytes_in_opb, enc->historyOffset, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ xrdp_orders_reset(struct xrdp_orders *self)
|
||||
{
|
||||
if (xrdp_orders_force_send(self) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_reset: xrdp_orders_force_send failed");
|
||||
return 1;
|
||||
}
|
||||
g_free(self->orders_state.text_data);
|
||||
@ -109,23 +110,29 @@ xrdp_orders_init(struct xrdp_orders *self)
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: fastpath");
|
||||
if (xrdp_rdp_init_fastpath(self->rdp_layer, self->out_s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_fastpath failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
||||
// LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TODO");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "xrdp_orders_init: slowpath");
|
||||
if (xrdp_rdp_init_data(self->rdp_layer, self->out_s) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_init: xrdp_rdp_init_data failed");
|
||||
return 1;
|
||||
}
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS);
|
||||
out_uint16_le(self->out_s, RDP_UPDATE_ORDERS); /* updateType */
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
self->order_count_ptr = self->out_s->p;
|
||||
out_uint8s(self->out_s, 2); /* number of orders, set later */
|
||||
out_uint8s(self->out_s, 2); /* pad */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] TS_UPDATE_ORDERS_PDU_DATA "
|
||||
"updateType %d (UPDATETYPE_ORDERS), pad2OctetsA <ignored>, "
|
||||
"numberOrders <to be set later>, pad2OctetsB <ignored>",
|
||||
RDP_UPDATE_ORDERS);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -154,6 +161,8 @@ xrdp_orders_send(struct xrdp_orders *self)
|
||||
if (xrdp_rdp_send_fastpath(self->rdp_layer,
|
||||
self->out_s, 0) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send: xrdp_rdp_send_fastpath failed");
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
@ -162,6 +171,8 @@ xrdp_orders_send(struct xrdp_orders *self)
|
||||
if (xrdp_rdp_send_data(self->rdp_layer, self->out_s,
|
||||
RDP_DATA_PDU_UPDATE) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send: xrdp_rdp_send_data failed");
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
@ -225,6 +236,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
{
|
||||
if (max_size > max_order_size)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Requested orders max_size (%d) "
|
||||
"is greater than the client connection max_size (%d)",
|
||||
max_size, max_order_size);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@ -237,7 +251,8 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
size = (int)(self->out_s->p - self->order_count_ptr);
|
||||
if (size < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "error in xrdp_orders_check, size too small: %d bytes", size);
|
||||
LOG(LOG_LEVEL_ERROR, "Bug: order data length cannot be negative. "
|
||||
"Found length %d bytes", size);
|
||||
return 1;
|
||||
}
|
||||
if (size > max_order_size)
|
||||
@ -245,7 +260,9 @@ xrdp_orders_check(struct xrdp_orders *self, int max_size)
|
||||
/* this suggests someone calls this function without passing the
|
||||
correct max_size so we end up putting more into the buffer
|
||||
than we indicate we can */
|
||||
LOG(LOG_LEVEL_WARNING, "error in xrdp_orders_check, size too big: %d bytes", size);
|
||||
LOG(LOG_LEVEL_WARNING, "Ignoring Bug: order data length "
|
||||
"is larger than maximum length. Expected %d, actual %d",
|
||||
max_order_size, size);
|
||||
/* We where getting called with size already greater than
|
||||
max_order_size
|
||||
Which I suspect was because the sending of text did not include
|
||||
@ -2175,15 +2192,23 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
|
||||
|
||||
if (xrdp_orders_check(self, 2000) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_orders_send_palette: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_STANDARD | TS_SECONDARY;
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] DRAWING_ORDER "
|
||||
"controlFlags 0x%2.2x (TS_STANDARD | TS_SECONDARY)", order_flags);
|
||||
|
||||
len = 1027 - 7; /* length after type minus 7 */
|
||||
out_uint16_le(self->out_s, len);
|
||||
out_uint16_le(self->out_s, 0); /* flags */
|
||||
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* type */
|
||||
out_uint16_le(self->out_s, len); /* orderLength */
|
||||
out_uint16_le(self->out_s, 0); /* extraFlags */
|
||||
out_uint8(self->out_s, TS_CACHE_COLOR_TABLE); /* orderType */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] SECONDARY_DRAWING_ORDER_HEADER "
|
||||
"orderLength %d, extraFlags 0x0000, orderType 0x%2.2x (TS_CACHE_COLOR_TABLE)",
|
||||
len, TS_CACHE_COLOR_TABLE);
|
||||
|
||||
out_uint8(self->out_s, cache_id);
|
||||
out_uint16_le(self->out_s, 256); /* num colors */
|
||||
|
||||
@ -2194,7 +2219,9 @@ xrdp_orders_send_palette(struct xrdp_orders *self, int *palette,
|
||||
out_uint8(self->out_s, palette[i] >> 16);
|
||||
out_uint8(self->out_s, 0);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPEGDI] CACHE_COLOR_TABLE_ORDER "
|
||||
"cacheIndex %d, numberColors 256, colorTable <omitted from log>",
|
||||
cache_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -42,12 +42,19 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
|
||||
order_size = 11;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_delete: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -55,6 +62,12 @@ xrdp_orders_send_window_delete(struct xrdp_orders *self, int window_id)
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, "
|
||||
"FieldsPresentFlags 0x%8.8x (WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED), "
|
||||
"WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Window");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -75,12 +88,19 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
|
||||
order_size = 14;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_cached_icon: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -89,10 +109,17 @@ xrdp_orders_send_window_cached_icon(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Cached Icon");
|
||||
|
||||
/* CacheEntry (2 bytes) */
|
||||
out_uint16_le(self->out_s, cache_entry);
|
||||
/* CacheId (1 byte) */
|
||||
out_uint8(self->out_s, cache_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d", cache_entry, cache_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -134,6 +161,18 @@ xrdp_orders_send_ts_icon(struct stream *s, int cache_entry, int cache_id,
|
||||
}
|
||||
|
||||
out_uint8p(s, icon_info->data, icon_info->data_bytes);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order fields [MS-RDPERP] TS_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d, Bpp %d, Width %d, Height %d, "
|
||||
"CbColorTable <%s>, "
|
||||
"CbBitsMask %d, CbBitsColor %d, BitsMask <omitted from log>, "
|
||||
"ColorTable <%s>, "
|
||||
"BitsColor <omitted from log>",
|
||||
cache_entry, cache_id, icon_info->bpp, icon_info->width,
|
||||
icon_info->height,
|
||||
(use_cmap ? "present, omitted from log" : "not present"),
|
||||
icon_info->mask_bytes, icon_info->data_bytes,
|
||||
(use_cmap ? "present, omitted from log" : "not present")
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -169,12 +208,19 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_icon: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -183,6 +229,10 @@ xrdp_orders_send_window_icon(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Window Icon");
|
||||
|
||||
xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
|
||||
|
||||
@ -372,23 +422,36 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_window_new_update: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
/* windowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_WINDOW_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Window (TS_WINDOW_INFO)");
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
|
||||
{
|
||||
/* ownerWindowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->owner_window_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"OwnerWindowId 0x%8.8x", window_state->owner_window_id);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
|
||||
@ -397,18 +460,28 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->style);
|
||||
/* extendedStyle (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->extended_style);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"Style 0x%8.8x, ExtendedStyle 0x%8.8x",
|
||||
window_state->style, window_state->extended_style);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
|
||||
{
|
||||
/* showState (1 byte) */
|
||||
out_uint8(self->out_s, window_state->show_state);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ShowState 0x%2.2x", window_state->show_state);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
|
||||
{
|
||||
/* titleInfo */
|
||||
xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"TitleInfo %s", window_state->title_info);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
|
||||
@ -417,26 +490,61 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->client_offset_x);
|
||||
/* clientOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ClientOffsetX %d, ClientOffsetY %d",
|
||||
window_state->client_offset_x, window_state->client_offset_y);
|
||||
}
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The ClientAreaWidth and ClientAreaHeight field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
|
||||
{
|
||||
/* clientAreaWidth (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_area_width);
|
||||
/* clientAreaHeight (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->client_area_height);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"ClientAreaWidth %d, ClientAreaHeight %d",
|
||||
window_state->client_area_width, window_state->client_area_height);
|
||||
}
|
||||
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
|
||||
* WindowLeftResizeMargin (optional)
|
||||
* WindowRightResizeMargin (optional)
|
||||
* WindowTopResizeMargin (optional)
|
||||
* WindowBottomResizeMargin (optional)
|
||||
*/
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The RPContent field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
|
||||
{
|
||||
/* RPContent (1 byte) */
|
||||
out_uint8(self->out_s, window_state->rp_content);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"RPContent 0x%2.2x", window_state->rp_content);
|
||||
}
|
||||
|
||||
/* TODO: The [MS-RDPERP] spec says that:
|
||||
* The RootParentHandle field only appears if the WndSupportLevel field of the
|
||||
* Window List Capability Set message is set to TS_WINDOW_LEVEL_SUPPORTED_EX
|
||||
* (as specified in [MS-RDPERP] section 2.2.1.1.2)
|
||||
*/
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
|
||||
{
|
||||
/* rootParentHandle (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->root_parent_handle);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"RootParentHandle 0x%8.8x", window_state->root_parent_handle);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
|
||||
@ -445,6 +553,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_offset_x);
|
||||
/* windowOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowOffsetX %d, WindowOffsetY %d",
|
||||
window_state->window_offset_x, window_state->window_offset_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
|
||||
@ -453,6 +565,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_client_delta_x);
|
||||
/* windowClientDeltaY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_client_delta_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowClientDeltaX %d, WindowClientDeltaY %d",
|
||||
window_state->window_client_delta_x, window_state->window_client_delta_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
|
||||
@ -461,6 +577,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->window_width);
|
||||
/* windowHeight (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->window_height);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"WindowWidth %d, WindowHeight %d",
|
||||
window_state->window_width, window_state->window_height);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
|
||||
@ -475,6 +595,9 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint16_le(self->out_s, window_state->window_rects[index].right);
|
||||
out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"NumWindowRects %d, WindowRects <omitted from log>",
|
||||
window_state->num_window_rects);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
|
||||
@ -483,6 +606,10 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_state->visible_offset_x);
|
||||
/* visibleOffsetY (4 bytes) */
|
||||
out_uint32_le(self->out_s, window_state->visible_offset_y);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"VisibleOffsetX %d, VisibleOffsetY %d",
|
||||
window_state->visible_offset_x, window_state->visible_offset_y);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
|
||||
@ -497,7 +624,17 @@ xrdp_orders_send_window_new_update(struct xrdp_orders *self, int window_id,
|
||||
out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
|
||||
out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
|
||||
}
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding optional field [MS-RDPERP] TS_WINDOW_INFO "
|
||||
"NumVisibilityRects %d, VisibilityRects <omitted from log>",
|
||||
window_state->num_visibility_rects);
|
||||
}
|
||||
/* TODO: The [MS-RDPERP] spec section 2.2.1.3.1.2.1 has the following additional fields:
|
||||
* OverlayDescription (optional, variable)
|
||||
* TaskbarButton (optional)
|
||||
* EnforceServerZOrder (optional)
|
||||
* AppBarState (optional)
|
||||
* AppBarEdge (optional)
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -516,12 +653,19 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
|
||||
order_size = 15;
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_notify_delete: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -531,6 +675,11 @@ xrdp_orders_send_notify_delete(struct xrdp_orders *self, int window_id,
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
/* notifyIconId (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] Deleted Notification Icons");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -610,12 +759,19 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_notify_new_update: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
out_uint8(self->out_s, order_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
@ -624,17 +780,27 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, window_id);
|
||||
/* notifyIconId (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_NOTIFYICON_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x, WindowId 0x%8.8x, NotifyIconId 0x%8.8x",
|
||||
order_size, field_present_flags, window_id, notify_id);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] New or Existing Notification Icons");
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
|
||||
{
|
||||
/* Version (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_state->version);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"Version %d", notify_state->version);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
|
||||
{
|
||||
/* ToolTip (variable) UNICODE_STRING */
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"ToolTip %s", notify_state->tool_tip);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
|
||||
@ -644,12 +810,20 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint32_le(self->out_s, notify_state->infotip.flags);
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
|
||||
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] TS_NOTIFY_ICON_INFOTIP "
|
||||
"Timeout %d, InfoFlags 0x%8.8x, InfoTipText %s, Title %s",
|
||||
notify_state->infotip.timeout, notify_state->infotip.flags,
|
||||
notify_state->infotip.text, notify_state->infotip.title);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
|
||||
{
|
||||
/* State (4 bytes) */
|
||||
out_uint32_le(self->out_s, notify_state->state);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"State %d", notify_state->state);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_ICON)
|
||||
@ -666,6 +840,10 @@ xrdp_orders_send_notify_new_update(struct xrdp_orders *self,
|
||||
out_uint16_le(self->out_s, notify_state->icon_cache_entry);
|
||||
/* CacheId (1 byte) */
|
||||
out_uint8(self->out_s, notify_state->icon_cache_id);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order field [MS-RDPERP] TS_CACHED_ICON_INFO "
|
||||
"CacheEntry %d, CacheId %d",
|
||||
notify_state->icon_cache_entry, notify_state->icon_cache_id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -704,21 +882,37 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
|
||||
|
||||
if (xrdp_orders_check(self, order_size) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"xrdp_orders_send_monitored_desktop: xrdp_orders_check failed");
|
||||
return 1;
|
||||
}
|
||||
self->order_count++;
|
||||
order_flags = TS_SECONDARY;
|
||||
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPEGDI] ALTSEC_DRAWING_ORDER_HEADER "
|
||||
"controlFlags.class 0x%1.1x (TS_SECONDARY), "
|
||||
"controlFlags.orderType 0x%2.2x (TS_ALTSEC_WINDOW)",
|
||||
(order_flags & 0x3), (order_flags >> 2));
|
||||
|
||||
out_uint8(self->out_s, order_flags);
|
||||
/* orderSize (2 bytes) */
|
||||
out_uint16_le(self->out_s, order_size);
|
||||
/* FieldsPresentFlags (4 bytes) */
|
||||
out_uint32_le(self->out_s, field_present_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPERP] TS_DESKTOP_ORDER_HEADER "
|
||||
"OrderSize %d, FieldsPresentFlags 0x%8.8x",
|
||||
order_size, field_present_flags);
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order [MS-RDPERP] %s",
|
||||
((field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_NONE) ?
|
||||
"Non-Monitored Desktop" : "Actively Monitored Desktop"));
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
|
||||
{
|
||||
/* ActiveWindowId (4 bytes) */
|
||||
out_uint32_le(self->out_s, mdo->active_window_id);
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"ActiveWindowId 0x%8.8x", mdo->active_window_id);
|
||||
}
|
||||
|
||||
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
|
||||
@ -731,6 +925,10 @@ xrdp_orders_send_monitored_desktop(struct xrdp_orders *self,
|
||||
{
|
||||
out_uint32_le(self->out_s, mdo->window_ids[index]);
|
||||
}
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding order optional field [MS-RDPERP] "
|
||||
"NumWindowIds %d, WindowIds <omitted from log>",
|
||||
mdo->num_window_ids);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -789,7 +789,7 @@ xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex)
|
||||
if (g_xfs == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"xfuse_add_clip_dir_item() called with no filesystem")
|
||||
"xfuse_add_clip_dir_item() called with no filesystem");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user