Skip to content

Commit 44c1bd2

Browse files
committed
GUACAMOLE-2002: Allow connection clipboard limits to be configured.
1 parent 32dbdfa commit 44c1bd2

24 files changed

+275
-41
lines changed

src/common/clipboard.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
#include <string.h>
3131
#include <stdlib.h>
3232

33-
guac_common_clipboard* guac_common_clipboard_alloc() {
33+
guac_common_clipboard* guac_common_clipboard_alloc(int buffer_size) {
3434

3535
guac_common_clipboard* clipboard = guac_mem_alloc(sizeof(guac_common_clipboard));
3636

3737
/* Init clipboard */
3838
clipboard->mimetype[0] = '\0';
39-
clipboard->buffer = guac_mem_alloc(GUAC_COMMON_CLIPBOARD_MAX_LENGTH);
40-
clipboard->available = GUAC_COMMON_CLIPBOARD_MAX_LENGTH;
39+
clipboard->buffer = guac_mem_alloc(buffer_size);
40+
clipboard->available = buffer_size;
4141
clipboard->length = 0;
4242

4343
pthread_mutex_init(&(clipboard->lock), NULL);

src/common/common/clipboard.h

+33-11
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,16 @@
3232
#define GUAC_COMMON_CLIPBOARD_BLOCK_SIZE 4096
3333

3434
/**
35-
* The maximum number of bytes to allow within the clipboard.
35+
* The minimum clipboard buffer size in bytes.
36+
* This is the original hardcoded clipboard buffer size.
3637
*/
37-
#define GUAC_COMMON_CLIPBOARD_MAX_LENGTH 262144
38+
#define GUAC_COMMON_CLIPBOARD_MIN_LENGTH 262144
39+
40+
/**
41+
* The maximum clipboard buffer size in bytes.
42+
* This should be enough for a raw 4K picture and even more.
43+
*/
44+
#define GUAC_COMMON_CLIPBOARD_MAX_LENGTH 52428800
3845

3946
/**
4047
* Generic clipboard structure.
@@ -72,30 +79,40 @@ typedef struct guac_common_clipboard {
7279

7380
/**
7481
* Creates a new clipboard.
82+
*
83+
* @param buffer_size
84+
* The buffer size in bytes.
7585
*/
76-
guac_common_clipboard* guac_common_clipboard_alloc();
86+
guac_common_clipboard* guac_common_clipboard_alloc(int buffer_size);
7787

7888
/**
7989
* Frees the given clipboard.
8090
*
81-
* @param clipboard The clipboard to free.
91+
* @param clipboard
92+
* The clipboard to free.
8293
*/
8394
void guac_common_clipboard_free(guac_common_clipboard* clipboard);
8495

8596
/**
8697
* Sends the contents of the clipboard along the given client, splitting
8798
* the contents as necessary.
8899
*
89-
* @param clipboard The clipboard whose contents should be sent.
90-
* @param client The client to send the clipboard contents on.
100+
* @param clipboard
101+
* The clipboard whose contents should be sent.
102+
*
103+
* @param client
104+
* The client to send the clipboard contents on.
91105
*/
92106
void guac_common_clipboard_send(guac_common_clipboard* clipboard, guac_client* client);
93107

94108
/**
95109
* Clears the clipboard contents and assigns a new mimetype for future data.
96110
*
97-
* @param clipboard The clipboard to reset.
98-
* @param mimetype The mimetype of future data.
111+
* @param clipboard
112+
* The clipboard to reset.
113+
*
114+
* @param mimetype
115+
* The mimetype of future data.
99116
*/
100117
void guac_common_clipboard_reset(guac_common_clipboard* clipboard, const char* mimetype);
101118

@@ -104,9 +121,14 @@ void guac_common_clipboard_reset(guac_common_clipboard* clipboard, const char* m
104121
* match the mimetype chosen for the clipboard data by
105122
* guac_common_clipboard_reset().
106123
*
107-
* @param clipboard The clipboard to append data to.
108-
* @param data The data to append.
109-
* @param length The number of bytes to append from the data given.
124+
* @param clipboard
125+
* The clipboard to append data to.
126+
*
127+
* @param data
128+
* The data to append.
129+
*
130+
* @param length
131+
* The number of bytes to append from the data given.
110132
*/
111133
void guac_common_clipboard_append(guac_common_clipboard* clipboard, const char* data, int length);
112134

src/protocols/kubernetes/kubernetes.c

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ void* guac_kubernetes_client_thread(void* data) {
246246
settings->width, settings->height, settings->resolution);
247247

248248
/* Set optional parameters */
249+
options->clipboard_buffer_size = settings->clipboard_buffer_size;
249250
options->disable_copy = settings->disable_copy;
250251
options->max_scrollback = settings->max_scrollback;
251252
options->font_name = settings->font_name;

src/protocols/kubernetes/settings.c

+27
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = {
5656
"read-only",
5757
"backspace",
5858
"scrollback",
59+
"clipboard-buffer-size",
5960
"disable-copy",
6061
"disable-paste",
6162
NULL
@@ -241,6 +242,11 @@ enum KUBERNETES_ARGS_IDX {
241242
*/
242243
IDX_SCROLLBACK,
243244

245+
/**
246+
* The maximum number of bytes to allow within the clipboard.
247+
*/
248+
IDX_CLIPBOARD_BUFFER_SIZE,
249+
244250
/**
245251
* Whether outbound clipboard access should be blocked. If set to "true",
246252
* it will not be possible to copy data from the terminal to the client
@@ -418,6 +424,27 @@ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user,
418424
guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
419425
IDX_BACKSPACE, GUAC_TERMINAL_DEFAULT_BACKSPACE);
420426

427+
/* Set the maximum number of bytes to allow within the clipboard. */
428+
settings->clipboard_buffer_size =
429+
guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,
430+
IDX_CLIPBOARD_BUFFER_SIZE, 0);
431+
432+
/* Use default clipboard buffer size if given one is invalid. */
433+
if (settings->clipboard_buffer_size < GUAC_COMMON_CLIPBOARD_MIN_LENGTH) {
434+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MIN_LENGTH;
435+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
436+
"size: \"%s\". Using the default minimum size: %i.",
437+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
438+
settings->clipboard_buffer_size);
439+
}
440+
else if (settings->clipboard_buffer_size > GUAC_COMMON_CLIPBOARD_MAX_LENGTH) {
441+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MAX_LENGTH;
442+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
443+
"size: \"%s\". Using the default maximum size: %i.",
444+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
445+
settings->clipboard_buffer_size);
446+
}
447+
421448
/* Parse clipboard copy disable flag */
422449
settings->disable_copy =
423450
guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv,

src/protocols/kubernetes/settings.h

+5
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ typedef struct guac_kubernetes_settings {
160160
*/
161161
int resolution;
162162

163+
/**
164+
* The maximum number of bytes to allow within the clipboard.
165+
*/
166+
int clipboard_buffer_size;
167+
163168
/**
164169
* Whether outbound clipboard access should be blocked. If set, it will not
165170
* be possible to copy data from the terminal to the client using the

src/protocols/rdp/channels/cliprdr.c

+13-7
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,9 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
371371

372372
guac_iconv_write* remote_writer;
373373
const char* input = clipboard->clipboard->buffer;
374-
char* output = guac_mem_alloc(GUAC_COMMON_CLIPBOARD_MAX_LENGTH);
374+
375+
int output_buf_size = clipboard->clipboard->available;
376+
char* output = guac_mem_alloc(output_buf_size);
375377

376378
/* Map requested clipboard format to a guac_iconv writer */
377379
switch (format_data_request->requestedFormatId) {
@@ -402,7 +404,7 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr,
402404
BYTE* start = (BYTE*) output;
403405
guac_iconv_read* local_reader = settings->normalize_clipboard ? GUAC_READ_UTF8_NORMALIZED : GUAC_READ_UTF8;
404406
guac_iconv(local_reader, &input, clipboard->clipboard->length,
405-
remote_writer, &output, GUAC_COMMON_CLIPBOARD_MAX_LENGTH);
407+
remote_writer, &output, output_buf_size);
406408

407409
CLIPRDR_FORMAT_DATA_RESPONSE data_response = {
408410
.requestedFormatData = (BYTE*) start,
@@ -470,7 +472,8 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
470472
return CHANNEL_RC_OK;
471473
}
472474

473-
char received_data[GUAC_COMMON_CLIPBOARD_MAX_LENGTH];
475+
int output_buf_size = clipboard->clipboard->available;
476+
char* received_data = guac_mem_alloc(output_buf_size);
474477

475478
guac_iconv_read* remote_reader;
476479
const char* input = (char*) format_data_response->requestedFormatData;
@@ -498,6 +501,7 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
498501
default:
499502
guac_client_log(client, GUAC_LOG_DEBUG, "Requested clipboard data "
500503
"in unsupported format (0x%X).", clipboard->requested_format);
504+
guac_mem_free(received_data);
501505
return CHANNEL_RC_OK;
502506

503507
}
@@ -512,13 +516,15 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr,
512516
/* Convert, store, and forward the clipboard data received from RDP
513517
* server */
514518
if (guac_iconv(remote_reader, &input, data_len,
515-
GUAC_WRITE_UTF8, &output, sizeof(received_data))) {
516-
int length = strnlen(received_data, sizeof(received_data));
519+
GUAC_WRITE_UTF8, &output, output_buf_size)) {
520+
int length = strnlen(received_data, output_buf_size);
517521
guac_common_clipboard_reset(clipboard->clipboard, "text/plain");
518522
guac_common_clipboard_append(clipboard->clipboard, received_data, length);
519523
guac_common_clipboard_send(clipboard->clipboard, client);
520524
}
521525

526+
guac_mem_free(received_data);
527+
522528
return CHANNEL_RC_OK;
523529

524530
}
@@ -618,12 +624,12 @@ static void guac_rdp_cliprdr_channel_disconnected(rdpContext* context,
618624

619625
}
620626

