diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 3342079d0..ba99b3532 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -939,6 +939,14 @@ void* guac_rdp_client_thread(void* data) { !settings->recording_exclude_touch, settings->recording_include_keys, settings->recording_write_existing); + + /* 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 49a38af06..86bc63110 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -127,6 +127,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "recording-include-keys", "create-recording-path", "recording-write-existing", + "require-recording", "resize-method", "enable-audio-input", "enable-touch", @@ -593,6 +594,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". @@ -1216,6 +1223,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 b4bb098d2..bd02514bc 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -595,6 +595,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 456f80f52..6998aba57 100644 --- a/src/protocols/ssh/settings.c +++ b/src/protocols/ssh/settings.c @@ -69,6 +69,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = { "recording-include-keys", "create-recording-path", "recording-write-existing", + "require-recording", "read-only", "server-alive-interval", "backspace", @@ -266,6 +267,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. @@ -546,6 +553,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 3d4f9a7e8..128055faf 100644 --- a/src/protocols/ssh/settings.h +++ b/src/protocols/ssh/settings.h @@ -278,6 +278,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 30cadf261..3f5224e55 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -293,6 +293,14 @@ void* ssh_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing); + + /* 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 3da708113..1a61500a8 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -60,6 +60,7 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = { "recording-include-keys", "create-recording-path", "recording-write-existing", + "require-recording", "read-only", "backspace", "func-keys-and-keypad", @@ -212,6 +213,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. @@ -526,6 +533,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 a92201b2d..368445558 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -254,6 +254,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 c084bffca..609cff81a 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -549,6 +549,14 @@ void* guac_telnet_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing); + + /* 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 7828971f7..e0ab20b2f 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -91,6 +91,7 @@ const char* GUAC_VNC_CLIENT_ARGS[] = { "recording-include-keys", "create-recording-path", "recording-write-existing", + "require-recording", "clipboard-buffer-size", "disable-copy", "disable-paste", @@ -367,6 +368,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. */ @@ -688,6 +695,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 1588b07db..8af2633e9 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -315,6 +315,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 630ce9868..2f8f0d16f 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -588,6 +588,14 @@ void* guac_vnc_client_thread(void* data) { 0, /* Touch events not supported */ settings->recording_include_keys, settings->recording_write_existing); + + /* 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 */