From 6f72337842bf4ac6c82fe84c3f47440e16ac4f9a Mon Sep 17 00:00:00 2001 From: alailson Date: Sat, 6 Jan 2024 16:50:12 -0300 Subject: [PATCH] add-optionalpermissions: add ability to change permissions of screen record file and path --- src/libguac/guacamole/recording.h | 14 +++++- src/libguac/guacamole/user.h | 32 +++++++++++++ src/libguac/recording.c | 16 +++---- src/libguac/user.c | 66 +++++++++++++++++++++++++++ src/protocols/kubernetes/kubernetes.c | 2 + src/protocols/kubernetes/settings.c | 24 ++++++++++ src/protocols/kubernetes/settings.h | 22 +++++++++ src/protocols/rdp/rdp.c | 2 + src/protocols/rdp/settings.c | 24 ++++++++++ src/protocols/rdp/settings.h | 23 ++++++++++ src/protocols/ssh/settings.c | 24 ++++++++++ src/protocols/ssh/settings.h | 22 +++++++++ src/protocols/ssh/ssh.c | 2 + src/protocols/telnet/settings.c | 24 ++++++++++ src/protocols/telnet/settings.h | 21 +++++++++ src/protocols/telnet/telnet.c | 2 + src/protocols/vnc/settings.c | 24 ++++++++++ src/protocols/vnc/settings.h | 22 +++++++++ src/protocols/vnc/vnc.c | 2 + 19 files changed, 357 insertions(+), 11 deletions(-) diff --git a/src/libguac/guacamole/recording.h b/src/libguac/guacamole/recording.h index 667713d16..738abf21f 100644 --- a/src/libguac/guacamole/recording.h +++ b/src/libguac/guacamole/recording.h @@ -22,6 +22,8 @@ #include +#include + /** * Provides functions and structures to be use for session recording. * @@ -122,6 +124,14 @@ typedef struct guac_recording { * written, or non-zero if the path should be created if it does not yet * exist. * + * @param file_permissions + * The permissions to apply for the recording file created within the specified + * path. + * + * @param path_permissions + * The permissions to apply for the recording path created within the specified + * path. + * * @param include_output * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should be included in the session recording, @@ -154,8 +164,8 @@ typedef struct guac_recording { * recording will be written, NULL otherwise. */ 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, + const char* path, const char* name, int create_path, mode_t file_permissions, + mode_t path_permissions, int include_output, int include_mouse, int include_touch, int include_keys); /** diff --git a/src/libguac/guacamole/user.h b/src/libguac/guacamole/user.h index 13fb146d4..ac2c2ee9b 100644 --- a/src/libguac/guacamole/user.h +++ b/src/libguac/guacamole/user.h @@ -42,6 +42,7 @@ #include #include +#include struct guac_user_info { @@ -1001,5 +1002,36 @@ int guac_user_parse_args_int(guac_user* user, const char** arg_names, int guac_user_parse_args_boolean(guac_user* user, const char** arg_names, const char** argv, int index, int default_value); +/** + * Parses a string representation of file permissions (e.g., "rwxrwxrwx") + * and converts it to a mode_t value. + * + * @param user + * The user joining the connection and providing the given arguments. + * + * @param arg_names + * A NULL-terminated array of argument names, corresponding to the provided + * array of argument values. This array must be exactly the same size as + * the argument value array, with one additional entry for the NULL + * terminator. + * + * @param argv + * An array of all argument values, corresponding to the provided array of + * argument names. This array must be exactly the same size as the argument + * name array, with the exception of the NULL terminator. + * + * @param index + * The index of the entry in both the arg_names and argv arrays which + * corresponds to the argument being parsed. + * + * @param default_value + * The value to return if the provided argument is blank or invalid. + * + * @return + * The parsed mode_t value. + */ +mode_t guac_user_parse_args_mode(guac_user* user, const char** arg_names, + const char** argv, int index, mode_t default_value); + #endif diff --git a/src/libguac/recording.c b/src/libguac/recording.c index 7544cc144..f855928d3 100644 --- a/src/libguac/recording.c +++ b/src/libguac/recording.c @@ -65,7 +65,7 @@ * failure. */ static int guac_recording_open(const char* path, - const char* name, char* basename, int basename_size) { + const char* name, char* basename, int basename_size, mode_t file_permissions) { int i; @@ -83,8 +83,7 @@ static int guac_recording_open(const char* path, /* Attempt to open recording */ int fd = open(basename, - O_CREAT | O_EXCL | O_WRONLY, - S_IRUSR | S_IWUSR | S_IRGRP); + O_CREAT | O_EXCL | O_WRONLY, file_permissions); /* Continuously retry with alternate names on failure */ if (fd == -1) { @@ -102,8 +101,7 @@ static int guac_recording_open(const char* path, /* Retry with newly-suffixed filename */ fd = open(basename, - O_CREAT | O_EXCL | O_WRONLY, - S_IRUSR | S_IWUSR | S_IRGRP); + O_CREAT | O_EXCL | O_WRONLY, file_permissions); } @@ -136,15 +134,15 @@ static int guac_recording_open(const char* path, } 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, + const char* path, const char* name, int create_path, mode_t file_permissions, + mode_t path_permissions, int include_output, int include_mouse, int include_touch, int include_keys) { char filename[GUAC_COMMON_RECORDING_MAX_NAME_LENGTH]; /* Create path if it does not exist, fail if impossible */ #ifndef __MINGW32__ - if (create_path && mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP) + if (create_path && mkdir(path, path_permissions) && errno != EEXIST) { #else if (create_path && _mkdir(path) && errno != EEXIST) { @@ -155,7 +153,7 @@ guac_recording* guac_recording_create(guac_client* client, } /* Attempt to open recording file */ - int fd = guac_recording_open(path, name, filename, sizeof(filename)); + int fd = guac_recording_open(path, name, filename, sizeof(filename), file_permissions); if (fd == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Creation of recording failed: %s", strerror(errno)); diff --git a/src/libguac/user.c b/src/libguac/user.c index ba6819678..b9e30827a 100644 --- a/src/libguac/user.c +++ b/src/libguac/user.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include guac_user* guac_user_alloc() { @@ -466,3 +468,67 @@ int guac_user_parse_args_boolean(guac_user* user, const char** arg_names, } +mode_t guac_user_parse_args_mode(guac_user* user, const char** arg_names, + const char** argv, int index, mode_t default_value) { + + /* Pull parameter value from argv */ + const char* value = argv[index]; + + /* Use default value if blank */ + if (value[0] == 0) { + + /* Log use of default */ + guac_user_log(user, GUAC_LOG_DEBUG, "Parameter \"%s\" omitted. Using " + "default value of %i.", arg_names[index], default_value); + + return default_value; + + } + + mode_t result = 0; + + /* Check if the provided value has the correct length */ + if (strlen(value) != 9) { + /* Log a warning and return the default value if the length is incorrect */ + guac_user_log(user, GUAC_LOG_WARNING, "Parameter \"%s\" must have length 9. Using default value.", arg_names[index]); + return default_value; + } + + // Define the permission bits + const char *permissions = "rwxr-xr-x"; + + /* Iterate over each character in the permission string */ + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + int permissionIndex = i * 3 + j; + /* If the character '-' is present in the permission string, no action needed */ + if (value[permissionIndex] == '-') { + /* No action needed for '-' */ + } else if (value[permissionIndex] == permissions[permissionIndex]) { + // Calculate the permission bit based on the position in the permission string: + // Example: For the first set of three characters ("rwx"): + // S_IRUSR is the constant representing the read permission for the owner. + // (S_IRUSR >> (i * 3 + j)) dynamically adjusts the permission bit based on the position. + // When i = 0 and j takes values 0, 1, 2: + // - For j = 0, it gives (0400 >> 0), which is 0400 (read permission). + // - For j = 1, it gives (0400 >> 1), which is 0200 (write permission). + // - For j = 2, it gives (0400 >> 2), which is 0100 (execute permission). + // These values represent the read, write, and execute permission bits for the owner. + result |= (S_IRUSR >> (permissionIndex)); + } + /* If the character is equal 'w' for groups and others log a warning and return the default value */ + else if (value[permissionIndex] == 'w') { + guac_user_log(user, GUAC_LOG_WARNING, "Parameter \"%s\" with value \"%s\" has invalid permission character at position %d. Writing is locked for the current running process. Using default value %o.", arg_names[index], value, permissionIndex, default_value); + return default_value; + } + /* If the character is neither 'r', 'w', nor 'x', log a warning and return the default value */ + else { + guac_user_log(user, GUAC_LOG_WARNING, "Parameter \"%s\" with value \"%s\" has invalid permission character at position %d. Only 'r', 'w', 'x' and '-' characthers are allowed. Using default value %o.", arg_names[index], value, permissionIndex, default_value); + return default_value; + } + } + } + + /* Return the parsed mode_t value */ + return result; +} diff --git a/src/protocols/kubernetes/kubernetes.c b/src/protocols/kubernetes/kubernetes.c index 3a75bb2e7..a2bf5274e 100644 --- a/src/protocols/kubernetes/kubernetes.c +++ b/src/protocols/kubernetes/kubernetes.c @@ -234,6 +234,8 @@ void* guac_kubernetes_client_thread(void* data) { settings->recording_path, settings->recording_name, settings->create_recording_path, + settings->recording_file_permissions, + settings->recording_path_permissions, !settings->recording_exclude_output, !settings->recording_exclude_mouse, 0, /* Touch events not supported */ diff --git a/src/protocols/kubernetes/settings.c b/src/protocols/kubernetes/settings.c index 5da7d8bec..3aa450d8c 100644 --- a/src/protocols/kubernetes/settings.c +++ b/src/protocols/kubernetes/settings.c @@ -51,6 +51,8 @@ const char* GUAC_KUBERNETES_CLIENT_ARGS[] = { "recording-exclude-mouse", "recording-include-keys", "create-recording-path", + "recording-file-permissions", + "recording-path-permissions", "read-only", "backspace", "scrollback", @@ -210,6 +212,18 @@ enum KUBERNETES_ARGS_IDX { */ IDX_CREATE_RECORDING_PATH, + /** + * The permissions that should be given to screen recording file which is written in + * the given path. + */ + IDX_RECORDING_FILE_PERMISSIONS, + + /** + * The permissions that should be given to screen recording path which is written in + * the given path. + */ + IDX_RECORDING_PATH_PERMISSIONS, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -389,6 +403,16 @@ guac_kubernetes_settings* guac_kubernetes_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); + /* Parse file permissions flag */ + settings->recording_file_permissions = + guac_user_parse_args_mode(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, + IDX_RECORDING_FILE_PERMISSIONS, GUAC_KUBERNETES_DEFAULT_RECORDING_FILE_PERMISSIONS); + + /* Parse path permissions flag */ + settings->recording_path_permissions = + guac_user_parse_args_mode(user, GUAC_KUBERNETES_CLIENT_ARGS, argv, + IDX_RECORDING_PATH_PERMISSIONS, GUAC_KUBERNETES_DEFAULT_RECORDING_PATH_PERMISSIONS); + /* 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 f7c9c1c37..8a2c34fd4 100644 --- a/src/protocols/kubernetes/settings.h +++ b/src/protocols/kubernetes/settings.h @@ -23,6 +23,8 @@ #include #include +#include +#include /** * The port to connect to when initiating any Kubernetes connection, if no @@ -46,6 +48,16 @@ */ #define GUAC_KUBERNETES_DEFAULT_RECORDING_NAME "recording" +/** + * The permissions to use for the screen recording file, if not specified. + */ +#define GUAC_KUBERNETES_DEFAULT_RECORDING_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP) + +/** + * The permissions to use for the screen recording path, if not specified. + */ +#define GUAC_KUBERNETES_DEFAULT_RECORDING_PATH_PERMISSIONS (S_IRWXU | S_IRGRP | S_IXGRP) + /** * Settings for the Kubernetes connection. The values for this structure are * parsed from the arguments given during the Guacamole protocol handshake @@ -208,6 +220,16 @@ typedef struct guac_kubernetes_settings { */ bool create_recording_path; + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_file_permissions; + + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_path_permissions; + /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 1a16780b5..e7bbf36ec 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -821,6 +821,8 @@ void* guac_rdp_client_thread(void* data) { settings->recording_path, settings->recording_name, settings->create_recording_path, + settings->recording_file_permissions, + settings->recording_path_permissions, !settings->recording_exclude_output, !settings->recording_exclude_mouse, !settings->recording_exclude_touch, diff --git a/src/protocols/rdp/settings.c b/src/protocols/rdp/settings.c index fb2217a64..6b77a3e7f 100644 --- a/src/protocols/rdp/settings.c +++ b/src/protocols/rdp/settings.c @@ -122,6 +122,8 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "recording-exclude-touch", "recording-include-keys", "create-recording-path", + "recording-file-permissions", + "recording-path-permissions", "resize-method", "enable-audio-input", "enable-touch", @@ -564,6 +566,18 @@ enum RDP_ARGS_IDX { */ IDX_CREATE_RECORDING_PATH, + /** + * The permissions that should be given to screen recording file which is written in + * the given path. + */ + IDX_RECORDING_FILE_PERMISSIONS, + + /** + * The permissions that should be given to screen recording path which is written in + * the given path. + */ + IDX_RECORDING_PATH_PERMISSIONS, + /** * The method to use to apply screen size changes requested by the user. * Valid values are blank, "display-update", and "reconnect". @@ -1161,6 +1175,16 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, 0); + /* Parse file permissions flag */ + settings->recording_file_permissions = + guac_user_parse_args_mode(user, GUAC_RDP_CLIENT_ARGS, argv, + IDX_RECORDING_FILE_PERMISSIONS, GUAC_RDP_DEFAULT_RECORDING_FILE_PERMISSIONS); + + /* Parse path permissions flag */ + settings->recording_path_permissions = + guac_user_parse_args_mode(user, GUAC_RDP_CLIENT_ARGS, argv, + IDX_RECORDING_PATH_PERMISSIONS, GUAC_RDP_DEFAULT_RECORDING_PATH_PERMISSIONS); + /* 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 11dbf59bc..a56ce81c3 100644 --- a/src/protocols/rdp/settings.h +++ b/src/protocols/rdp/settings.h @@ -27,6 +27,9 @@ #include #include +#include +#include + /** * The maximum number of bytes in the client hostname claimed during * connection. @@ -68,6 +71,16 @@ */ #define GUAC_RDP_DEFAULT_RECORDING_NAME "recording" +/** + * The permissions to use for the screen recording file, if not specified. + */ +#define GUAC_RDP_DEFAULT_RECORDING_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP) + +/** + * The permissions to use for the screen recording path, if not specified. + */ +#define GUAC_RDP_DEFAULT_RECORDING_PATH_PERMISSIONS (S_IRWXU | S_IRGRP | S_IXGRP) + /** * The number of entries contained within the OrderSupport BYTE array * referenced by the rdpSettings structure. This value is defined by the RDP @@ -525,6 +538,16 @@ typedef struct guac_rdp_settings { */ int create_recording_path; + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_file_permissions; + + /** + * The permissions to apply for the screen recording path. + */ + mode_t recording_path_permissions; + /** * Non-zero if output which is broadcast to each connected client * (graphics, streams, etc.) should NOT be included in the session diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c index 228068b2f..8735b554b 100644 --- a/src/protocols/ssh/settings.c +++ b/src/protocols/ssh/settings.c @@ -63,6 +63,8 @@ const char* GUAC_SSH_CLIENT_ARGS[] = { "recording-exclude-mouse", "recording-include-keys", "create-recording-path", + "recording-file-permissions", + "recording-path-permissions", "read-only", "server-alive-interval", "backspace", @@ -241,6 +243,18 @@ enum SSH_ARGS_IDX { */ IDX_CREATE_RECORDING_PATH, + /** + * The permissions that should be given to screen recording file which is written in + * the given path. + */ + IDX_RECORDING_FILE_PERMISSIONS, + + /** + * The permissions that should be given to screen recording path which is written in + * the given path. + */ + IDX_RECORDING_PATH_PERMISSIONS, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -495,6 +509,16 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); + /* Parse file permissions flag */ + settings->recording_file_permissions = + guac_user_parse_args_mode(user, GUAC_SSH_CLIENT_ARGS, argv, + IDX_RECORDING_FILE_PERMISSIONS, GUAC_SSH_DEFAULT_RECORDING_FILE_PERMISSIONS); + + /* Parse path permissions flag */ + settings->recording_path_permissions = + guac_user_parse_args_mode(user, GUAC_SSH_CLIENT_ARGS, argv, + IDX_RECORDING_PATH_PERMISSIONS, GUAC_SSH_DEFAULT_RECORDING_PATH_PERMISSIONS); + /* 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 e5d207501..7e01df1b2 100644 --- a/src/protocols/ssh/settings.h +++ b/src/protocols/ssh/settings.h @@ -25,6 +25,8 @@ #include #include +#include +#include /** * The port to connect to when initiating any SSH connection, if no other port @@ -42,6 +44,16 @@ */ #define GUAC_SSH_DEFAULT_RECORDING_NAME "recording" +/** + * The permissions to use for the screen recording file, if not specified. + */ +#define GUAC_SSH_DEFAULT_RECORDING_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP) + +/** + * The permissions to use for the screen recording path, if not specified. + */ +#define GUAC_SSH_DEFAULT_RECORDING_PATH_PERMISSIONS (S_IRWXU | S_IRGRP | S_IXGRP) + /** * The default polling timeout for SSH activity in milliseconds. */ @@ -225,6 +237,16 @@ typedef struct guac_ssh_settings { */ bool create_recording_path; + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_file_permissions; + + /** + * The permissions to apply for the screen recording path. + */ + mode_t recording_path_permissions; + /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 171bdaa66..8777d7457 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -261,6 +261,8 @@ void* ssh_client_thread(void* data) { settings->recording_path, settings->recording_name, settings->create_recording_path, + settings->recording_file_permissions, + settings->recording_path_permissions, !settings->recording_exclude_output, !settings->recording_exclude_mouse, 0, /* Touch events not supported */ diff --git a/src/protocols/telnet/settings.c b/src/protocols/telnet/settings.c index 86271c69c..1d674cc4d 100644 --- a/src/protocols/telnet/settings.c +++ b/src/protocols/telnet/settings.c @@ -55,6 +55,8 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = { "recording-exclude-mouse", "recording-include-keys", "create-recording-path", + "recording-file-permissions", + "recording-path-permissions", "read-only", "backspace", "terminal-type", @@ -193,6 +195,18 @@ enum TELNET_ARGS_IDX { */ IDX_CREATE_RECORDING_PATH, + /** + * The permissions that should be given to screen recording file which is written in + * the given path. + */ + IDX_RECORDING_FILE_PERMISSIONS, + + /** + * The permissions that should be given to screen recording path which is written in + * the given path. + */ + IDX_RECORDING_PATH_PERMISSIONS, + /** * "true" if this connection should be read-only (user input should be * dropped), "false" or blank otherwise. @@ -486,6 +500,16 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); + /* Parse file permissions flag */ + settings->recording_file_permissions = + guac_user_parse_args_mode(user, GUAC_TELNET_CLIENT_ARGS, argv, + IDX_RECORDING_FILE_PERMISSIONS, GUAC_TELNET_DEFAULT_RECORDING_FILE_PERMISSIONS); + + /* Parse path permissions flag */ + settings->recording_path_permissions = + guac_user_parse_args_mode(user, GUAC_TELNET_CLIENT_ARGS, argv, + IDX_RECORDING_PATH_PERMISSIONS, GUAC_TELNET_DEFAULT_RECORDING_PATH_PERMISSIONS); + /* 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 02de1cb3c..278fddc09 100644 --- a/src/protocols/telnet/settings.h +++ b/src/protocols/telnet/settings.h @@ -25,6 +25,7 @@ #include #include +#include #include #include /** @@ -49,6 +50,16 @@ */ #define GUAC_TELNET_DEFAULT_RECORDING_NAME "recording" +/** + * The permissions to use for the screen recording file, if not specified. + */ +#define GUAC_TELNET_DEFAULT_RECORDING_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP) + +/** + * The permissions to use for the screen recording path, if not specified. + */ +#define GUAC_TELNET_DEFAULT_RECORDING_PATH_PERMISSIONS (S_IRWXU | S_IRGRP | S_IXGRP) + /** * The regular expression to use when searching for the username/login prompt * if no other regular expression is specified. @@ -213,6 +224,16 @@ typedef struct guac_telnet_settings { */ bool create_recording_path; + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_file_permissions; + + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_path_permissions; + /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output diff --git a/src/protocols/telnet/telnet.c b/src/protocols/telnet/telnet.c index 263d1d193..7d90faa3a 100644 --- a/src/protocols/telnet/telnet.c +++ b/src/protocols/telnet/telnet.c @@ -603,6 +603,8 @@ void* guac_telnet_client_thread(void* data) { settings->recording_path, settings->recording_name, settings->create_recording_path, + settings->recording_file_permissions, + settings->recording_path_permissions, !settings->recording_exclude_output, !settings->recording_exclude_mouse, 0, /* Touch events not supported */ diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c index a7171128e..9277e7096 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -84,6 +84,8 @@ const char* GUAC_VNC_CLIENT_ARGS[] = { "recording-exclude-mouse", "recording-include-keys", "create-recording-path", + "recording-file-permissions", + "recording-path-permissions", "disable-copy", "disable-paste", @@ -331,6 +333,18 @@ enum VNC_ARGS_IDX { */ IDX_CREATE_RECORDING_PATH, + /** + * The permissions that should be given to screen recording file which is written in + * the given path. + */ + IDX_RECORDING_FILE_PERMISSIONS, + + /** + * The permissions that should be given to screen recording path which is written in + * the given path. + */ + IDX_RECORDING_PATH_PERMISSIONS, + /** * Whether outbound clipboard access should be blocked. If set to "true", * it will not be possible to copy data from the remote desktop to the @@ -594,6 +608,16 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, false); + /* Parse path creation flag */ + settings->recording_file_permissions = + guac_user_parse_args_mode(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_RECORDING_FILE_PERMISSIONS, GUAC_VNC_DEFAULT_RECORDING_FILE_PERMISSIONS); + + /* Parse path creation flag */ + settings->recording_path_permissions = + guac_user_parse_args_mode(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_RECORDING_PATH_PERMISSIONS, GUAC_VNC_DEFAULT_RECORDING_PATH_PERMISSIONS); + /* 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 76139bd4b..c8a1bd4fa 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -24,12 +24,24 @@ #include "config.h" #include +#include +#include /** * The filename to use for the screen recording, if not specified. */ #define GUAC_VNC_DEFAULT_RECORDING_NAME "recording" +/** + * The permissions to use for the screen recording file, if not specified. + */ +#define GUAC_VNC_DEFAULT_RECORDING_FILE_PERMISSIONS (S_IRUSR | S_IWUSR | S_IRGRP) + +/** + * The permissions to use for the screen recording path, if not specified. + */ +#define GUAC_VNC_DEFAULT_RECORDING_PATH_PERMISSIONS (S_IRWXU | S_IRGRP | S_IXGRP) + /** * VNC-specific client data. */ @@ -250,6 +262,16 @@ typedef struct guac_vnc_settings { */ bool create_recording_path; + /** + * The permissions to apply for the screen recording file. + */ + mode_t recording_file_permissions; + + /** + * The permissions to apply for the screen recording path. + */ + mode_t recording_path_permissions; + /** * Whether output which is broadcast to each connected client (graphics, * streams, etc.) should NOT be included in the session recording. Output diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 3b94d5e75..66859035f 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -425,6 +425,8 @@ void* guac_vnc_client_thread(void* data) { settings->recording_path, settings->recording_name, settings->create_recording_path, + settings->recording_file_permissions, + settings->recording_path_permissions, !settings->recording_exclude_output, !settings->recording_exclude_mouse, 0, /* Touch events not supported */