GUACAMOLE-474: Implement logic to disable file transfers in each protocol.

This commit is contained in:
Nick Couchman 2019-12-26 11:25:58 -05:00
parent 42e382062c
commit 1a699686b9
13 changed files with 92 additions and 25 deletions

View File

@ -69,6 +69,16 @@ typedef struct guac_common_ssh_sftp_filesystem {
* instruction. * instruction.
*/ */
char upload_path[GUAC_COMMON_SSH_SFTP_MAX_PATH]; char upload_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
/**
* If downloads from SFTP to the local browser should be disabled.
*/
int disable_download;
/**
* If uploads from the local browser to SFTP should be disabled.
*/
int disable_upload;
} guac_common_ssh_sftp_filesystem; } guac_common_ssh_sftp_filesystem;
@ -122,13 +132,20 @@ typedef struct guac_common_ssh_sftp_ls_state {
* The name to send as the name of the filesystem whenever it is exposed * The name to send as the name of the filesystem whenever it is exposed
* to a user, or NULL to automatically generate a name from the provided * to a user, or NULL to automatically generate a name from the provided
* root_path. * root_path.
*
* @param disable_download
* Whether downloads from the SFTP share to the local browser should be
* disabled.
*
* @param disable_upload
* Whether uploads from the local browser to SFTP should be disabled.
* *
* @return * @return
* A new SFTP filesystem object, not yet exposed to users. * A new SFTP filesystem object, not yet exposed to users.
*/ */
guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem( guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem(
guac_common_ssh_session* session, const char* root_path, guac_common_ssh_session* session, const char* root_path,
const char* name); const char* name, int disable_download, int disable_upload);
/** /**
* Destroys the given filesystem object, disconnecting from SFTP and freeing * Destroys the given filesystem object, disconnecting from SFTP and freeing

View File

@ -429,7 +429,7 @@ int guac_common_ssh_sftp_handle_file_stream(
/** /**
* Handler for ack messages which continue an outbound SFTP data transfer * Handler for ack messages which continue an outbound SFTP data transfer
* (download), signalling the current status and requesting additional data. * (download), signaling the current status and requesting additional data.
* The data associated with the given stream is expected to be a pointer to an * The data associated with the given stream is expected to be a pointer to an
* open LIBSSH2_SFTP_HANDLE for the file from which the data is to be read. * open LIBSSH2_SFTP_HANDLE for the file from which the data is to be read.
* *
@ -787,6 +787,13 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
/* Otherwise, send file contents */ /* Otherwise, send file contents */
else { else {
/* If downloads are disabled, log and return. */
if (filesystem->disable_download) {
guac_user_log(user, GUAC_LOG_INFO,
"File downloads have been disabled.");
return 0;
}
/* Open as normal file */ /* Open as normal file */
LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath, LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath,
LIBSSH2_FXF_READ, 0); LIBSSH2_FXF_READ, 0);
@ -903,7 +910,11 @@ guac_object* guac_common_ssh_alloc_sftp_filesystem_object(
/* Init filesystem */ /* Init filesystem */
guac_object* fs_object = guac_user_alloc_object(user); guac_object* fs_object = guac_user_alloc_object(user);
fs_object->get_handler = guac_common_ssh_sftp_get_handler; fs_object->get_handler = guac_common_ssh_sftp_get_handler;
fs_object->put_handler = guac_common_ssh_sftp_put_handler;
/* Only handle uploads if not disabled. */
if (!filesystem->disable_upload)
fs_object->put_handler = guac_common_ssh_sftp_put_handler;
fs_object->data = filesystem; fs_object->data = filesystem;
/* Send filesystem to user */ /* Send filesystem to user */
@ -916,7 +927,7 @@ guac_object* guac_common_ssh_alloc_sftp_filesystem_object(
guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem( guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem(
guac_common_ssh_session* session, const char* root_path, guac_common_ssh_session* session, const char* root_path,
const char* name) { const char* name, int disable_download, int disable_upload) {
/* Request SFTP */ /* Request SFTP */
LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session); LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session);
@ -930,6 +941,10 @@ guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem(
/* Associate SSH session with SFTP data and user */ /* Associate SSH session with SFTP data and user */
filesystem->ssh_session = session; filesystem->ssh_session = session;
filesystem->sftp_session = sftp_session; filesystem->sftp_session = sftp_session;
/* Copy over disable flags */
filesystem->disable_download = disable_download;
filesystem->disable_upload = disable_upload;
/* Normalize and store the provided root path */ /* Normalize and store the provided root path */
if (!guac_common_ssh_sftp_normalize_path(filesystem->root_path, if (!guac_common_ssh_sftp_normalize_path(filesystem->root_path,

View File

@ -221,8 +221,9 @@ void guac_rdpdr_fs_process_close(guac_rdp_common_svc* svc,
return; return;
/* If file was written to, and it's in the \Download folder, start stream */ /* If file was written to, and it's in the \Download folder, start stream */
if (file->bytes_written > 0 && if (file->bytes_written > 0
strncmp(file->absolute_path, "\\Download\\", 10) == 0) { && strncmp(file->absolute_path, "\\Download\\", 10) == 0
&& !((guac_rdp_fs*) device->data)->disable_download) {
guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path); guac_client_for_owner(svc->client, guac_rdp_download_to_user, file->absolute_path);
guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id); guac_rdp_fs_delete((guac_rdp_fs*) device->data, iorequest->file_id);
} }

View File

@ -43,7 +43,7 @@
#include <unistd.h> #include <unistd.h>
guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path,
int create_drive_path) { int create_drive_path, int disable_download, int disable_upload) {
/* Create drive path if it does not exist */ /* Create drive path if it does not exist */
if (create_drive_path) { if (create_drive_path) {
@ -65,6 +65,8 @@ guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path,
fs->drive_path = strdup(drive_path); fs->drive_path = strdup(drive_path);
fs->file_id_pool = guac_pool_alloc(0); fs->file_id_pool = guac_pool_alloc(0);
fs->open_files = 0; fs->open_files = 0;
fs->disable_download = disable_download;
fs->disable_upload = disable_upload;
return fs; return fs;
@ -77,11 +79,15 @@ void guac_rdp_fs_free(guac_rdp_fs* fs) {
} }
guac_object* guac_rdp_fs_alloc_object(guac_rdp_fs* fs, guac_user* user) { guac_object* guac_rdp_fs_alloc_object(guac_rdp_fs* fs, guac_user* user) {
/* Init filesystem */ /* Init filesystem */
guac_object* fs_object = guac_user_alloc_object(user); guac_object* fs_object = guac_user_alloc_object(user);
fs_object->get_handler = guac_rdp_download_get_handler; fs_object->get_handler = guac_rdp_download_get_handler;
fs_object->put_handler = guac_rdp_upload_put_handler;
/* Assign handler only if uploads are not disabled. */
if(!fs->disable_upload)
fs_object->put_handler = guac_rdp_upload_put_handler;
fs_object->data = fs; fs_object->data = fs;
/* Send filesystem to user */ /* Send filesystem to user */

View File

@ -219,6 +219,16 @@ typedef struct guac_rdp_fs {
* All available file structures. * All available file structures.
*/ */
guac_rdp_fs_file files[GUAC_RDP_FS_MAX_FILES]; guac_rdp_fs_file files[GUAC_RDP_FS_MAX_FILES];
/**
* If downloads from the remote server to the browser should be disabled.
*/
int disable_download;
/**
* If uploads from the browser to the remote server should be disabled.
*/
int disable_upload;
} guac_rdp_fs; } guac_rdp_fs;
@ -258,12 +268,20 @@ typedef struct guac_rdp_fs_info {
* @param create_drive_path * @param create_drive_path
* Non-zero if the drive path specified should be automatically created if * Non-zero if the drive path specified should be automatically created if
* it does not yet exist, zero otherwise. * it does not yet exist, zero otherwise.
*
* @param disable_download
* Non-zero if downloads from the remote server to the local browser should
* be disabled.
*
* @param disable_upload
* Non-zero if uploads from the browser to the remote server should be
* disabled.
* *
* @return * @return
* The newly-allocated filesystem. * The newly-allocated filesystem.
*/ */
guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path, guac_rdp_fs* guac_rdp_fs_alloc(guac_client* client, const char* drive_path,
int create_drive_path); int create_drive_path, int disable_download, int disable_upload);
/** /**
* Frees the given filesystem. * Frees the given filesystem.

View File

@ -548,7 +548,8 @@ void* guac_rdp_client_thread(void* data) {
/* Allocate actual emulated filesystem */ /* Allocate actual emulated filesystem */
rdp_client->filesystem = rdp_client->filesystem =
guac_rdp_fs_alloc(client, settings->drive_path, guac_rdp_fs_alloc(client, settings->drive_path,
settings->create_drive_path); settings->create_drive_path, settings->disable_download,
settings->disable_upload);
/* Expose filesystem to owner */ /* Expose filesystem to owner */
guac_client_for_owner(client, guac_rdp_fs_expose, guac_client_for_owner(client, guac_rdp_fs_expose,
@ -617,7 +618,9 @@ void* guac_rdp_client_thread(void* data) {
/* Load and expose filesystem */ /* Load and expose filesystem */
rdp_client->sftp_filesystem = rdp_client->sftp_filesystem =
guac_common_ssh_create_sftp_filesystem(rdp_client->sftp_session, guac_common_ssh_create_sftp_filesystem(rdp_client->sftp_session,
settings->sftp_root_directory, NULL); settings->sftp_root_directory, NULL,
settings->sftp_disable_download,
settings->sftp_disable_upload);
/* Expose filesystem to connection owner */ /* Expose filesystem to connection owner */
guac_client_for_owner(client, guac_client_for_owner(client,

View File

@ -131,16 +131,17 @@ int guac_rdp_user_file_handler(guac_user* user, guac_stream* stream,
#ifdef ENABLE_COMMON_SSH #ifdef ENABLE_COMMON_SSH
guac_rdp_settings* settings = rdp_client->settings; guac_rdp_settings* settings = rdp_client->settings;
/* If SFTP is enabled, it should be used for default uploads only if RDPDR /* If SFTP is enabled and SFTP uploads have not been disabled, it should be
* is not enabled or its upload directory has been set */ * used for default uploads only if RDPDR is not enabled or its upload
if (rdp_client->sftp_filesystem != NULL) { * directory has been set */
if (rdp_client->sftp_filesystem != NULL && !settings->sftp_disable_upload) {
if (!settings->drive_enabled || settings->sftp_directory != NULL) if (!settings->drive_enabled || settings->sftp_directory != NULL)
return guac_rdp_sftp_file_handler(user, stream, mimetype, filename); return guac_rdp_sftp_file_handler(user, stream, mimetype, filename);
} }
#endif #endif
/* Default to using RDPDR uploads (if enabled) */ /* Default to using RDPDR uploads (if enabled) */
if (rdp_client->filesystem != NULL) if (rdp_client->filesystem != NULL && !settings->disable_upload)
return guac_rdp_upload_file_handler(user, stream, mimetype, filename); return guac_rdp_upload_file_handler(user, stream, mimetype, filename);
/* File transfer not enabled */ /* File transfer not enabled */

View File

@ -368,7 +368,7 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
/* Disable file downloads. */ /* Disable file downloads. */
settings->sftp_disable_download = settings->sftp_disable_download =
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv, guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
IDX_SFTP_DISABLE_DOWNLAOD, false); IDX_SFTP_DISABLE_DOWNLOAD, false);
/* Disable file uploads. */ /* Disable file uploads. */
settings->sftp_disable_upload = settings->sftp_disable_upload =

View File

@ -185,14 +185,14 @@ typedef struct guac_ssh_settings {
* downloads will not be allowed over SFTP. If not set or set to false, file * downloads will not be allowed over SFTP. If not set or set to false, file
* downloads will be allowed. * downloads will be allowed.
*/ */
bool disable_download; bool sftp_disable_download;
/** /**
* Whether file uploads over SFTP should be disabled. If set to true, file * Whether file uploads over SFTP should be disabled. If set to true, file
* uploads will not be allowed over SFTP. If not set or set to false, file * uploads will not be allowed over SFTP. If not set or set to false, file
* uploads will be allowed. * uploads will be allowed.
*/ */
bool disable_upload; bool sftp_disable_upload;
#ifdef ENABLE_SSH_AGENT #ifdef ENABLE_SSH_AGENT
/** /**

View File

@ -320,7 +320,8 @@ void* ssh_client_thread(void* data) {
/* Request SFTP */ /* Request SFTP */
ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem( ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(
ssh_client->sftp_session, settings->sftp_root_directory, ssh_client->sftp_session, settings->sftp_root_directory,
NULL); NULL, settings->sftp_disable_download,
settings->sftp_disable_upload);
/* Expose filesystem to connection owner */ /* Expose filesystem to connection owner */
guac_client_for_owner(client, guac_client_for_owner(client,
@ -328,8 +329,11 @@ void* ssh_client_thread(void* data) {
ssh_client->sftp_filesystem); ssh_client->sftp_filesystem);
/* Init handlers for Guacamole-specific console codes */ /* Init handlers for Guacamole-specific console codes */
ssh_client->term->upload_path_handler = guac_sftp_set_upload_path; if (!settings->sftp_disable_upload)
ssh_client->term->file_download_handler = guac_sftp_download_file; ssh_client->term->upload_path_handler = guac_sftp_set_upload_path;
if (!settings->sftp_disable_download)
ssh_client->term->file_download_handler = guac_sftp_download_file;
guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized"); guac_client_log(client, GUAC_LOG_DEBUG, "SFTP session initialized");

View File

@ -99,7 +99,7 @@ int guac_ssh_user_join_handler(guac_user* user, int argc, char** argv) {
user->size_handler = guac_ssh_user_size_handler; user->size_handler = guac_ssh_user_size_handler;
/* Set generic (non-filesystem) file upload handler */ /* Set generic (non-filesystem) file upload handler */
if (settings->enable_sftp) if (settings->enable_sftp && !settings->sftp_disable_upload)
user->file_handler = guac_sftp_file_handler; user->file_handler = guac_sftp_file_handler;
} }

View File

@ -101,7 +101,7 @@ int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) {
#ifdef ENABLE_COMMON_SSH #ifdef ENABLE_COMMON_SSH
/* Set generic (non-filesystem) file upload handler */ /* Set generic (non-filesystem) file upload handler */
if (settings->enable_sftp) if (settings->enable_sftp && !settings->sftp_disable_upload)
user->file_handler = guac_vnc_sftp_file_handler; user->file_handler = guac_vnc_sftp_file_handler;
#endif #endif

View File

@ -342,7 +342,9 @@ void* guac_vnc_client_thread(void* data) {
/* Load filesystem */ /* Load filesystem */
vnc_client->sftp_filesystem = vnc_client->sftp_filesystem =
guac_common_ssh_create_sftp_filesystem(vnc_client->sftp_session, guac_common_ssh_create_sftp_filesystem(vnc_client->sftp_session,
settings->sftp_root_directory, NULL); settings->sftp_root_directory, NULL,
settings->sftp_disable_download,
settings->sftp_disable_upload);
/* Expose filesystem to connection owner */ /* Expose filesystem to connection owner */
guac_client_for_owner(client, guac_client_for_owner(client,