From 942d2f64789d1f67bf450a27ac6f2a1a5d365712 Mon Sep 17 00:00:00 2001 From: Siva Gudivada Date: Wed, 29 Apr 2026 19:53:21 +0000 Subject: [PATCH 1/4] GUACAMOLE-2223: Add new "require-recording" flag to RDP, SSH, Telnet, and VNC settings --- src/protocols/rdp/rdp.c | 8 ++++++++ src/protocols/rdp/settings.c | 12 ++++++++++++ src/protocols/rdp/settings.h | 7 +++++++ src/protocols/ssh/settings.c | 12 ++++++++++++ src/protocols/ssh/settings.h | 7 +++++++ src/protocols/ssh/ssh.c | 8 ++++++++ src/protocols/telnet/settings.c | 12 ++++++++++++ src/protocols/telnet/settings.h | 7 +++++++ src/protocols/telnet/telnet.c | 8 ++++++++ src/protocols/vnc/settings.c | 12 ++++++++++++ src/protocols/vnc/settings.h | 7 +++++++ src/protocols/vnc/vnc.c | 8 ++++++++ 12 files changed, 108 insertions(+) diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 797a95e98..cb4764363 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -940,6 +940,14 @@ void* guac_rdp_client_thread(void* data) { settings->recording_include_keys, settings->recording_write_existing, settings->recording_include_clipboard); + + /* If recording is required but failed, abort the connection */ + if (rdp_client->recording == NULL && settings->require_recording) { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Session recording is required but could not be created. " + "Aborting connection."); + return NULL; + } } /* Continue handling connections until error or client disconnect */ diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index 1a1ff97f2..f00a05b63 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -128,6 +128,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "recording-include-clipboard", "create-recording-path", "recording-write-existing", + "require-recording", "resize-method", "enable-audio-input", "enable-touch", @@ -604,6 +605,12 @@ enum RDP_ARGS_IDX { */ IDX_RECORDING_WRITE_EXISTING, + /** + * Whether recording is required. If set to "true", the connection will + * be closed if the recording cannot be created for any reason. + */ + IDX_REQUIRE_RECORDING, + /** * The method to use to apply screen size changes requested by the user. * Valid values are blank, "display-update", and "reconnect". @@ -1232,6 +1239,11 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_RECORDING_WRITE_EXISTING, 0); + /* Parse require recording flag */ + settings->require_recording = + guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, + IDX_REQUIRE_RECORDING, 0); + /* No resize method */ if (strcmp(argv[IDX_RESIZE_METHOD], "") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Resize method: none"); diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index 6b2928773..e0cbfccf0 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -605,6 +605,13 @@ typedef struct guac_rdp_settings { */ int recording_write_existing; + /** + * Non-zero if the connection should be closed when a recording cannot be + * created. Zero by default, meaning the connection will proceed even if + * recording fails. + */ + int require_recording; + /** * The method to apply when the user's display changes size. */ diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c index b7a8f43c4..184550bec 100644 --- a/src/protocols/ssh/settings.c +++ b/src/protocols/ssh/settings.c @@ -70,6 +70,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = { "recording-include-clipboard", "create-recording-path", "recording-write-existing", + "require-recording", "read-only", "server-alive-interval", "backspace", @@ -277,6 +278,12 @@ enum SSH_ARGS_IDX { */ IDX_RECORDING_WRITE_EXISTING, + /** + * Whether recording is required. If set to "true", the connection will + * be closed if the recording cannot be created for any reason. + */ + IDX_REQUIRE_RECORDING, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -562,6 +569,11 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_RECORDING_WRITE_EXISTING, false); + /* Parse require recording flag */ + settings->require_recording = + guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, + IDX_REQUIRE_RECORDING, false); + /* Parse server alive interval */ settings->server_alive_interval = guac_user_parse_args_int(user, GUAC_SSH_CLIENT_ARGS, argv, diff --git a/src/protocols/ssh/settings.h b/src/protocols/ssh/settings.h index 1e130ec59..183b145c3 100644 --- a/src/protocols/ssh/settings.h +++ b/src/protocols/ssh/settings.h @@ -288,6 +288,13 @@ typedef struct guac_ssh_settings { */ bool recording_write_existing; + /** + * Non-zero if the connection should be closed when a recording cannot be + * created. Zero by default, meaning the connection will proceed even if + * recording fails. + */ + bool require_recording; + /** * The number of seconds between sending server alive messages. */ diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 5bf38633b..4364d1c06 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -294,6 +294,14 @@ void* ssh_client_thread(void* data) { settings->recording_include_keys, settings->recording_write_existing, settings->recording_include_clipboard); + + /* If recording is required but failed, abort the connection */ + if (ssh_client->recording == NULL && settings->require_recording) { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Session recording is required but could not be created. " + "Aborting connection."); + return NULL; + } } /* Create terminal options with required parameters */ diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c index 20ba07f9d..70d8b727f 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -61,6 +61,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = { "recording-include-clipboard", "create-recording-path", "recording-write-existing", + "require-recording", "read-only", "backspace", "func-keys-and-keypad", @@ -223,6 +224,12 @@ enum TELNET_ARGS_IDX { */ IDX_RECORDING_WRITE_EXISTING, + /** + * Whether recording is required. If set to "true", the connection will + * be closed if the recording cannot be created for any reason. + */ + IDX_REQUIRE_RECORDING, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -542,6 +549,11 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_RECORDING_WRITE_EXISTING, false); + /* Parse require recording flag */ + settings->require_recording = + guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, + IDX_REQUIRE_RECORDING, false); + /* Parse backspace key code */ settings->backspace = guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv, diff --git a/src/protocols/telnet/settings.h b/src/protocols/telnet/settings.h index 77834e55f..6792d5365 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -264,6 +264,13 @@ typedef struct guac_telnet_settings { */ bool recording_write_existing; + /** + * Non-zero if the connection should be closed when a recording cannot be + * created. Zero by default, meaning the connection will proceed even if + * recording fails. + */ + bool require_recording; + /** * The ASCII code, as an integer, that the telnet client will use when the * backspace key is pressed. By default, this is 127, ASCII delete, if diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index 5ffc683aa..f7b3c2635 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -550,6 +550,14 @@ void* guac_telnet_client_thread(void* data) { settings->recording_include_keys, settings->recording_write_existing, settings->recording_include_clipboard); + + /* If recording is required but failed, abort the connection */ + if (telnet_client->recording == NULL && settings->require_recording) { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Session recording is required but could not be created. " + "Aborting connection."); + return NULL; + } } /* Create terminal options with required parameters */ diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c index 5ad05dd79..1fcb327b0 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -92,6 +92,7 @@ const char* GUAC_VNC_CLIENT_ARGS[] = { "recording-include-clipboard", "create-recording-path", "recording-write-existing", + "require-recording", "clipboard-buffer-size", "disable-copy", "disable-paste", @@ -378,6 +379,12 @@ enum VNC_ARGS_IDX { */ IDX_RECORDING_WRITE_EXISTING, + /** + * Whether recording is required. If set to "true", the connection will + * be closed if the recording cannot be created for any reason. + */ + IDX_REQUIRE_RECORDING, + /** * The maximum number of bytes to allow within the clipboard. */ @@ -704,6 +711,11 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_RECORDING_WRITE_EXISTING, false); + /* Parse require recording flag */ + settings->require_recording = + guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_REQUIRE_RECORDING, false); + /* Parse clipboard copy disable flag */ settings->disable_copy = 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 9bf75ca70..e599321a3 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -325,6 +325,13 @@ typedef struct guac_vnc_settings { * Disabled by default. */ bool recording_write_existing; + + /** + * Non-zero if the connection should be closed when a recording cannot be + * created. Zero by default, meaning the connection will proceed even if + * recording fails. + */ + bool require_recording; /** * Whether or not to send the magic Wake-on-LAN (WoL) packet prior to diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 0cd0bca2a..5e7bb169d 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -696,6 +696,14 @@ void* guac_vnc_client_thread(void* data) { settings->recording_include_keys, settings->recording_write_existing, settings->recording_include_clipboard); + + /* If recording is required but failed, abort the connection */ + if (vnc_client->recording == NULL && settings->require_recording) { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Session recording is required but could not be created. " + "Aborting connection."); + return NULL; + } } /* Create display */ From 3c4248759a2219ccec6086e239e43e4f1a56a866 Mon Sep 17 00:00:00 2001 From: Siva Gudivada Date: Fri, 29 May 2026 00:20:17 +0000 Subject: [PATCH 2/4] * convert to bool rdp/settings.h * update comments consistent with other boolean recording flags --- src/protocols/rdp/settings.h | 8 ++++---- src/protocols/ssh/settings.h | 6 +++--- src/protocols/telnet/settings.h | 6 +++--- src/protocols/vnc/settings.h | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/protocols/rdp/settings.h b/src/protocols/rdp/settings.h index e0cbfccf0..14d34e9c7 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -606,11 +606,11 @@ typedef struct guac_rdp_settings { int recording_write_existing; /** - * Non-zero if the connection should be closed when a recording cannot be - * created. Zero by default, meaning the connection will proceed even if - * recording fails. + * Whether the connection should be closed when a recording cannot be + * created. Disabled by default, meaning the connection will proceed even + * if recording fails. */ - int require_recording; + bool require_recording; /** * The method to apply when the user's display changes size. diff --git a/src/protocols/ssh/settings.h b/src/protocols/ssh/settings.h index 183b145c3..43983f891 100644 --- a/src/protocols/ssh/settings.h +++ b/src/protocols/ssh/settings.h @@ -289,9 +289,9 @@ typedef struct guac_ssh_settings { bool recording_write_existing; /** - * Non-zero if the connection should be closed when a recording cannot be - * created. Zero by default, meaning the connection will proceed even if - * recording fails. + * Whether the connection should be closed when a recording cannot be + * created. Disabled by default, meaning the connection will proceed even + * if recording fails. */ bool require_recording; diff --git a/src/protocols/telnet/settings.h b/src/protocols/telnet/settings.h index 6792d5365..34c679f44 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -265,9 +265,9 @@ typedef struct guac_telnet_settings { bool recording_write_existing; /** - * Non-zero if the connection should be closed when a recording cannot be - * created. Zero by default, meaning the connection will proceed even if - * recording fails. + * Whether the connection should be closed when a recording cannot be + * created. Disabled by default, meaning the connection will proceed even + * if recording fails. */ bool require_recording; diff --git a/src/protocols/vnc/settings.h b/src/protocols/vnc/settings.h index e599321a3..54a9c9b71 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -327,9 +327,9 @@ typedef struct guac_vnc_settings { bool recording_write_existing; /** - * Non-zero if the connection should be closed when a recording cannot be - * created. Zero by default, meaning the connection will proceed even if - * recording fails. + * Whether the connection should be closed when a recording cannot be + * created. Disabled by default, meaning the connection will proceed even + * if recording fails. */ bool require_recording; From 3aed1a1ba148df51a60376520b43c0a42b898912 Mon Sep 17 00:00:00 2001 From: Siva Gudivada Date: Fri, 29 May 2026 00:20:35 +0000 Subject: [PATCH 3/4] add flag to kubernetes --- src/protocols/kubernetes/kubernetes.c | 8 ++++++++ src/protocols/kubernetes/settings.c | 12 ++++++++++++ src/protocols/kubernetes/settings.h | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index c18f15184..26a25a793 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -240,6 +240,14 @@ void* guac_kubernetes_client_thread(void* data) { settings->recording_include_keys, settings->recording_write_existing, settings->recording_include_clipboard); + + /* If recording is required but failed, abort the connection */ + if (kubernetes_client->recording == NULL && settings->require_recording) { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Session recording is required but could not be created. " + "Aborting connection."); + return NULL; + } } /* Create terminal options with required parameters */ diff --git a/src/protocols/kubernetes/settings.c b/src/protocols/kubernetes/settings.c index 710f2cc4b..9069e063e 100644 --- a/src/protocols/kubernetes/settings.c +++ b/src/protocols/kubernetes/settings.c @@ -55,6 +55,7 @@ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = { "recording-include-clipboard", "create-recording-path", "recording-write-existing", + "require-recording", "read-only", "backspace", "scrollback", @@ -238,6 +239,12 @@ enum KUBERNETES_ARGS_IDX { */ IDX_RECORDING_WRITE_EXISTING, + /** + * Whether recording is required. If set to "true", the connection will + * be closed if the recording cannot be created for any reason. + */ + IDX_REQUIRE_RECORDING, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -443,6 +450,11 @@ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_RECORDING_WRITE_EXISTING, false); + /* Parse require recording flag */ + settings->require_recording = + guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, + IDX_REQUIRE_RECORDING, false); + /* Parse backspace key code */ settings->backspace = guac_user_parse_args_int(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, diff --git a/src/protocols/kubernetes/settings.h b/src/protocols/kubernetes/settings.h index 01db24207..48622c0de 100644 --- a/src/protocols/kubernetes/settings.h +++ b/src/protocols/kubernetes/settings.h @@ -261,6 +261,13 @@ typedef struct guac_kubernetes_settings { */ bool recording_write_existing; + /** + * Whether the connection should be closed when a recording cannot be + * created. Disabled by default, meaning the connection will proceed even + * if recording fails. + */ + bool require_recording; + /** * The ASCII code, as an integer, that the Kubernetes client will use when * the backspace key is pressed. By default, this is 127, ASCII delete, if From a749f285fc4a2090b746f9e4a24b4484235f49e1 Mon Sep 17 00:00:00 2001 From: Siva Gudivada Date: Fri, 29 May 2026 01:11:26 +0000 Subject: [PATCH 4/4] Handle runtime write failures:wrap fd socket to enforce require_recording --- src/libguac/guacamole/recording.h | 21 +++- src/libguac/recording.c | 134 +++++++++++++++++++++++++- src/protocols/kubernetes/kubernetes.c | 3 +- src/protocols/rdp/rdp.c | 3 +- src/protocols/ssh/ssh.c | 3 +- src/protocols/telnet/telnet.c | 3 +- src/protocols/vnc/vnc.c | 3 +- 7 files changed, 163 insertions(+), 7 deletions(-) diff --git a/src/libguac/guacamole/recording.h b/src/libguac/guacamole/recording.h index b39502e48..d111191da 100644 --- a/src/libguac/guacamole/recording.h +++ b/src/libguac/guacamole/recording.h @@ -115,6 +115,19 @@ typedef struct guac_recording { */ int include_clipboard; + /** + * The client associated with this recording. Used to abort the connection + * if a write to the recording fails and require_recording is set. + */ + guac_client* client; + + /** + * Whether the connection should be aborted if writing to the recording + * fails. If non-zero, any write error on the recording socket will + * trigger a connection abort. + */ + int require_recording; + } guac_recording; /** @@ -179,6 +192,11 @@ typedef struct guac_recording { * caution. Clipboard can easily contain sensitive information, such as * passwords, credit card numbers, etc. * + * @param require_recording + * Non-zero if the connection should be aborted when a write to the + * recording file fails, zero otherwise. If zero, write errors will be + * silently ignored and the connection will continue. + * * @return * A new guac_recording structure representing the in-progress * recording if the recording file has been successfully created and a @@ -187,7 +205,8 @@ 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_clipboard); + int include_keys, int allow_write_existing, int include_clipboard, + int require_recording); /** * Frees the resources associated with the given in-progress recording. Note diff --git a/src/libguac/recording.c b/src/libguac/recording.c index e5636ec14..edb0a9cd8 100644 --- a/src/libguac/recording.c +++ b/src/libguac/recording.c @@ -39,10 +39,134 @@ #include #include +/** + * Data specific to the write-required socket wrapper, which aborts the + * associated client connection if any write to the underlying socket fails. + */ +typedef struct guac_socket_require_write_data { + + /** + * The wrapped socket to which all write operations are delegated. + */ + guac_socket* wrapped; + + /** + * The client to abort if a write fails. + */ + guac_client* client; + +} guac_socket_require_write_data; + +/** + * Write handler for the require-write socket wrapper. Delegates the write to + * the wrapped socket, aborting the client connection on failure. + */ +static ssize_t __guac_socket_require_write_handler(guac_socket* socket, + const void* buf, size_t count) { + + guac_socket_require_write_data* data = + (guac_socket_require_write_data*) socket->data; + + if (guac_socket_write(data->wrapped, buf, count)) { + guac_client_abort(data->client, + GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Write to recording failed. Aborting connection."); + return -1; + } + + return count; + +} + +/** + * Flush handler for the require-write socket wrapper. Delegates the flush to + * the wrapped socket, aborting the client connection on failure. + */ +static ssize_t __guac_socket_require_flush_handler(guac_socket* socket) { + + guac_socket_require_write_data* data = + (guac_socket_require_write_data*) socket->data; + + if (guac_socket_flush(data->wrapped)) { + guac_client_abort(data->client, + GUAC_PROTOCOL_STATUS_SERVER_ERROR, + "Flush of recording failed. Aborting connection."); + return -1; + } + + return 0; + +} + +/** + * Lock handler for the require-write socket wrapper. + */ +static void __guac_socket_require_lock_handler(guac_socket* socket) { + guac_socket_require_write_data* data = + (guac_socket_require_write_data*) socket->data; + guac_socket_instruction_begin(data->wrapped); +} + +/** + * Unlock handler for the require-write socket wrapper. + */ +static void __guac_socket_require_unlock_handler(guac_socket* socket) { + guac_socket_require_write_data* data = + (guac_socket_require_write_data*) socket->data; + guac_socket_instruction_end(data->wrapped); +} + +/** + * Free handler for the require-write socket wrapper. Frees the wrapped socket + * and the wrapper data. + */ +static int __guac_socket_require_free_handler(guac_socket* socket) { + guac_socket_require_write_data* data = + (guac_socket_require_write_data*) socket->data; + guac_socket_free(data->wrapped); + guac_mem_free(data); + return 0; +} + +/** + * Creates a socket wrapper that aborts the given client's connection if any + * write to the underlying socket fails. + * + * @param socket + * The socket to wrap. + * + * @param client + * The client to abort on write failure. + * + * @return + * A new guac_socket that delegates to the given socket but aborts the + * client on any write or flush error. + */ +static guac_socket* guac_socket_require_write(guac_socket* wrapped, + guac_client* client) { + + guac_socket_require_write_data* data = + guac_mem_alloc(sizeof(guac_socket_require_write_data)); + data->wrapped = wrapped; + data->client = client; + + guac_socket* socket = guac_socket_alloc(); + socket->data = data; + socket->write_handler = __guac_socket_require_write_handler; + socket->flush_handler = __guac_socket_require_flush_handler; + socket->lock_handler = __guac_socket_require_lock_handler; + socket->unlock_handler = __guac_socket_require_unlock_handler; + socket->free_handler = __guac_socket_require_free_handler; + + return socket; + +} + 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_clipboard) { + int include_keys, int allow_write_existing, int include_clipboard, + int require_recording) { char filename[GUAC_COMMON_RECORDING_MAX_NAME_LENGTH]; @@ -77,6 +201,14 @@ guac_recording* guac_recording_create(guac_client* client, recording->include_touch = include_touch; recording->include_keys = include_keys; recording->include_clipboard = include_clipboard; + recording->client = client; + recording->require_recording = require_recording; + + /* If recording is required, wrap the recording socket so that any write + * failure will automatically abort the client connection */ + if (require_recording) + recording->socket = guac_socket_require_write( + recording->socket, client); if (include_clipboard) recording->clipboard_stream = guac_client_alloc_stream(client); diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index 26a25a793..7c4db6321 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -239,7 +239,8 @@ void* guac_kubernetes_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing, - settings->recording_include_clipboard); + settings->recording_include_clipboard, + settings->require_recording); /* If recording is required but failed, abort the connection */ if (kubernetes_client->recording == NULL && settings->require_recording) { diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index cb4764363..b1a5e5e32 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -939,7 +939,8 @@ void* guac_rdp_client_thread(void* data) { !settings->recording_exclude_touch, settings->recording_include_keys, settings->recording_write_existing, - settings->recording_include_clipboard); + settings->recording_include_clipboard, + settings->require_recording); /* If recording is required but failed, abort the connection */ if (rdp_client->recording == NULL && settings->require_recording) { diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 4364d1c06..c9c389c23 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -293,7 +293,8 @@ void* ssh_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing, - settings->recording_include_clipboard); + settings->recording_include_clipboard, + settings->require_recording); /* If recording is required but failed, abort the connection */ if (ssh_client->recording == NULL && settings->require_recording) { diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index f7b3c2635..04dba4f5a 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -549,7 +549,8 @@ void* guac_telnet_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing, - settings->recording_include_clipboard); + settings->recording_include_clipboard, + settings->require_recording); /* If recording is required but failed, abort the connection */ if (telnet_client->recording == NULL && settings->require_recording) { diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 5e7bb169d..2bbebce7d 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -695,7 +695,8 @@ void* guac_vnc_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing, - settings->recording_include_clipboard); + settings->recording_include_clipboard, + settings->require_recording); /* If recording is required but failed, abort the connection */ if (vnc_client->recording == NULL && settings->require_recording) {