Merge pull request #1298 from jaroslaw-osmanski/restrict-outbound-clipboard

Restrict outbound clipboard
This commit is contained in:
metalefty 2019-03-20 10:37:40 +09:00 committed by GitHub
commit ec05d4208d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 199 additions and 148 deletions

View File

@ -196,6 +196,12 @@ login for all users is enabled.
\fIThis option is currently ignored!\fR Only members of this group can
have session management rights.
.TP
\fBRestrictOutboundClipboard\fR=\fI[true|false]\fR
If set to \fB1\fR, \fBtrue\fR or \fByes\fR, will restrict the clipboard
outbound from the server, to prevent data copied inside the xrdp session
to be be pasted in the client host. Default value is \fBfalse\fR.
.TP
\fBAlwaysGroupCheck\fR=\fI[true|false]\fR
If set to \fB1\fR, \fBtrue\fR or \fByes\fR, require group membership even

View File

@ -59,6 +59,7 @@ int g_cliprdr_chan_id = -1; /* cliprdr */
int g_rdpsnd_chan_id = -1; /* rdpsnd */
int g_rdpdr_chan_id = -1; /* rdpdr */
int g_rail_chan_id = -1; /* rail */
int g_restrict_outbound_clipboard = 0;
char *g_exec_name;
tbus g_exec_event;
@ -1780,7 +1781,7 @@ main(int argc, char **argv)
enum logReturns error;
struct log_config logconfig;
enum logLevels log_level;
char *restrict_outbound_clipboard_env;
g_init("xrdp-chansrv"); /* os_calls */
log_path[255] = 0;
@ -1791,6 +1792,15 @@ main(int argc, char **argv)
return 1;
}
restrict_outbound_clipboard_env = g_getenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD");
if (restrict_outbound_clipboard_env != 0)
{
if (g_strcmp(restrict_outbound_clipboard_env, "1") == 0)
{
g_restrict_outbound_clipboard = 1;
}
}
read_ini();
pid = g_getpid();
display_text = g_getenv("DISPLAY");

View File

