Skip to content

Commit 7a3baed

Browse files
committed
Allow shortcut for multiple use of clipboard data
fixes: QubesOS/qubes-issues#6640
1 parent 89d0254 commit 7a3baed

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

gui-daemon/guid.conf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ global: {
6161
#
6262
# secure_copy_sequence = "Ctrl-Shift-c";
6363
# secure_paste_sequence = "Ctrl-Shift-v";
64+
#
65+
# Secure paste key sequence clears global clipboard after pasting. User could
66+
# set another key sequence for multiple-use of clipboard data. This could be
67+
# potentially a security risk and is disabled by default.
68+
#
69+
# secure_multipaste_sequence = "None";
6470

6571
# Limit number of windows
6672
#

gui-daemon/xside.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ static Time get_clipboard_xevent_timestamp(bool logging) {
976976

977977
/* fetch clippboard content from file */
978978
/* lock already taken in is_special_keypress() */
979-
static void get_qubes_clipboard(Ghandles *g, char **data, int *len)
979+
static void get_qubes_clipboard(Ghandles *g, char **data, int *len, bool multipaste)
980980
{
981981
FILE *file;
982982
*len = 0;
@@ -1041,7 +1041,16 @@ static void get_qubes_clipboard(Ghandles *g, char **data, int *len)
10411041
fclose(file);
10421042
metadata.sent_size = *len;
10431043
metadata.successful = true;
1044-
clear_clipboard(&metadata);
1044+
if (multipaste) {
1045+
// triggering notification by updating file modification time
1046+
if (utimensat(0, QUBES_CLIPBOARD_FILENAME, NULL, 0) == -1) {
1047+
show_error_message(g, "secure multi-paste: failed to update modification time of file " QUBES_CLIPBOARD_FILENAME);
1048+
} else {
1049+
metadata.cleared = false;
1050+
save_clipboard_metadata(&metadata);
1051+
}
1052+
} else
1053+
clear_clipboard(&metadata);
10451054
}
10461055

10471056
/* This is specific to Microsoft Windows and non-X11 compliant OS */
@@ -1513,8 +1522,13 @@ static int is_special_keypress(Ghandles * g, const XKeyEvent * ev, XID remote_wi
15131522
}
15141523

15151524
/* paste */
1516-
if (((int)ev->state & SPECIAL_KEYS_MASK) == g->paste_seq_mask
1517-
&& ev->keycode == XKeysymToKeycode(g->display, g->paste_seq_key)) {
1525+
bool multipaste = false;
1526+
if (((int)ev->state & SPECIAL_KEYS_MASK) == g->multipaste_seq_mask
1527+
&& ev->keycode == XKeysymToKeycode(g->display, g->multipaste_seq_key)) {
1528+
multipaste = true;
1529+
}
1530+
if (multipaste || (((int)ev->state & SPECIAL_KEYS_MASK) == g->paste_seq_mask
1531+
&& ev->keycode == XKeysymToKeycode(g->display, g->paste_seq_key))) {
15181532
if (ev->type != KeyPress)
15191533
return 1;
15201534
inter_appviewer_lock(g, 1);
@@ -1541,7 +1555,7 @@ static int is_special_keypress(Ghandles * g, const XKeyEvent * ev, XID remote_wi
15411555
hdr.type = MSG_CLIPBOARD_DATA;
15421556
if (g->log_level > 0)
15431557
fprintf(stderr, "secure paste\n");
1544-
get_qubes_clipboard(g, &data, &len);
1558+
get_qubes_clipboard(g, &data, &len, multipaste);
15451559
if (len > 0) {
15461560
/* MSG_CLIPBOARD_DATA used to use the window field to pass the length
15471561
of the blob, be aware when working with old implementations. */
@@ -4345,6 +4359,8 @@ static void load_default_config_values(Ghandles * g)
43454359
g->copy_seq_key = XK_c;
43464360
g->paste_seq_mask = ControlMask | ShiftMask;
43474361
g->paste_seq_key = XK_v;
4362+
g->multipaste_seq_mask = 0;
4363+
g->multipaste_seq_key = NoSymbol;
43484364
g->clipboard_buffer_size = DEFAULT_CLIPBOARD_BUFFER_SIZE;
43494365
g->allow_fullscreen = 0;
43504366
g->override_redirect_protection = 1;
@@ -4416,6 +4432,11 @@ static void parse_vm_config(Ghandles * g, config_setting_t * group)
44164432
parse_key_sequence(config_setting_get_string(setting),
44174433
&g->paste_seq_mask, &g->paste_seq_key);
44184434
}
4435+
if ((setting =
4436+
config_setting_get_member(group, "secure_multipaste_sequence"))) {
4437+
parse_key_sequence(config_setting_get_string(setting),
4438+
&g->multipaste_seq_mask, &g->multipaste_seq_key);
4439+
}
44194440

44204441
if ((setting =
44214442
config_setting_get_member(group, "max_clipboard_size"))) {

gui-daemon/xside.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ struct _global_handles {
218218
KeySym copy_seq_key; /* key for secure-copy key sequence */
219219
int paste_seq_mask; /* modifiers mask for secure-paste key sequence */
220220
KeySym paste_seq_key; /* key for secure-paste key sequence */
221+
int multipaste_seq_mask; /* modifiers mask for secure-multipaste key sequence */
222+
KeySym multipaste_seq_key; /* key for secure-multipaste key sequence */
221223
unsigned int clipboard_buffer_size; /* maximum clipboard size limit */
222224
int qrexec_clipboard; /* 0: use GUI protocol to fetch/put clipboard, 1: use qrexec */
223225
int use_kdialog; /* use kdialog for prompts (default on KDE) or zenity (default on non-KDE) */

0 commit comments

Comments
 (0)