diff --git a/src/libguac/guacamole/recording.h b/src/libguac/guacamole/recording.h index e44bc8468d..eeafbca5df 100644 --- a/src/libguac/guacamole/recording.h +++ b/src/libguac/guacamole/recording.h @@ -48,6 +48,11 @@ */ #define GUAC_COMMON_RECORDING_MAX_NAME_LENGTH 2048 +/** + * The block size to use when sending clipboard data in a recording. + */ +#define GUAC_RECORDING_CLIPBOARD_BLOCK_SIZE 4096 + /** * An in-progress session recording, attached to a guac_client instance such * that output Guacamole instructions may be dynamically intercepted and @@ -61,6 +66,12 @@ typedef struct guac_recording { */ guac_socket* socket; + /** + * The stream used for recording clipboard data. This stream is allocated + * once during recording creation and reused for all clipboard events. + */ + guac_stream* clipboard_stream; + /** * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should be included in the session recording, @@ -95,6 +106,15 @@ typedef struct guac_recording { */ int include_keys; + /** + * Non-zero if clipboard paste data should be included in the session + * recording, zero otherwise. Including clipboard data within the recording may + * be necessary in certain auditing contexts, but should only be done with + * caution. Clipboard can easily contain sensitive information, such as + * passwords, credit card numbers, etc. + */ + int include_clipboard; + } guac_recording; /** @@ -152,6 +172,13 @@ typedef struct guac_recording { * Non-zero if writing to an existing file should be allowed, or zero * otherwise. * + * @param include_clipboard + * Non-zero if clipboard paste data should be included in the session + * recording, zero otherwise. Including clipboard data within the recording may + * be necessary in certain auditing contexts, but should only be done with + * caution. Clipboard can easily contain sensitive information, such as + * passwords, credit card numbers, etc. + * * @return * A new guac_recording structure representing the in-progress * recording if the recording file has been successfully created and a @@ -160,7 +187,7 @@ typedef struct guac_recording { guac_recording* guac_recording_create(guac_client* client, const char* path, const char* name, int create_path, int include_output, int include_mouse, int include_touch, - int include_keys, int allow_write_existing); + int include_keys, int allow_write_existing, int include_clipboard); /** * Frees the resources associated with the given in-progress recording. Note @@ -256,5 +283,69 @@ void guac_recording_report_touch(guac_recording* recording, void guac_recording_report_key(guac_recording* recording, int keysym, int pressed); -#endif +/** + * Reports a clipboard paste instruction within the recording. + * The full structure consists of clipboard instruction, one or more + * blob instructions and end instruction. + * + * @param recording + * The guac_recording associated with the clipboard instruction. + * + * @param stream + * The guac_stream allocated for the clipboard paste instruction. + * + * @param mimetype + * The clipboard data mimetype + */ +void guac_recording_report_clipboard_begin(guac_recording* recording, + guac_stream* stream, char* mimetype); + +/** + * Report a clipboard paste blob within the recording. + * + * @param recording + * The guac_recording associated with the clipboard instruction. + * + * @param stream + * The guac_stream associated with the clipboard instruction. + * + * @param data + * The clipboard blob data. + * + * @param length + * Length of the blob data. + */ +void guac_recording_report_clipboard_blob(guac_recording* recording, + guac_stream* stream, void* data, int length); + +/** + * Report a clipboard paste end instruction within the recording. + * + * @param recording + * The guac_recording associated with the clipboard instruction. + * + * @param stream + * The guac_stream associated with the clipboard instruction. + */ +void guac_recording_report_clipboard_end(guac_recording* recording, + guac_stream* stream); +/** + * Reports clipboard data within the recording. + * + * @param recording + * The guac_recording to write clipboard data to. + * + * @param mimetype + * The mimetype of the clipboard data (e.g., "text/plain"). + * + * @param data + * The clipboard data buffer. + * + * @param length + * The length of the clipboard data in bytes. + */ +void guac_recording_report_clipboard(guac_recording* recording, + const char* mimetype, const char* data, int length); + +#endif diff --git a/src/libguac/recording.c b/src/libguac/recording.c index 2cfcdf39dd..e5636ec144 100644 --- a/src/libguac/recording.c +++ b/src/libguac/recording.c @@ -42,7 +42,7 @@ guac_recording* guac_recording_create(guac_client* client, const char* path, const char* name, int create_path, int include_output, int include_mouse, int include_touch, - int include_keys, int allow_write_existing) { + int include_keys, int allow_write_existing, int include_clipboard) { char filename[GUAC_COMMON_RECORDING_MAX_NAME_LENGTH]; @@ -76,6 +76,12 @@ guac_recording* guac_recording_create(guac_client* client, recording->include_mouse = include_mouse; recording->include_touch = include_touch; recording->include_keys = include_keys; + recording->include_clipboard = include_clipboard; + + if (include_clipboard) + recording->clipboard_stream = guac_client_alloc_stream(client); + else + recording->clipboard_stream = NULL; /* Replace client socket with wrapped recording socket only if including * output within the recording */ @@ -133,3 +139,52 @@ void guac_recording_report_key(guac_recording* recording, } +void guac_recording_report_clipboard_begin(guac_recording* recording, guac_stream* stream, char* mimetype) { + /* Report clipboard only if recording should contain it */ + if (recording->include_clipboard) + guac_protocol_send_clipboard(recording->socket, stream, mimetype); +} + +void guac_recording_report_clipboard_blob(guac_recording* recording, guac_stream* stream, void* data, int length) { + /* Report clipboard only if recording should contain it */ + if (recording->include_clipboard) + guac_protocol_send_blob(recording->socket, stream, data, length); +} + +void guac_recording_report_clipboard_end(guac_recording* recording, guac_stream* stream) { + /* Report clipboard only if recording should contain it */ + if (recording->include_clipboard) + guac_protocol_send_end(recording->socket, stream); +} + +void guac_recording_report_clipboard(guac_recording* recording, + const char* mimetype, const char* data, int length) { + + /* Report clipboard only if recording should contain clipboard changes */ + if (!recording->include_clipboard || !recording->clipboard_stream) + return; + + guac_socket* socket = recording->socket; + guac_stream* stream = recording->clipboard_stream; + + const char* current = data; + int remaining = length; + + guac_protocol_send_clipboard(socket, stream, mimetype); + + while (remaining > 0) { + + int block_size = GUAC_RECORDING_CLIPBOARD_BLOCK_SIZE; + if (remaining < block_size) + block_size = remaining; + + guac_protocol_send_blob(socket, stream, current, block_size); + + remaining -= block_size; + current += block_size; + + } + + guac_protocol_send_end(socket, stream); + +} diff --git a/src/protocols/kubernetes/clipboard.c b/src/protocols/kubernetes/clipboard.c index f031f11e28..0fc3fd463f 100644 --- a/src/protocols/kubernetes/clipboard.c +++ b/src/protocols/kubernetes/clipboard.c @@ -39,6 +39,10 @@ int guac_kubernetes_clipboard_handler(guac_user* user, guac_stream* stream, stream->blob_handler = guac_kubernetes_clipboard_blob_handler; stream->end_handler = guac_kubernetes_clipboard_end_handler; + /* Report clipboard within recording */ + if (kubernetes_client->recording != NULL) + guac_recording_report_clipboard_begin(kubernetes_client->recording, stream, mimetype); + return 0; } @@ -49,6 +53,10 @@ int guac_kubernetes_clipboard_blob_handler(guac_user* user, guac_kubernetes_client* kubernetes_client = (guac_kubernetes_client*) client->data; + /* Report clipboard blob within recording */ + if (kubernetes_client->recording != NULL) + guac_recording_report_clipboard_blob(kubernetes_client->recording, stream, data, length); + /* Append new data */ guac_terminal_clipboard_append(kubernetes_client->term, data, length); @@ -58,8 +66,15 @@ int guac_kubernetes_clipboard_blob_handler(guac_user* user, int guac_kubernetes_clipboard_end_handler(guac_user* user, guac_stream* stream) { + guac_client* client = user->client; + guac_kubernetes_client* kubernetes_client = + (guac_kubernetes_client*) client->data; + + /* Report clipboard blob within recording */ + if (kubernetes_client->recording != NULL) + guac_recording_report_clipboard_end(kubernetes_client->recording, stream); + /* Nothing to do - clipboard is implemented within client */ return 0; } - diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index 7eef33b16a..f3d88103ce 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -238,7 +238,8 @@ void* guac_kubernetes_client_thread(void* data) { !settings->recording_exclude_mouse, 0, /* Touch events not supported */ settings->recording_include_keys, - settings->recording_write_existing); + settings->recording_write_existing, + settings->recording_include_clipboard); } /* Create terminal options with required parameters */ diff --git a/src/protocols/kubernetes/settings.c b/src/protocols/kubernetes/settings.c index a56ef8027f..0533a13e25 100644 --- a/src/protocols/kubernetes/settings.c +++ b/src/protocols/kubernetes/settings.c @@ -51,6 +51,7 @@ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = { "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", + "recording-include-clipboard", "create-recording-path", "recording-write-existing", "read-only", @@ -213,6 +214,16 @@ enum KUBERNETES_ARGS_IDX { */ IDX_RECORDING_INCLUDE_KEYS, + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + IDX_RECORDING_INCLUDE_CLIPBOARD, + /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. @@ -409,6 +420,11 @@ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); + /* Parse clipboard inclusion flag */ + settings->recording_include_clipboard = + guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, + IDX_RECORDING_INCLUDE_CLIPBOARD, false); + /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, diff --git a/src/protocols/kubernetes/settings.h b/src/protocols/kubernetes/settings.h index 2222c0a1d4..65173904cb 100644 --- a/src/protocols/kubernetes/settings.h +++ b/src/protocols/kubernetes/settings.h @@ -245,6 +245,16 @@ typedef struct guac_kubernetes_settings { */ bool recording_include_keys; + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + bool recording_include_clipboard; + /** * Whether existing files should be appended to when creating a new recording. * Disabled by default. diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index a93bf8c15c..bc93666388 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -521,6 +521,13 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, guac_common_clipboard_reset(clipboard->clipboard, "text/plain"); guac_common_clipboard_append(clipboard->clipboard, received_data, length); guac_common_clipboard_send(clipboard->clipboard, client); + + /* Record clipboard if recording is active */ + if (rdp_client->recording != NULL) + guac_recording_report_clipboard(rdp_client->recording, + clipboard->clipboard->mimetype, + clipboard->clipboard->buffer, + clipboard->clipboard->length); } guac_mem_free(received_data); @@ -695,6 +702,12 @@ int guac_rdp_clipboard_handler(guac_user* user, guac_stream* stream, /* Clear any current contents, assigning the mimetype the data which will * be received */ guac_common_clipboard_reset(clipboard->clipboard, mimetype); + + /* Report clipboard within recording */ + if (rdp_client->recording != NULL) + guac_recording_report_clipboard_begin(rdp_client->recording, stream, + mimetype); + return 0; } @@ -711,6 +724,10 @@ int guac_rdp_clipboard_blob_handler(guac_user* user, guac_stream* stream, if (clipboard == NULL) return 0; + /* Report clipboard blob within recording */ + if (rdp_client->recording != NULL) + guac_recording_report_clipboard_blob(rdp_client->recording, stream, data, length); + /* Append received data to current clipboard contents */ guac_common_clipboard_append(clipboard->clipboard, (char*) data, length); return 0; @@ -728,6 +745,10 @@ int guac_rdp_clipboard_end_handler(guac_user* user, guac_stream* stream) { if (clipboard == NULL) return 0; + /* Report clipboard stream end within recording */ + if (rdp_client->recording != NULL) + guac_recording_report_clipboard_end(rdp_client->recording, stream); + /* Terminate clipboard data with NULL */ guac_common_clipboard_append(clipboard->clipboard, "", 1); diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index aad1763b85..8e9fa305b7 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -930,7 +930,8 @@ void* guac_rdp_client_thread(void* data) { !settings->recording_exclude_mouse, !settings->recording_exclude_touch, settings->recording_include_keys, - settings->recording_write_existing); + settings->recording_write_existing, + settings->recording_include_clipboard); } /* Continue handling connections until error or client disconnect */ diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 2b2c91cbe1..ea81331f77 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -125,6 +125,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "recording-exclude-mouse", "recording-exclude-touch", "recording-include-keys", + "recording-include-clipboard", "create-recording-path", "recording-write-existing", "resize-method", @@ -581,6 +582,16 @@ enum RDP_ARGS_IDX { */ IDX_RECORDING_INCLUDE_KEYS, + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + IDX_RECORDING_INCLUDE_CLIPBOARD, + /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. @@ -1205,6 +1216,11 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, 0); + /* Parse clipboard inclusion flag */ + settings->recording_include_clipboard = + guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, + IDX_RECORDING_INCLUDE_CLIPBOARD, false); + /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 5f01a1adf3..ce71f84848 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -590,6 +590,16 @@ typedef struct guac_rdp_settings { */ int recording_include_keys; + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + bool recording_include_clipboard; + /** * Non-zero if existing files should be appended to when creating a new * recording. Disabled by default. diff --git a/src/protocols/ssh/clipboard.c b/src/protocols/ssh/clipboard.c index 0e2363259f..49c8815c4c 100644 --- a/src/protocols/ssh/clipboard.c +++ b/src/protocols/ssh/clipboard.c @@ -38,15 +38,24 @@ int guac_ssh_clipboard_handler(guac_user* user, guac_stream* stream, stream->blob_handler = guac_ssh_clipboard_blob_handler; stream->end_handler = guac_ssh_clipboard_end_handler; + /* Report clipboard within recording */ + if (ssh_client->recording != NULL) + guac_recording_report_clipboard_begin(ssh_client->recording, stream, + mimetype); + return 0; } int guac_ssh_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { - - /* Append new data */ guac_client* client = user->client; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; + + /* Report clipboard blob within recording */ + if (ssh_client->recording != NULL) + guac_recording_report_clipboard_blob(ssh_client->recording, stream, data, length); + + /* Append new data */ guac_terminal_clipboard_append(ssh_client->term, data, length); return 0; @@ -54,8 +63,14 @@ int guac_ssh_clipboard_blob_handler(guac_user* user, guac_stream* stream, int guac_ssh_clipboard_end_handler(guac_user* user, guac_stream* stream) { + guac_client* client = user->client; + guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; + + /* Report clipboard stream end within recording */ + if (ssh_client->recording != NULL) + guac_recording_report_clipboard_end(ssh_client->recording, stream); + /* Nothing to do - clipboard is implemented within client */ return 0; } - diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c index a4ea39ba61..69c1b1bb69 100644 --- a/src/protocols/ssh/settings.c +++ b/src/protocols/ssh/settings.c @@ -65,6 +65,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = { "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", + "recording-include-clipboard", "create-recording-path", "recording-write-existing", "read-only", @@ -251,6 +252,16 @@ enum SSH_ARGS_IDX { */ IDX_RECORDING_INCLUDE_KEYS, + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + IDX_RECORDING_INCLUDE_CLIPBOARD, + /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. @@ -527,6 +538,11 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); + /* Parse clipboard inclusion flag */ + settings->recording_include_clipboard = + guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, + IDX_RECORDING_INCLUDE_CLIPBOARD, false); + /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, diff --git a/src/protocols/ssh/settings.h b/src/protocols/ssh/settings.h index c67c292f56..521ab07282 100644 --- a/src/protocols/ssh/settings.h +++ b/src/protocols/ssh/settings.h @@ -274,6 +274,16 @@ typedef struct guac_ssh_settings { */ bool recording_include_keys; + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + bool recording_include_clipboard; + /** * Whether existing files should be appended to when creating a new recording. * Disabled by default. diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 1c5ba76f5e..e978e62242 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -286,7 +286,8 @@ void* ssh_client_thread(void* data) { !settings->recording_exclude_mouse, 0, /* Touch events not supported */ settings->recording_include_keys, - settings->recording_write_existing); + settings->recording_write_existing, + settings->recording_include_clipboard); } /* Create terminal options with required parameters */ diff --git a/src/protocols/telnet/clipboard.c b/src/protocols/telnet/clipboard.c index 08d28b111f..f6e81a6037 100644 --- a/src/protocols/telnet/clipboard.c +++ b/src/protocols/telnet/clipboard.c @@ -38,15 +38,25 @@ int guac_telnet_clipboard_handler(guac_user* user, guac_stream* stream, stream->blob_handler = guac_telnet_clipboard_blob_handler; stream->end_handler = guac_telnet_clipboard_end_handler; + /* Report clipboard within recording */ + if (telnet_client->recording != NULL) + guac_recording_report_clipboard_begin(telnet_client->recording, stream, + mimetype); + return 0; } int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream, void* data, int length) { - /* Append new data */ guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; + + /* Report clipboard blob within recording */ + if (telnet_client->recording != NULL) + guac_recording_report_clipboard_blob(telnet_client->recording, stream, data, length); + + /* Append new data */ guac_terminal_clipboard_append(telnet_client->term, data, length); return 0; @@ -54,8 +64,14 @@ int guac_telnet_clipboard_blob_handler(guac_user* user, guac_stream* stream, int guac_telnet_clipboard_end_handler(guac_user* user, guac_stream* stream) { + guac_client* client = user->client; + guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; + + /* Report clipboard stream end within recording */ + if (telnet_client->recording != NULL) + guac_recording_report_clipboard_end(telnet_client->recording, stream); + /* Nothing to do - clipboard is implemented within client */ return 0; } - diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c index 7a8277927a..0ce89a7dd2 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -56,6 +56,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = { "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", + "recording-include-clipboard", "create-recording-path", "recording-write-existing", "read-only", @@ -197,6 +198,16 @@ enum TELNET_ARGS_IDX { */ IDX_RECORDING_INCLUDE_KEYS, + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + IDX_RECORDING_INCLUDE_CLIPBOARD, + /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. @@ -507,6 +518,11 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); + /* Parse clipboard inclusion flag */ + settings->recording_include_clipboard = + guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, + IDX_RECORDING_INCLUDE_CLIPBOARD, false); + /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, diff --git a/src/protocols/telnet/settings.h b/src/protocols/telnet/settings.h index 5eb8f2fb80..6fe378c18b 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -250,6 +250,16 @@ typedef struct guac_telnet_settings { */ bool recording_include_keys; + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + bool recording_include_clipboard; + /** * Whether existing files should be appended to when creating a new recording. * Disabled by default. diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index 37e68e0777..8f6afb1d3a 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -537,7 +537,8 @@ void* guac_telnet_client_thread(void* data) { !settings->recording_exclude_mouse, 0, /* Touch events not supported */ settings->recording_include_keys, - settings->recording_write_existing); + settings->recording_write_existing, + settings->recording_include_clipboard); } /* Create terminal options with required parameters */ diff --git a/src/protocols/vnc/clipboard.c b/src/protocols/vnc/clipboard.c index aea0bcd226..8dbbb590f6 100644 --- a/src/protocols/vnc/clipboard.c +++ b/src/protocols/vnc/clipboard.c @@ -92,6 +92,11 @@ int guac_vnc_clipboard_handler(guac_user* user, guac_stream* stream, stream->blob_handler = guac_vnc_clipboard_blob_handler; stream->end_handler = guac_vnc_clipboard_end_handler; + /* Report clipboard within recording */ + if (vnc_client->recording != NULL) + guac_recording_report_clipboard_begin(vnc_client->recording, stream, + mimetype); + return 0; } @@ -106,6 +111,10 @@ int guac_vnc_clipboard_blob_handler(guac_user* user, guac_stream* stream, if (clipboard == NULL) return 0; + /* Report clipboard blob within recording */ + if (vnc_client->recording != NULL) + guac_recording_report_clipboard_blob(vnc_client->recording, stream, data, length); + /* Append new data */ guac_common_clipboard_append(clipboard, (char*) data, length); @@ -131,6 +140,10 @@ int guac_vnc_clipboard_end_handler(guac_user* user, guac_stream* stream) { char* output = output_data; guac_iconv_write* writer = vnc_client->clipboard_writer; + /* Report clipboard stream end within recording */ + if (vnc_client->recording != NULL) + guac_recording_report_clipboard_end(vnc_client->recording, stream); + /* Convert clipboard contents */ guac_iconv(GUAC_READ_UTF8, &input, clipboard->length, writer, &output, output_buf_size); @@ -171,4 +184,3 @@ void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { guac_mem_free(received_data); } - diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c index 64d3f9266c..570e222e94 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -87,6 +87,7 @@ const char* GUAC_VNC_CLIENT_ARGS[] = { "recording-exclude-output", "recording-exclude-mouse", "recording-include-keys", + "recording-include-clipboard", "create-recording-path", "recording-write-existing", "clipboard-buffer-size", @@ -353,6 +354,16 @@ enum VNC_ARGS_IDX { */ IDX_RECORDING_INCLUDE_KEYS, + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + IDX_RECORDING_INCLUDE_CLIPBOARD, + /** * Whether the specified screen recording path should automatically be * created if it does not yet exist. @@ -676,6 +687,11 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_INCLUDE_KEYS, false); + /* Parse clipboard inclusion flag */ + settings->recording_include_clipboard = + guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_RECORDING_INCLUDE_CLIPBOARD, false); + /* Parse path creation flag */ settings->create_recording_path = guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, diff --git a/src/protocols/vnc/settings.h b/src/protocols/vnc/settings.h index a23585f0db..9d489ad13c 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -312,6 +312,16 @@ typedef struct guac_vnc_settings { */ bool recording_include_keys; + /** + * Whether clipboard paste data should be included in the session recording. + * Clipboard data is NOT included by default within the recording, + * as doing so has privacy and security implications. Including clipboard data + * may be necessary in certain auditing contexts, but should only be done + * with caution. Clipboard data can easily contain sensitive information, such + * as passwords, credit card numbers, etc. + */ + bool recording_include_clipboard; + /** * Whether existing files should be appended to when creating a new recording. * Disabled by default. diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 8f5fa9129f..5b6886c631 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -587,7 +587,8 @@ void* guac_vnc_client_thread(void* data) { !settings->recording_exclude_mouse, 0, /* Touch events not supported */ settings->recording_include_keys, - settings->recording_write_existing); + settings->recording_write_existing, + settings->recording_include_clipboard); } /* Create display */