@ -185,38 +185,38 @@ x-special/gnome-copied-files
#define LOG_LEVEL LOG_ERROR
#define log_error(_params...) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ERROR: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
#define log_always(_params...) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ALWAYS: ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
}
#define log_info(_params...) \
{ \
if (LOG_INFO <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
{ \
if (LOG_INFO <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
#define log_debug(_params...) \
{ \
if (LOG_DEBUG <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
{ \
if (LOG_DEBUG <= LOG_LEVEL) \
{ \
g_write("[%10.10u]: CLIPBOARD %s: %d : ", \
g_time3(), __func__, __LINE__); \
g_writeln (_params); \
} \
}
static char g_bmp_image_header[] =
{
@ -235,6 +235,8 @@ extern tbus g_x_wait_obj; /* in xcommon.c */
extern Screen *g_screen; /* in xcommon.c */
extern int g_screen_num; /* in xcommon.c */
extern int g_restrict_outbound_clipboard; /* in chansrv.c */
int g_clip_up = 0;
static Atom g_clipboard_atom = 0; /* CLIPBOARD */
@ -286,10 +288,10 @@ static int g_file_format_id = -1;
static char g_last_atom_name[256] = "";
/*****************************************************************************/
static char*
static char *
get_atom_text(Atom atom)
{
char* name;
char *name;
int failed;
failed = 0;
@ -405,10 +407,10 @@ clipboard_init(void)
if (rv == 0)
{
log_debug("clipboard_init: g_xfixes_event_base %d",
g_xfixes_event_base);
g_xfixes_event_base);
st = XFixesQueryVersion(g_display, &ver_maj, &ver_min);
log_debug("clipboard_init st %d, maj %d min %d", st,
ver_maj, ver_min);
ver_maj, ver_min);
g_clip_property_atom = XInternAtom(g_display, "XRDP_CLIP_PROPERTY_ATOM",
False);
g_get_time_atom = XInternAtom(g_display, "XRDP_GET_TIME_ATOM",
@ -428,7 +430,7 @@ clipboard_init(void)
if (g_image_bmp_atom == None)
{
log_error("clipboard_init: g_image_bmp_atom was "
"not allocated");
"not allocated");
}
g_wnd = XCreateSimpleWindow(g_display, RootWindowOfScreen(g_screen),
@ -463,12 +465,12 @@ clipboard_init(void)
s_mark_end(s);
size = (int)(s->end - s->data);
log_debug("clipboard_init: data out, sending "
"CB_CLIP_CAPS (clip_msg_id = 1)");
"CB_CLIP_CAPS (clip_msg_id = 1)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
if (rv != 0)
{
log_error("clipboard_init: send_channel_data failed "
"rv = %d", rv);
"rv = %d", rv);
rv = 4;
}
}
@ -484,12 +486,12 @@ clipboard_init(void)
s_mark_end(s);
size = (int)(s->end - s->data);
log_debug("clipboard_init: data out, sending "
"CB_MONITOR_READY (clip_msg_id = 1)");
"CB_MONITOR_READY (clip_msg_id = 1)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
if (rv != 0)
{
log_error("clipboard_init: send_channel_data failed "
"rv = %d", rv);
"rv = %d", rv);
rv = 4;
}
}
@ -554,7 +556,7 @@ clipboard_send_data_request(int format_id)
s_mark_end(s);
size = (int)(s->end - s->data);
log_debug("clipboard_send_data_request: data out, sending "
"CLIPRDR_DATA_REQUEST (clip_msg_id = 4)");
"CLIPRDR_DATA_REQUEST (clip_msg_id = 4)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
@ -577,7 +579,7 @@ clipboard_send_format_ack(void)
s_mark_end(s);
size = (int)(s->end - s->data);
log_debug("clipboard_send_format_ack: data out, sending "
"CLIPRDR_FORMAT_ACK (clip_msg_id = 3)");
"CLIPRDR_FORMAT_ACK (clip_msg_id = 3)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
@ -715,7 +717,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
break;
default:
log_debug("clipboard_send_format_announce: unknown "
"xrdp_clip_type %d", xrdp_clip_type);
"xrdp_clip_type %d", xrdp_clip_type);
break;
}
}
@ -759,7 +761,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
break;
default:
log_debug("clipboard_send_format_announce: unknown "
"xrdp_clip_type %d", xrdp_clip_type);
"xrdp_clip_type %d", xrdp_clip_type);
break;
}
}
@ -774,7 +776,7 @@ clipboard_send_format_announce(int xrdp_clip_type)
size = (int)(s->end - s->data);
//g_hexdump(s->data, size);
log_debug("clipboard_send_format_announce: data out, sending "
"CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)");
"CLIPRDR_FORMAT_ANNOUNCE (clip_msg_id = 2)");
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
@ -789,7 +791,7 @@ clipboard_send_data_response_for_image(const char *data, int data_size)
int rv;
log_debug("clipboard_send_data_response_for_image: data_size %d",
data_size);
data_size);
make_stream(s);
init_stream(s, 64 + data_size);
out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
@ -814,17 +816,17 @@ clipboard_send_data_response_for_text(const char *data, int data_size)
int num_chars;
log_debug("clipboard_send_data_response_for_text: data_size %d",
data_size);
data_size);
//g_hexdump(data, data_size);
num_chars = g_mbstowcs(0, data, 0);
if (num_chars < 0)
{
log_error("clipboard_send_data_response_for_text: "
"bad string");
"bad string");
num_chars = 0;
}
log_debug("clipboard_send_data_response_for_text: data_size %d "
"num_chars %d", data_size, num_chars);
"num_chars %d", data_size, num_chars);
make_stream(s);
init_stream(s, 64 + num_chars * 2);
out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
@ -833,15 +835,15 @@ clipboard_send_data_response_for_text(const char *data, int data_size)
if (clipboard_out_unicode(s, data, num_chars) != num_chars * 2)
{
log_error("clipboard_send_data_response_for_text: error "
"clipboard_out_unicode didn't write right number of bytes");
"clipboard_out_unicode didn't write right number of bytes");
}
out_uint16_le(s, 0); /* nil for string */
out_uint32_le(s, 0);
s_mark_end(s);
size = (int)(s->end - s->data);
log_debug("clipboard_send_data_response_for_text: data out, "
"sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d "
"num_chars %d", size, num_chars);
"sending CLIPRDR_DATA_RESPONSE (clip_msg_id = 5) size %d "
"num_chars %d", size, num_chars);
rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
free_stream(s);
return rv;
@ -869,7 +871,7 @@ clipboard_send_data_response(int xrdp_clip_type, const char *data, int data_size
else
{
log_debug("clipboard_send_data_response: unknown "
"xrdp_clip_type %d", xrdp_clip_type);
"xrdp_clip_type %d", xrdp_clip_type);
}
}
else
@ -908,7 +910,7 @@ clipboard_provide_selection_c2s(XSelectionRequestEvent *req, Atom type)
long val1[2];
log_debug("clipboard_provide_selection_c2s: bytes %d",
g_clip_c2s.total_bytes);
g_clip_c2s.total_bytes);
if (g_clip_c2s.total_bytes < g_incr_max_req_size)
{
XChangeProperty(g_display, req->requestor, req->property,
@ -934,8 +936,8 @@ clipboard_provide_selection_c2s(XSelectionRequestEvent *req, Atom type)
g_clip_c2s.property = req->property;
g_clip_c2s.window = req->requestor;
log_debug("clipboard_provide_selection_c2s: start INCR property %s "
"type %s", get_atom_text(req->property),
get_atom_text(type));
"type %s", get_atom_text(req->property),
get_atom_text(type));
val1[0] = g_clip_c2s.total_bytes;
val1[1] = 0;
XChangeProperty(g_display, req->requestor, req->property,
@ -1020,7 +1022,7 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
char *holdp;
log_debug("clipboard_process_format_announce: "
"CLIPRDR_FORMAT_ANNOUNCE");
"CLIPRDR_FORMAT_ANNOUNCE");
log_debug("clipboard_process_format_announce %d", clip_msg_len);
clipboard_send_format_ack();
@ -1052,8 +1054,8 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
clip_msg_len -= 32;
}
log_debug("clipboard_process_format_announce: formatId 0x%8.8x "
"wszFormatName [%s] clip_msg_len %d", formatId, desc,
clip_msg_len);
"wszFormatName [%s] clip_msg_len %d", formatId, desc,
clip_msg_len);
if (g_num_formatIds <= 15)
{
g_formatIds[g_num_formatIds] = formatId;
@ -1073,13 +1075,13 @@ clipboard_process_format_announce(struct stream *s, int clip_msg_status,
}
if ((g_num_formatIds > 0) &&
(g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */
(g_clip_s2c.incr_in_progress == 0))
(g_clip_c2s.incr_in_progress == 0) && /* don't interrupt incr */
(g_clip_s2c.incr_in_progress == 0))
{
if (clipboard_set_selection_owner() != 0)
{
log_error("clipboard_process_format_announce: "
"XSetSelectionOwner failed");
"XSetSelectionOwner failed");
}
}
@ -1130,7 +1132,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
int requestedFormatId;
log_debug("clipboard_process_data_request: "
"CLIPRDR_DATA_REQUEST");
"CLIPRDR_DATA_REQUEST");
log_debug("clipboard_process_data_request:");
log_debug(" %d", g_clip_s2c.xrdp_clip_type);
in_uint32_le(s, requestedFormatId);
@ -1146,7 +1148,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else
{
log_debug("clipboard_process_data_request: CB_FORMAT_FILE, "
"calling XConvertSelection to g_utf8_atom");
"calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_FILE;
XConvertSelection(g_display, g_clipboard_atom, g_clip_s2c.type,
g_clip_property_atom, g_wnd, CurrentTime);
@ -1162,7 +1164,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else
{
log_debug("clipboard_process_data_request: CB_FORMAT_DIB, "
"calling XConvertSelection to g_image_bmp_atom");
"calling XConvertSelection to g_image_bmp_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_BITMAP;
XConvertSelection(g_display, g_clipboard_atom, g_image_bmp_atom,
g_clip_property_atom, g_wnd, CurrentTime);
@ -1178,7 +1180,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
else
{
log_debug("clipboard_process_data_request: CB_FORMAT_UNICODETEXT, "
"calling XConvertSelection to g_utf8_atom");
"calling XConvertSelection to g_utf8_atom");
g_clip_s2c.xrdp_clip_type = XRDP_CB_TEXT;
XConvertSelection(g_display, g_clipboard_atom, g_utf8_atom,
g_clip_property_atom, g_wnd, CurrentTime);
@ -1186,7 +1188,7 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
break;
default:
log_debug("clipboard_process_data_request: unknown type %d",
requestedFormatId);
requestedFormatId);
clipboard_send_data_response_failed();
break;
}
@ -1201,14 +1203,14 @@ clipboard_process_data_request(struct stream *s, int clip_msg_status,
clipboard data. */
static int
clipboard_process_data_response_for_image(struct stream *s,
int clip_msg_status,
int clip_msg_len)
int clip_msg_status,
int clip_msg_len)
{
XSelectionRequestEvent *lxev;
int len;
log_debug("clipboard_process_data_response_for_image: "
"CLIPRDR_DATA_RESPONSE_FOR_IMAGE");
"CLIPRDR_DATA_RESPONSE_FOR_IMAGE");
lxev = &g_saved_selection_req_event;
len = (int)(s->end - s->p);
if (len < 1)
@ -1231,7 +1233,7 @@ clipboard_process_data_response_for_image(struct stream *s,
g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14);
in_uint8a(s, g_clip_c2s.data + 14, len);
log_debug("clipboard_process_data_response_for_image: calling "
"clipboard_provide_selection_c2s");
"clipboard_provide_selection_c2s");
clipboard_provide_selection_c2s(lxev, lxev->target);
return 0;
}
@ -1259,7 +1261,7 @@ clipboard_process_data_response(struct stream *s, int clip_msg_status,
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_BITMAP)
{
clipboard_process_data_response_for_image(s, clip_msg_status,
clip_msg_len);
clip_msg_len);
return 0;
}
if (g_clip_c2s.xrdp_clip_type == XRDP_CB_FILE)
@ -1287,7 +1289,7 @@ clipboard_process_data_response(struct stream *s, int clip_msg_status,
return 0;
}
log_debug("clipboard_process_data_response: "
"CLIPRDR_DATA_RESPONSE");
"CLIPRDR_DATA_RESPONSE");
len = (int)(s->end - s->p);
if (len < 1)
{
@ -1362,10 +1364,10 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
in_uint32_le(s, version); /* version */
in_uint32_le(s, flags); /* generalFlags */
log_debug("clipboard_process_clip_caps: "
"g_cliprdr_version %d version %d "
"g_cliprdr_flags 0x%x flags 0x%x",
g_cliprdr_version, version,
g_cliprdr_flags, flags);
"g_cliprdr_version %d version %d "
"g_cliprdr_flags 0x%x flags 0x%x",
g_cliprdr_version, version,
g_cliprdr_flags, flags);
if (version < g_cliprdr_version)
{
g_cliprdr_version = version;
@ -1374,7 +1376,7 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
break;
default:
log_debug("clipboard_process_clip_caps: unknown "
"capabilitySetType %d", capabilitySetType);
"capabilitySetType %d", capabilitySetType);
break;
}
s->p = holdp + lengthCapability;
@ -1552,16 +1554,16 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
if (!g_clip_up)
{
log_error("aborting clipboard_data_in - clipboard has not "
"been initialized");
"been initialized");
/* we return 0 here to indicate no protocol problem occurred */
return 0;
}
log_debug("clipboard_data_in: chan_id %d "
"chan_flags 0x%x length %d total_length %d "
"in_request %d g_ins->size %d",
chan_id, chan_flags, length, total_length,
g_clip_c2s.in_request, g_ins->size);
"chan_flags 0x%x length %d total_length %d "
"in_request %d g_ins->size %d",
chan_id, chan_flags, length, total_length,
g_clip_c2s.in_request, g_ins->size);
if (g_clip_c2s.doing_response_ss)
{
@ -1621,37 +1623,37 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
in_uint32_le(ls, clip_msg_len);
log_debug("clipboard_data_in: clip_msg_id %d "
"clip_msg_status %d clip_msg_len %d",
clip_msg_id, clip_msg_status, clip_msg_len);
"clip_msg_status %d clip_msg_len %d",
clip_msg_id, clip_msg_status, clip_msg_len);
rv = 0;
log_debug("clipboard_data_in: %d", clip_msg_id);
switch (clip_msg_id)
{
/* sent by client or server when its local system clipboard is */
/* updated with new clipboard data; contains Clipboard Format ID */
/* and name pairs of new Clipboard Formats on the clipboard. */
/* sent by client or server when its local system clipboard is */
/* updated with new clipboard data; contains Clipboard Format ID */
/* and name pairs of new Clipboard Formats on the clipboard. */
case CB_FORMAT_LIST: /* 2 CLIPRDR_FORMAT_ANNOUNCE */
rv = clipboard_process_format_announce(ls, clip_msg_status,
clip_msg_len);
break;
/* response to CB_FORMAT_LIST; used to indicate whether */
/* processing of the Format List PDU was successful */
/* response to CB_FORMAT_LIST; used to indicate whether */
/* processing of the Format List PDU was successful */
case CB_FORMAT_LIST_RESPONSE: /* 3 CLIPRDR_FORMAT_ACK */
rv = clipboard_process_format_ack(ls, clip_msg_status,
clip_msg_len);
break;
/* sent by recipient of CB_FORMAT_LIST; used to request data for one */
/* of the formats that was listed in CB_FORMAT_LIST */
/* sent by recipient of CB_FORMAT_LIST; used to request data for one */
/* of the formats that was listed in CB_FORMAT_LIST */
case CB_FORMAT_DATA_REQUEST: /* 4 CLIPRDR_DATA_REQUEST */
rv = clipboard_process_data_request(ls, clip_msg_status,
clip_msg_len);
break;
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
/* whether processing of the CB_FORMAT_DATA_REQUEST was */
/* successful; if processing was successful, */
/* CB_FORMAT_DATA_RESPONSE includes contents of requested */
/* clipboard data. */
/* sent as a reply to CB_FORMAT_DATA_REQUEST; used to indicate */
/* whether processing of the CB_FORMAT_DATA_REQUEST was */
/* successful; if processing was successful, */
/* CB_FORMAT_DATA_RESPONSE includes contents of requested */
/* clipboard data. */
case CB_FORMAT_DATA_RESPONSE: /* 5 CLIPRDR_DATA_RESPONSE */
rv = clipboard_process_data_response(ls, clip_msg_status,
clip_msg_len);
@ -1671,7 +1673,7 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
default:
log_debug("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id);
log_error("clipboard_data_in: unknown clip_msg_id %d",
clip_msg_id);
clip_msg_id);
break;
}
@ -1703,21 +1705,22 @@ clipboard_event_selection_owner_notify(XEvent *xevent)
lxevent = (XFixesSelectionNotifyEvent *)xevent;
log_debug("clipboard_event_selection_owner_notify: 0x%lx", lxevent->owner);
log_debug("clipboard_event_selection_owner_notify: "
"window %ld subtype %d owner %ld g_wnd %ld",
lxevent->window, lxevent->subtype, lxevent->owner, g_wnd);
"window %ld subtype %d owner %ld g_wnd %ld",
lxevent->window, lxevent->subtype, lxevent->owner, g_wnd);
if (lxevent->owner == g_wnd)
{
log_debug("clipboard_event_selection_owner_notify: matches g_wnd");
log_debug("clipboard_event_selection_owner_notify: skipping, "
"owner == g_wnd");
"owner == g_wnd");
g_got_selection = 1;
return 0;
}
g_got_selection = 0;
if (lxevent->owner != 0) /* nil owner comes when selection */
{ /* window is closed */
{
/* window is closed */
XConvertSelection(g_display, g_clipboard_atom, g_targets_atom,
g_clip_property_atom, g_wnd, lxevent->timestamp);
}
@ -1871,22 +1874,22 @@ clipboard_event_selection_notify(XEvent *xevent)
if (lxevent->property == None)
{
log_error("clipboard_event_selection_notify: clip could "
"not be converted");
"not be converted");
rv = 1;
}
if (rv == 0)
{
log_debug("clipboard_event_selection_notify: wnd 0x%lx prop %s",
lxevent->requestor,
get_atom_text(lxevent->property));
lxevent->requestor,
get_atom_text(lxevent->property));
rv = clipboard_get_window_property(lxevent->requestor, lxevent->property,
&type, &fmt,
&n_items, &data, &data_size);
if (rv != 0)
{
log_error("clipboard_event_selection_notify: "
"clipboard_get_window_property failed error %d", rv);
"clipboard_get_window_property failed error %d", rv);
return 0;
}
//g_hexdump(data, data_size);
@ -1896,9 +1899,9 @@ clipboard_event_selection_notify(XEvent *xevent)
/* nothing more to do here, the data is coming in through
PropertyNotify */
log_debug("clipboard_event_selection_notify: type is INCR "
"data_size %d property name %s type %s", data_size,
get_atom_text(lxevent->property),
get_atom_text(lxevent->type));
"data_size %d property name %s type %s", data_size,
get_atom_text(lxevent->property),
get_atom_text(lxevent->type));
g_clip_s2c.incr_in_progress = 1;
g_clip_s2c.property = lxevent->property;
g_clip_s2c.type = lxevent->target;
@ -1928,7 +1931,7 @@ clipboard_event_selection_notify(XEvent *xevent)
"clipboard_event_selection_notify: 0x%lx %s 0x%lx",
atom, get_atom_text(atom), XA_STRING));
log_debug("clipboard_event_selection_notify: 0x%lx %s",
atom, get_atom_text(atom));
atom, get_atom_text(atom));
if (atom == g_utf8_atom)
{
got_utf8 = 1;
@ -1955,16 +1958,16 @@ clipboard_event_selection_notify(XEvent *xevent)
else
{
log_error("clipboard_event_selection_notify: error, "
"target is 'TARGETS' and type[%ld] or fmt[%d] not right, "
"should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32);
"target is 'TARGETS' and type[%ld] or fmt[%d] not right, "
"should be type[%ld], fmt[%d]", type, fmt, XA_ATOM, 32);
}
}
else if (lxevent->target == g_utf8_atom)
{
log_debug("clipboard_event_selection_notify: UTF8_STRING "
"data_size %d", data_size);
"data_size %d", data_size);
log_debug("clipboard_event_selection_notify: UTF8_STRING "
"data_size %d", data_size);
"data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{
g_free(g_clip_s2c.data);
@ -1987,9 +1990,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == XA_STRING)
{
log_debug("clipboard_event_selection_notify: XA_STRING "
"data_size %d", data_size);
"data_size %d", data_size);
log_debug("clipboard_event_selection_notify: XA_STRING "
"data_size %d", data_size);
"data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{
g_free(g_clip_s2c.data);
@ -2004,9 +2007,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_image_bmp_atom)
{
log_debug("clipboard_event_selection_notify: image/bmp "
"data_size %d", data_size);
"data_size %d", data_size);
log_debug("clipboard_event_selection_notify: image/bmp "
"data_size %d", data_size);
"data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 14))
{
g_free(g_clip_s2c.data);
@ -2020,9 +2023,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_file_atom1)
{
log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size);
"data_size %d", data_size);
log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size);
"data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{
g_free(g_clip_s2c.data);
@ -2037,9 +2040,9 @@ clipboard_event_selection_notify(XEvent *xevent)
else if (lxevent->target == g_file_atom2)
{
log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size);
"data_size %d", data_size);
log_debug("clipboard_event_selection_notify: text/uri-list "
"data_size %d", data_size);
"data_size %d", data_size);
if ((g_clip_s2c.incr_in_progress == 0) && (data_size > 0))
{
g_free(g_clip_s2c.data);
@ -2054,13 +2057,13 @@ clipboard_event_selection_notify(XEvent *xevent)
else
{
log_error("clipboard_event_selection_notify: "
"unknown target");
"unknown target");
}
}
else
{
log_error("clipboard_event_selection_notify: "
"unknown selection");
"unknown selection");
}
}
@ -2145,24 +2148,24 @@ clipboard_event_selection_request(XEvent *xevent)
lxev = (XSelectionRequestEvent *)xevent;
log_debug("clipboard_event_selection_request: 0x%lx", lxev->property);
log_debug("clipboard_event_selection_request: g_wnd %ld, "
".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld",
g_wnd, lxev->requestor, lxev->owner, lxev->selection,
get_atom_text(lxev->selection),
lxev->target, lxev->property);
".requestor %ld .owner %ld .selection %ld '%s' .target %ld .property %ld",
g_wnd, lxev->requestor, lxev->owner, lxev->selection,
get_atom_text(lxev->selection),
lxev->target, lxev->property);
if (lxev->property == None)
{
log_debug("clipboard_event_selection_request: lxev->property "
"is None");
"is None");
log_debug("clipboard_event_selection_request: "
"lxev->property is None");
"lxev->property is None");
}
else if (lxev->target == g_targets_atom)
{
log_debug("clipboard_event_selection_request: g_targets_atom");
/* requestor is asking what the selection can be converted to */
log_debug("clipboard_event_selection_request: "
"g_targets_atom");
"g_targets_atom");
atom_buf[0] = g_targets_atom;
atom_buf[1] = g_timestamp_atom;
atom_buf[2] = g_multiple_atom;
@ -2193,7 +2196,7 @@ clipboard_event_selection_request(XEvent *xevent)
{
/* requestor is asking the time I got the selection */
log_debug("clipboard_event_selection_request: "
"g_timestamp_atom");
"g_timestamp_atom");
atom_buf[0] = g_selection_time;
atom_buf[1] = 0;
return clipboard_provide_selection(lxev, XA_INTEGER, 32,
@ -2203,7 +2206,7 @@ clipboard_event_selection_request(XEvent *xevent)
{
/* target, property pairs */
log_debug("clipboard_event_selection_request: "
"g_multiple_atom");
"g_multiple_atom");
xdata = 0;
if (clipboard_get_window_property(lxev->requestor, lxev->property,
@ -2211,7 +2214,7 @@ clipboard_event_selection_request(XEvent *xevent)
&xdata_size) == 0)
{
log_debug("clipboard_event_selection_request: g_multiple_atom "
"n_items %d", n_items);
"n_items %d", n_items);
/* todo */
g_free(xdata);
}
@ -2276,7 +2279,7 @@ clipboard_event_selection_request(XEvent *xevent)
else
{
log_debug("clipboard_event_selection_request: unknown "
"target %s", get_atom_text(lxev->target));
"target %s", get_atom_text(lxev->target));
LOGM((LOG_LEVEL_ERROR, "clipboard_event_selection_request: unknown "
"target %s", get_atom_text(lxev->target)));
}
@ -2332,9 +2335,9 @@ clipboard_event_property_notify(XEvent *xevent)
log_debug("clipboard_event_property_notify:");
log_debug("clipboard_event_property_notify: PropertyNotify .window %ld "
".state %d .atom %ld %s", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom,
get_atom_text(xevent->xproperty.atom));
".state %d .atom %ld %s", xevent->xproperty.window,
xevent->xproperty.state, xevent->xproperty.atom,
get_atom_text(xevent->xproperty.atom));
if (g_clip_c2s.incr_in_progress &&
(xevent->xproperty.window == g_clip_c2s.window) &&
@ -2353,7 +2356,7 @@ clipboard_event_property_notify(XEvent *xevent)
data = (tui8 *)(g_clip_c2s.data + g_clip_c2s.incr_bytes_done);
data_bytes = g_clip_c2s.read_bytes_done - g_clip_c2s.incr_bytes_done;
if ((data_bytes < 1) &&
(g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes))
(g_clip_c2s.read_bytes_done < g_clip_c2s.total_bytes))
{
g_clip_c2s.incr_in_progress = 0;
return 0;
@ -2423,7 +2426,7 @@ clipboard_event_property_notify(XEvent *xevent)
else
{
log_error("clipboard_event_property_notify: error unknown type %ld",
g_clip_s2c.type);
g_clip_s2c.type);
clipboard_send_data_response_failed();
}
@ -2484,6 +2487,8 @@ clipboard_xevent(void *xevent)
{
XEvent *lxevent;
log_debug("clipboard_xevent: event detected");
if (!g_clip_up)
{
return 1;
@ -2494,7 +2499,15 @@ clipboard_xevent(void *xevent)
switch (lxevent->type)
{
case SelectionNotify:
clipboard_event_selection_notify(lxevent);
if (g_restrict_outbound_clipboard == 0)
{
clipboard_event_selection_notify(lxevent);
}
else
{
log_debug("outbound clipboard is restricted because of config");
return 1;
}
break;
case SelectionRequest:
clipboard_event_selection_request(lxevent);

View File

@ -235,6 +235,7 @@ config_read_security(int file, struct config_security *sc,
sc->login_retry = 3;
sc->ts_users_enable = 0;
sc->ts_admins_enable = 0;
sc->restrict_outbound_clipboard = 0;
file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);
@ -273,6 +274,12 @@ config_read_security(int file, struct config_security *sc,
{
sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i));
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
{
sc->restrict_outbound_clipboard = g_text2bool((char *)list_get_item(param_v, i));
}
}
return 0;
@ -481,7 +488,7 @@ config_dump(struct config_sesman *config)
g_writeln(" DefaultWindowManager: %s", config->default_wm);
g_writeln(" ReconnectScript: %s", config->reconnect_sh);
g_writeln(" AuthFilePath: %s",
((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
((config->auth_file_path) ? (config->auth_file_path) : ("disabled")));
/* Session configuration */
g_writeln("Session configuration:");
@ -497,6 +504,7 @@ config_dump(struct config_sesman *config)
g_writeln(" AllowRootLogin: %d", sc->allow_root);
g_writeln(" MaxLoginRetry: %d", sc->login_retry);
g_writeln(" AlwaysGroupCheck: %d", sc->ts_always_group_check);
g_writeln(" RestrictOutboundClipboard: %d", sc->restrict_outbound_clipboard);
g_printf( " TSUsersGroup: ");
if (sc->ts_users_enable)
@ -530,7 +538,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->xorg_params->count; i++)
{
g_writeln(" Parameter %02d %s",
i, (char *) list_get_item(config->xorg_params, i));
i, (char *) list_get_item(config->xorg_params, i));
}
/* Xvnc */
@ -542,7 +550,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->vnc_params->count; i++)
{
g_writeln(" Parameter %02d %s",
i, (char *)list_get_item(config->vnc_params, i));
i, (char *)list_get_item(config->vnc_params, i));
}
/* X11rdp */
@ -554,7 +562,7 @@ config_dump(struct config_sesman *config)
for (i = 0; i < config->rdp_params->count; i++)
{
g_writeln(" Parameter %02d %s",
i, (char *)list_get_item(config->rdp_params, i));
i, (char *)list_get_item(config->rdp_params, i));
}
/* SessionVariables */
@ -567,7 +575,7 @@ config_dump(struct config_sesman *config)
{
g_writeln(" Parameter %02d %s=%s",
i, (char *) list_get_item(config->env_names, i),
(char *) list_get_item(config->env_values, i));
(char *) list_get_item(config->env_values, i));
}
}