621-
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client) {
627+
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client, int buffer_size) {
622628

623629
/* Allocate clipboard and underlying storage */
624630
guac_rdp_clipboard* clipboard = guac_mem_zalloc(sizeof(guac_rdp_clipboard));
625631
clipboard->client = client;
626-
clipboard->clipboard = guac_common_clipboard_alloc();
632+
clipboard->clipboard = guac_common_clipboard_alloc(buffer_size);
627633
clipboard->requested_format = CF_TEXT;
628634

629635
return clipboard;

src/protocols/rdp/channels/cliprdr.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,14 @@ typedef struct guac_rdp_clipboard {
7171
* The guac_client associated with the Guacamole side of the RDP
7272
* connection.
7373
*
74+
* @param buffer_size
75+
* The buffer size in bytes.
76+
*
7477
* @return
7578
* A newly-allocated instance of guac_rdp_clipboard which has been
7679
* initialized for processing Guacamole clipboard data.
7780
*/
78-
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client);
81+
guac_rdp_clipboard* guac_rdp_clipboard_alloc(guac_client* client, int buffer_size);
7982

8083
/**
8184
* Initializes clipboard support for RDP and handling of the CLIPRDR channel.

src/protocols/rdp/client.c

-3
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
205205
guac_rdp_client* rdp_client = guac_mem_zalloc(sizeof(guac_rdp_client));
206206
client->data = rdp_client;
207207

208-
/* Init clipboard */
209-
rdp_client->clipboard = guac_rdp_clipboard_alloc(client);
210-
211208
/* Init display update module */
212209
rdp_client->disp = guac_rdp_disp_alloc(client);
213210

src/protocols/rdp/settings.c

+27
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
140140

141141
"load-balance-info",
142142

143+
"clipboard-buffer-size",
143144
"disable-copy",
144145
"disable-paste",
145146

@@ -658,6 +659,11 @@ enum RDP_ARGS_IDX {
658659
* the connection broker, if a connection broker is being used.
659660
*/
660661
IDX_LOAD_BALANCE_INFO,
662+
663+
/**
664+
* The maximum number of bytes to allow within the clipboard.
665+
*/
666+
IDX_CLIPBOARD_BUFFER_SIZE,
661667

662668
/**
663669
* Whether outbound clipboard access should be blocked. If set to "true",
@@ -1284,6 +1290,27 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user,
12841290
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
12851291
IDX_LOAD_BALANCE_INFO, NULL);
12861292

1293+
/* Set the maximum number of bytes to allow within the clipboard. */
1294+
settings->clipboard_buffer_size =
1295+
guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv,
1296+
IDX_CLIPBOARD_BUFFER_SIZE, 0);
1297+
1298+
/* Use default clipboard buffer size if given one is invalid. */
1299+
if (settings->clipboard_buffer_size < GUAC_COMMON_CLIPBOARD_MIN_LENGTH) {
1300+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MIN_LENGTH;
1301+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
1302+
"size: \"%s\". Using the default minimum size: %i.",
1303+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
1304+
settings->clipboard_buffer_size);
1305+
}
1306+
else if (settings->clipboard_buffer_size > GUAC_COMMON_CLIPBOARD_MAX_LENGTH) {
1307+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MAX_LENGTH;
1308+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
1309+
"size: \"%s\". Using the default maximum size: %i.",
1310+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
1311+
settings->clipboard_buffer_size);
1312+
}
1313+
12871314
/* Parse clipboard copy disable flag */
12881315
settings->disable_copy =
12891316
guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv,

src/protocols/rdp/settings.h

+5
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,11 @@ typedef struct guac_rdp_settings {
341341
*/
342342
char** svc_names;
343343

344+
/**
345+
* The maximum number of bytes to allow within the clipboard.
346+
*/
347+
int clipboard_buffer_size;
348+
344349
/**
345350
* Whether outbound clipboard access should be blocked. If set, it will not
346351
* be possible to copy data from the remote desktop to the client using the

src/protocols/rdp/user.c

+4
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ int guac_rdp_user_join_handler(guac_user* user, int argc, char** argv) {
6767
/* Store owner's settings at client level */
6868
rdp_client->settings = settings;
6969

70+
/* Init clipboard */
71+
rdp_client->clipboard =
72+
guac_rdp_clipboard_alloc(user->client, settings->clipboard_buffer_size);
73+
7074
/* Start client thread */
7175
if (pthread_create(&rdp_client->client_thread, NULL,
7276
guac_rdp_client_thread, user->client)) {

src/protocols/ssh/settings.c

+28
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "argv.h"
2323
#include "client.h"
2424
#include "common/defaults.h"
25+
#include "common/clipboard.h"
2526
#include "settings.h"
2627
#include "terminal/terminal.h"
2728

@@ -73,6 +74,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
7374
"scrollback",
7475
"locale",
7576
"timezone",
77+
"clipboard-buffer-size",
7678
"disable-copy",
7779
"disable-paste",
7880
"wol-send-packet",
@@ -310,6 +312,11 @@ enum SSH_ARGS_IDX {
310312
*/
311313
IDX_TIMEZONE,
312314

315+
/**
316+
* The maximum number of bytes to allow within the clipboard.
317+
*/
318+
IDX_CLIPBOARD_BUFFER_SIZE,
319+
313320
/**
314321
* Whether outbound clipboard access should be blocked. If set to "true",
315322
* it will not be possible to copy data from the terminal to the client
@@ -555,6 +562,27 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
555562
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
556563
IDX_TIMEZONE, user->info.timezone);
557564

565+
/* Set the maximum number of bytes to allow within the clipboard. */
566+
settings->clipboard_buffer_size =
567+
guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv,
568+
IDX_CLIPBOARD_BUFFER_SIZE, 0);
569+
570+
/* Use default clipboard buffer size if given one is invalid. */
571+
if (settings->clipboard_buffer_size < GUAC_COMMON_CLIPBOARD_MIN_LENGTH) {
572+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MIN_LENGTH;
573+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
574+
"size: \"%s\". Using the default minimum size: %i.",
575+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
576+
settings->clipboard_buffer_size);
577+
}
578+
else if (settings->clipboard_buffer_size > GUAC_COMMON_CLIPBOARD_MAX_LENGTH) {
579+
settings->clipboard_buffer_size = GUAC_COMMON_CLIPBOARD_MAX_LENGTH;
580+
guac_user_log(user, GUAC_LOG_ERROR, "Invalid clipboard buffer "
581+
"size: \"%s\". Using the default maximum size: %i.",
582+
argv[IDX_CLIPBOARD_BUFFER_SIZE],
583+
settings->clipboard_buffer_size);
584+
}
585+
558586
/* Parse clipboard copy disable flag */
559587
settings->disable_copy =
560588
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,

0 commit comments

Comments
 (0)