View File

@ -54,12 +54,13 @@
#define SESMAN_CFG_LOG_ENABLE_SYSLOG "EnableSyslog"
#define SESMAN_CFG_LOG_SYSLOG_LEVEL "SyslogLevel"
*/
#define SESMAN_CFG_SECURITY "Security"
#define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry"
#define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin"
#define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
#define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
#define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
#define SESMAN_CFG_SECURITY "Security"
#define SESMAN_CFG_SEC_LOGIN_RETRY "MaxLoginRetry"
#define SESMAN_CFG_SEC_ALLOW_ROOT "AllowRootLogin"
#define SESMAN_CFG_SEC_USR_GROUP "TerminalServerUsers"
#define SESMAN_CFG_SEC_ADM_GROUP "TerminalServerAdmins"
#define SESMAN_CFG_SEC_ALWAYSGROUPCHECK "AlwaysGroupCheck"
#define SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD "RestrictOutboundClipboard"
#define SESMAN_CFG_SESSIONS "Sessions"
#define SESMAN_CFG_SESS_MAX "MaxSessions"
@ -126,6 +127,11 @@ struct config_security
* @brief if the Groups are not found deny access
*/
int ts_always_group_check;
/**
* @var restrict_outbound_clipboard
* @brief if the clipboard should be enforced restricted. If true only allow client -> server, not vice versa.
*/
int restrict_outbound_clipboard;
};
/**

View File

@ -19,6 +19,9 @@ TerminalServerAdmins=tsadmins
; When AlwaysGroupCheck=false access will be permitted
; if the group TerminalServerUsers is not defined.
AlwaysGroupCheck=false
; When RestrictOutboundClipboard=true clipboard from the
; server is not pushed to the client.
RestrictOutboundClipboard=false
[Sessions]
;; X11DisplayOffset - x11 display number offset

View File

@ -374,6 +374,11 @@ session_start_chansrv(char *username, int display)
g_cfg->env_names,
g_cfg->env_values);
if (g_cfg->sec.restrict_outbound_clipboard == 1)
{
g_setenv("CHANSRV_RESTRICT_OUTBOUND_CLIPBOARD", "1", 1);
}
/* executing chansrv */
g_execvp(exe_path, (char **) (chansrv_params->items));
/* should not get here */