GUACAMOLE-303: Merge Allow root directory of SFTP filesystem to be configured.
This commit is contained in:
commit
07db9808a0
@ -33,6 +33,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GUAC_COMMON_SSH_SFTP_MAX_PATH 2048
|
#define GUAC_COMMON_SSH_SFTP_MAX_PATH 2048
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of path components per path.
|
||||||
|
*/
|
||||||
|
#define GUAC_COMMON_SSH_SFTP_MAX_DEPTH 1024
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of an SFTP-driven filesystem object. Unlike guac_object, this
|
* Representation of an SFTP-driven filesystem object. Unlike guac_object, this
|
||||||
* structure is not tied to any particular user.
|
* structure is not tied to any particular user.
|
||||||
@ -54,6 +59,11 @@ typedef struct guac_common_ssh_sftp_filesystem {
|
|||||||
*/
|
*/
|
||||||
LIBSSH2_SFTP* sftp_session;
|
LIBSSH2_SFTP* sftp_session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the directory to expose to the user as a filesystem object.
|
||||||
|
*/
|
||||||
|
char root_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path files will be sent to, if uploaded directly via a "file"
|
* The path files will be sent to, if uploaded directly via a "file"
|
||||||
* instruction.
|
* instruction.
|
||||||
@ -103,15 +113,22 @@ typedef struct guac_common_ssh_sftp_ls_state {
|
|||||||
* The session to use to provide SFTP. This session will automatically be
|
* The session to use to provide SFTP. This session will automatically be
|
||||||
* destroyed when this filesystem is destroyed.
|
* destroyed when this filesystem is destroyed.
|
||||||
*
|
*
|
||||||
|
* @param root_path
|
||||||
|
* The path accessible via SFTP to consider the root path of the filesystem
|
||||||
|
* exposed to the user. Only the contents of this path will be available
|
||||||
|
* via the filesystem object.
|
||||||
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* 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.
|
* to a user, or NULL to automatically generate a name from the provided
|
||||||
|
* root_path.
|
||||||
*
|
*
|
||||||
* @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* name);
|
guac_common_ssh_session* session, const char* root_path,
|
||||||
|
const char* name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the given filesystem object, disconnecting from SFTP and freeing
|
* Destroys the given filesystem object, disconnecting from SFTP and freeing
|
||||||
|
@ -32,6 +32,111 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an arbitrary absolute path, which may contain "..", ".", and
|
||||||
|
* backslashes, creates an equivalent absolute path which does NOT contain
|
||||||
|
* relative path components (".." or "."), backslashes, or empty path
|
||||||
|
* components. With the exception of paths referring to the root directory, the
|
||||||
|
* resulting path is guaranteed to not contain trailing slashes.
|
||||||
|
*
|
||||||
|
* Normalization will fail if the given path is not absolute, is too long, or
|
||||||
|
* contains more than GUAC_COMMON_SSH_SFTP_MAX_DEPTH path components.
|
||||||
|
*
|
||||||
|
* @param fullpath
|
||||||
|
* The buffer to populate with the normalized path. The normalized path
|
||||||
|
* will not contain relative path components like ".." or ".", nor will it
|
||||||
|
* contain backslashes. This buffer MUST be at least
|
||||||
|
* GUAC_COMMON_SSH_SFTP_MAX_PATH bytes in size.
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* The absolute path to normalize.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if normalization succeeded, zero otherwise.
|
||||||
|
*/
|
||||||
|
static int guac_common_ssh_sftp_normalize_path(char* fullpath,
|
||||||
|
const char* path) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int path_depth = 0;
|
||||||
|
char path_component_data[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
||||||
|
const char* path_components[GUAC_COMMON_SSH_SFTP_MAX_DEPTH];
|
||||||
|
|
||||||
|
const char** current_path_component = &(path_components[0]);
|
||||||
|
const char* current_path_component_data = &(path_component_data[0]);
|
||||||
|
|
||||||
|
/* If original path is not absolute, normalization fails */
|
||||||
|
if (path[0] != '\\' && path[0] != '/')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Skip past leading slash */
|
||||||
|
path++;
|
||||||
|
|
||||||
|
/* Copy path into component data for parsing */
|
||||||
|
strncpy(path_component_data, path, sizeof(path_component_data) - 1);
|
||||||
|
|
||||||
|
/* Find path components within path */
|
||||||
|
for (i = 0; i < sizeof(path_component_data); i++) {
|
||||||
|
|
||||||
|
/* If current character is a path separator, parse as component */
|
||||||
|
char c = path_component_data[i];
|
||||||
|
if (c == '/' || c == '\\' || c == '\0') {
|
||||||
|
|
||||||
|
/* Terminate current component */
|
||||||
|
path_component_data[i] = '\0';
|
||||||
|
|
||||||
|
/* If component refers to parent, just move up in depth */
|
||||||
|
if (strcmp(current_path_component_data, "..") == 0) {
|
||||||
|
if (path_depth > 0)
|
||||||
|
path_depth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, if component not current directory, add to list */
|
||||||
|
else if (strcmp(current_path_component_data, ".") != 0
|
||||||
|
&& strcmp(current_path_component_data, "") != 0)
|
||||||
|
path_components[path_depth++] = current_path_component_data;
|
||||||
|
|
||||||
|
/* If end of string, stop */
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Update start of next component */
|
||||||
|
current_path_component_data = &(path_component_data[i+1]);
|
||||||
|
|
||||||
|
} /* end if separator */
|
||||||
|
|
||||||
|
} /* end for each character */
|
||||||
|
|
||||||
|
/* If no components, the path is simply root */
|
||||||
|
if (path_depth == 0) {
|
||||||
|
strcpy(fullpath, "/");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure last component is null-terminated */
|
||||||
|
path_component_data[i] = 0;
|
||||||
|
|
||||||
|
/* Convert components back into path */
|
||||||
|
for (; path_depth > 0; path_depth--) {
|
||||||
|
|
||||||
|
const char* filename = *(current_path_component++);
|
||||||
|
|
||||||
|
/* Add separator */
|
||||||
|
*(fullpath++) = '/';
|
||||||
|
|
||||||
|
/* Copy string */
|
||||||
|
while (*filename != 0)
|
||||||
|
*(fullpath++) = *(filename++);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminate absolute path */
|
||||||
|
*(fullpath++) = 0;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates the last error message received by the SFTP layer of an SSH
|
* Translates the last error message received by the SFTP layer of an SSH
|
||||||
* session into a Guacamole protocol status code.
|
* session into a Guacamole protocol status code.
|
||||||
@ -183,6 +288,73 @@ static int guac_ssh_append_filename(char* fullpath, const char* path,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates the given paths, separating the two with a single forward
|
||||||
|
* slash. The full result must be no more than GUAC_COMMON_SSH_SFTP_MAX_PATH
|
||||||
|
* bytes long, counting null terminator.
|
||||||
|
*
|
||||||
|
* @param fullpath
|
||||||
|
* The buffer to store the result within. This buffer must be at least
|
||||||
|
* GUAC_COMMON_SSH_SFTP_MAX_PATH bytes long.
|
||||||
|
*
|
||||||
|
* @param path_a
|
||||||
|
* The path to place at the beginning of the resulting path.
|
||||||
|
*
|
||||||
|
* @param path_b
|
||||||
|
* The path to append after path_a within the resulting path.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if the paths were successfully concatenated together, zero
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
static int guac_ssh_append_path(char* fullpath, const char* path_a,
|
||||||
|
const char* path_b) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Copy path, appending a trailing slash */
|
||||||
|
for (i = 0; i < GUAC_COMMON_SSH_SFTP_MAX_PATH; i++) {
|
||||||
|
|
||||||
|
char c = path_a[i];
|
||||||
|
if (c == '\0') {
|
||||||
|
if (i > 0 && path_a[i-1] != '/')
|
||||||
|
fullpath[i++] = '/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy character if not end of string */
|
||||||
|
fullpath[i] = c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip past leading slashes in second path */
|
||||||
|
while (*path_b == '/')
|
||||||
|
path_b++;
|
||||||
|
|
||||||
|
/* Append path */
|
||||||
|
for (; i < GUAC_COMMON_SSH_SFTP_MAX_PATH; i++) {
|
||||||
|
|
||||||
|
char c = *(path_b++);
|
||||||
|
if (c == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Append each character within path */
|
||||||
|
fullpath[i] = c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify path length is within maximum */
|
||||||
|
if (i == GUAC_COMMON_SSH_SFTP_MAX_PATH)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Terminate path string */
|
||||||
|
fullpath[i] = '\0';
|
||||||
|
|
||||||
|
/* Append was successful */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for blob messages which continue an inbound SFTP data transfer
|
* Handler for blob messages which continue an inbound SFTP data transfer
|
||||||
* (upload). The data associated with the given stream is expected to be a
|
* (upload). The data associated with the given stream is expected to be a
|
||||||
@ -567,6 +739,38 @@ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates a stream name for the given SFTP filesystem object into the
|
||||||
|
* absolute path corresponding to the actual file it represents.
|
||||||
|
*
|
||||||
|
* @param fullpath
|
||||||
|
* The buffer to populate with the translated path. This buffer MUST be at
|
||||||
|
* least GUAC_COMMON_SSH_SFTP_MAX_PATH bytes in size.
|
||||||
|
*
|
||||||
|
* @param object
|
||||||
|
* The Guacamole protocol object associated with the SFTP filesystem.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* The name of the stream (file) to translate into an absolute path.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Non-zero if translation succeeded, zero otherwise.
|
||||||
|
*/
|
||||||
|
static int guac_common_ssh_sftp_translate_name(char* fullpath,
|
||||||
|
guac_object* object, char* name) {
|
||||||
|
|
||||||
|
char normalized_name[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
||||||
|
|
||||||
|
guac_common_ssh_sftp_filesystem* filesystem =
|
||||||
|
(guac_common_ssh_sftp_filesystem*) object->data;
|
||||||
|
|
||||||
|
/* Normalize stream name into a path, and append to the root path */
|
||||||
|
return guac_common_ssh_sftp_normalize_path(normalized_name, name)
|
||||||
|
&& guac_ssh_append_path(fullpath, filesystem->root_path,
|
||||||
|
normalized_name);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for get messages. In context of SFTP and the filesystem exposed via
|
* Handler for get messages. In context of SFTP and the filesystem exposed via
|
||||||
* the Guacamole protocol, get messages request the body of a file within the
|
* the Guacamole protocol, get messages request the body of a file within the
|
||||||
@ -587,16 +791,25 @@ static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
|
|||||||
static int guac_common_ssh_sftp_get_handler(guac_user* user,
|
static int guac_common_ssh_sftp_get_handler(guac_user* user,
|
||||||
guac_object* object, char* name) {
|
guac_object* object, char* name) {
|
||||||
|
|
||||||
|
char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
||||||
|
|
||||||
guac_common_ssh_sftp_filesystem* filesystem =
|
guac_common_ssh_sftp_filesystem* filesystem =
|
||||||
(guac_common_ssh_sftp_filesystem*) object->data;
|
(guac_common_ssh_sftp_filesystem*) object->data;
|
||||||
|
|
||||||
LIBSSH2_SFTP* sftp = filesystem->sftp_session;
|
LIBSSH2_SFTP* sftp = filesystem->sftp_session;
|
||||||
LIBSSH2_SFTP_ATTRIBUTES attributes;
|
LIBSSH2_SFTP_ATTRIBUTES attributes;
|
||||||
|
|
||||||
|
/* Translate stream name into filesystem path */
|
||||||
|
if (!guac_common_ssh_sftp_translate_name(fullpath, object, name)) {
|
||||||
|
guac_user_log(user, GUAC_LOG_INFO, "Unable to generate real path "
|
||||||
|
"for stream \"%s\"", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt to read file information */
|
/* Attempt to read file information */
|
||||||
if (libssh2_sftp_stat(sftp, name, &attributes)) {
|
if (libssh2_sftp_stat(sftp, fullpath, &attributes)) {
|
||||||
guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
|
guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
|
||||||
name);
|
fullpath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,10 +817,10 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
|
|||||||
if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) {
|
if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) {
|
||||||
|
|
||||||
/* Open as directory */
|
/* Open as directory */
|
||||||
LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, name);
|
LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, fullpath);
|
||||||
if (dir == NULL) {
|
if (dir == NULL) {
|
||||||
guac_user_log(user, GUAC_LOG_INFO,
|
guac_user_log(user, GUAC_LOG_INFO,
|
||||||
"Unable to read directory \"%s\"", name);
|
"Unable to read directory \"%s\"", fullpath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,11 +851,11 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
/* Open as normal file */
|
/* Open as normal file */
|
||||||
LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, name,
|
LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath,
|
||||||
LIBSSH2_FXF_READ, 0);
|
LIBSSH2_FXF_READ, 0);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
guac_user_log(user, GUAC_LOG_INFO,
|
guac_user_log(user, GUAC_LOG_INFO,
|
||||||
"Unable to read file \"%s\"", name);
|
"Unable to read file \"%s\"", fullpath);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,19 +901,28 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
|
|||||||
static int guac_common_ssh_sftp_put_handler(guac_user* user,
|
static int guac_common_ssh_sftp_put_handler(guac_user* user,
|
||||||
guac_object* object, guac_stream* stream, char* mimetype, char* name) {
|
guac_object* object, guac_stream* stream, char* mimetype, char* name) {
|
||||||
|
|
||||||
|
char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH];
|
||||||
|
|
||||||
guac_common_ssh_sftp_filesystem* filesystem =
|
guac_common_ssh_sftp_filesystem* filesystem =
|
||||||
(guac_common_ssh_sftp_filesystem*) object->data;
|
(guac_common_ssh_sftp_filesystem*) object->data;
|
||||||
|
|
||||||
LIBSSH2_SFTP* sftp = filesystem->sftp_session;
|
LIBSSH2_SFTP* sftp = filesystem->sftp_session;
|
||||||
|
|
||||||
|
/* Translate stream name into filesystem path */
|
||||||
|
if (!guac_common_ssh_sftp_translate_name(fullpath, object, name)) {
|
||||||
|
guac_user_log(user, GUAC_LOG_INFO, "Unable to generate real path "
|
||||||
|
"for stream \"%s\"", name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open file via SFTP */
|
/* Open file via SFTP */
|
||||||
LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, name,
|
LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, fullpath,
|
||||||
LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
|
LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
|
||||||
S_IRUSR | S_IWUSR);
|
S_IRUSR | S_IWUSR);
|
||||||
|
|
||||||
/* Acknowledge stream if successful */
|
/* Acknowledge stream if successful */
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
guac_user_log(user, GUAC_LOG_DEBUG, "File \"%s\" opened", name);
|
guac_user_log(user, GUAC_LOG_DEBUG, "File \"%s\" opened", fullpath);
|
||||||
guac_protocol_send_ack(user->socket, stream, "SFTP: File opened",
|
guac_protocol_send_ack(user->socket, stream, "SFTP: File opened",
|
||||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
@ -708,7 +930,7 @@ static int guac_common_ssh_sftp_put_handler(guac_user* user,
|
|||||||
/* Abort on failure */
|
/* Abort on failure */
|
||||||
else {
|
else {
|
||||||
guac_user_log(user, GUAC_LOG_INFO,
|
guac_user_log(user, GUAC_LOG_INFO,
|
||||||
"Unable to open file \"%s\"", name);
|
"Unable to open file \"%s\"", fullpath);
|
||||||
guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed",
|
guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed",
|
||||||
guac_sftp_get_status(filesystem));
|
guac_sftp_get_status(filesystem));
|
||||||
}
|
}
|
||||||
@ -756,7 +978,8 @@ 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* name) {
|
guac_common_ssh_session* session, const char* root_path,
|
||||||
|
const char* name) {
|
||||||
|
|
||||||
/* Request SFTP */
|
/* Request SFTP */
|
||||||
LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session);
|
LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session);
|
||||||
@ -768,10 +991,24 @@ guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem(
|
|||||||
malloc(sizeof(guac_common_ssh_sftp_filesystem));
|
malloc(sizeof(guac_common_ssh_sftp_filesystem));
|
||||||
|
|
||||||
/* Associate SSH session with SFTP data and user */
|
/* Associate SSH session with SFTP data and user */
|
||||||
filesystem->name = strdup(name);
|
|
||||||
filesystem->ssh_session = session;
|
filesystem->ssh_session = session;
|
||||||
filesystem->sftp_session = sftp_session;
|
filesystem->sftp_session = sftp_session;
|
||||||
|
|
||||||
|
/* Normalize and store the provided root path */
|
||||||
|
if (!guac_common_ssh_sftp_normalize_path(filesystem->root_path,
|
||||||
|
root_path)) {
|
||||||
|
guac_client_log(session->client, GUAC_LOG_WARNING, "Cannot create "
|
||||||
|
"SFTP filesystem - \"%s\" is not a valid path.", root_path);
|
||||||
|
free(filesystem);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate filesystem name from root path if no name is provided */
|
||||||
|
if (name != NULL)
|
||||||
|
filesystem->name = strdup(name);
|
||||||
|
else
|
||||||
|
filesystem->name = strdup(filesystem->root_path);
|
||||||
|
|
||||||
/* Initially upload files to current directory */
|
/* Initially upload files to current directory */
|
||||||
strcpy(filesystem->upload_path, ".");
|
strcpy(filesystem->upload_path, ".");
|
||||||
|
|
||||||
|
@ -987,8 +987,8 @@ 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(
|
guac_common_ssh_create_sftp_filesystem(rdp_client->sftp_session,
|
||||||
rdp_client->sftp_session, "/");
|
settings->sftp_root_directory, NULL);
|
||||||
|
|
||||||
/* Expose filesystem to connection owner */
|
/* Expose filesystem to connection owner */
|
||||||
guac_client_for_owner(client,
|
guac_client_for_owner(client,
|
||||||
|
@ -84,6 +84,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
|
|||||||
"sftp-private-key",
|
"sftp-private-key",
|
||||||
"sftp-passphrase",
|
"sftp-passphrase",
|
||||||
"sftp-directory",
|
"sftp-directory",
|
||||||
|
"sftp-root-directory",
|
||||||
"sftp-server-alive-interval",
|
"sftp-server-alive-interval",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -367,6 +368,12 @@ enum RDP_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_SFTP_DIRECTORY,
|
IDX_SFTP_DIRECTORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object. If omitted, "/" will be used by default.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interval at which SSH keepalive messages are sent to the server for
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
@ -784,6 +791,11 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user,
|
|||||||
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
|
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
|
||||||
IDX_SFTP_DIRECTORY, NULL);
|
IDX_SFTP_DIRECTORY, NULL);
|
||||||
|
|
||||||
|
/* SFTP root directory */
|
||||||
|
settings->sftp_root_directory =
|
||||||
|
guac_user_parse_args_string(user, GUAC_RDP_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY, "/");
|
||||||
|
|
||||||
/* Default keepalive value */
|
/* Default keepalive value */
|
||||||
settings->sftp_server_alive_interval =
|
settings->sftp_server_alive_interval =
|
||||||
guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv,
|
guac_user_parse_args_int(user, GUAC_RDP_CLIENT_ARGS, argv,
|
||||||
@ -909,6 +921,7 @@ void guac_rdp_settings_free(guac_rdp_settings* settings) {
|
|||||||
#ifdef ENABLE_COMMON_SSH
|
#ifdef ENABLE_COMMON_SSH
|
||||||
/* Free SFTP settings */
|
/* Free SFTP settings */
|
||||||
free(settings->sftp_directory);
|
free(settings->sftp_directory);
|
||||||
|
free(settings->sftp_root_directory);
|
||||||
free(settings->sftp_hostname);
|
free(settings->sftp_hostname);
|
||||||
free(settings->sftp_passphrase);
|
free(settings->sftp_passphrase);
|
||||||
free(settings->sftp_password);
|
free(settings->sftp_password);
|
||||||
|
@ -360,6 +360,12 @@ typedef struct guac_rdp_settings {
|
|||||||
*/
|
*/
|
||||||
char* sftp_directory;
|
char* sftp_directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object.
|
||||||
|
*/
|
||||||
|
char* sftp_root_directory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interval at which SSH keepalive messages are sent to the server for
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
|
@ -37,6 +37,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
|
|||||||
"font-name",
|
"font-name",
|
||||||
"font-size",
|
"font-size",
|
||||||
"enable-sftp",
|
"enable-sftp",
|
||||||
|
"sftp-root-directory",
|
||||||
"private-key",
|
"private-key",
|
||||||
"passphrase",
|
"passphrase",
|
||||||
#ifdef ENABLE_SSH_AGENT
|
#ifdef ENABLE_SSH_AGENT
|
||||||
@ -92,6 +93,12 @@ enum SSH_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_ENABLE_SFTP,
|
IDX_ENABLE_SFTP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object. If omitted, "/" will be used by default.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The private key to use for authentication, if any.
|
* The private key to use for authentication, if any.
|
||||||
*/
|
*/
|
||||||
@ -236,6 +243,11 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
|
|||||||
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
|
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
IDX_ENABLE_SFTP, false);
|
IDX_ENABLE_SFTP, false);
|
||||||
|
|
||||||
|
/* SFTP root directory */
|
||||||
|
settings->sftp_root_directory =
|
||||||
|
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY, "/");
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_AGENT
|
#ifdef ENABLE_SSH_AGENT
|
||||||
settings->enable_agent =
|
settings->enable_agent =
|
||||||
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
|
guac_user_parse_args_boolean(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
@ -316,6 +328,9 @@ void guac_ssh_settings_free(guac_ssh_settings* settings) {
|
|||||||
/* Free requested command */
|
/* Free requested command */
|
||||||
free(settings->command);
|
free(settings->command);
|
||||||
|
|
||||||
|
/* Free SFTP settings */
|
||||||
|
free(settings->sftp_root_directory);
|
||||||
|
|
||||||
/* Free typescript settings */
|
/* Free typescript settings */
|
||||||
free(settings->typescript_name);
|
free(settings->typescript_name);
|
||||||
free(settings->typescript_path);
|
free(settings->typescript_path);
|
||||||
|
@ -145,6 +145,12 @@ typedef struct guac_ssh_settings {
|
|||||||
*/
|
*/
|
||||||
bool enable_sftp;
|
bool enable_sftp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object.
|
||||||
|
*/
|
||||||
|
char* sftp_root_directory;
|
||||||
|
|
||||||
#ifdef ENABLE_SSH_AGENT
|
#ifdef ENABLE_SSH_AGENT
|
||||||
/**
|
/**
|
||||||
* Whether the SSH agent is enabled.
|
* Whether the SSH agent is enabled.
|
||||||
|
@ -266,7 +266,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, "/");
|
ssh_client->sftp_session, settings->sftp_root_directory,
|
||||||
|
NULL);
|
||||||
|
|
||||||
/* Expose filesystem to connection owner */
|
/* Expose filesystem to connection owner */
|
||||||
guac_client_for_owner(client,
|
guac_client_for_owner(client,
|
||||||
|
@ -66,6 +66,7 @@ const char* GUAC_VNC_CLIENT_ARGS[] = {
|
|||||||
"sftp-private-key",
|
"sftp-private-key",
|
||||||
"sftp-passphrase",
|
"sftp-passphrase",
|
||||||
"sftp-directory",
|
"sftp-directory",
|
||||||
|
"sftp-root-directory",
|
||||||
"sftp-server-alive-interval",
|
"sftp-server-alive-interval",
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -229,6 +230,12 @@ enum VNC_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_SFTP_DIRECTORY,
|
IDX_SFTP_DIRECTORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object. If omitted, "/" will be used by default.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interval at which SSH keepalive messages are sent to the server for
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
@ -405,6 +412,11 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user,
|
|||||||
guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv,
|
guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv,
|
||||||
IDX_SFTP_DIRECTORY, NULL);
|
IDX_SFTP_DIRECTORY, NULL);
|
||||||
|
|
||||||
|
/* SFTP root directory */
|
||||||
|
settings->sftp_root_directory =
|
||||||
|
guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY, "/");
|
||||||
|
|
||||||
/* Default keepalive value */
|
/* Default keepalive value */
|
||||||
settings->sftp_server_alive_interval =
|
settings->sftp_server_alive_interval =
|
||||||
guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv,
|
guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv,
|
||||||
@ -447,6 +459,7 @@ void guac_vnc_settings_free(guac_vnc_settings* settings) {
|
|||||||
#ifdef ENABLE_COMMON_SSH
|
#ifdef ENABLE_COMMON_SSH
|
||||||
/* Free SFTP settings */
|
/* Free SFTP settings */
|
||||||
free(settings->sftp_directory);
|
free(settings->sftp_directory);
|
||||||
|
free(settings->sftp_root_directory);
|
||||||
free(settings->sftp_hostname);
|
free(settings->sftp_hostname);
|
||||||
free(settings->sftp_passphrase);
|
free(settings->sftp_passphrase);
|
||||||
free(settings->sftp_password);
|
free(settings->sftp_password);
|
||||||
|
@ -174,6 +174,12 @@ typedef struct guac_vnc_settings {
|
|||||||
*/
|
*/
|
||||||
char* sftp_directory;
|
char* sftp_directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object.
|
||||||
|
*/
|
||||||
|
char* sftp_root_directory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interval at which SSH keepalive messages are sent to the server for
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
|
@ -271,8 +271,8 @@ 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(
|
guac_common_ssh_create_sftp_filesystem(vnc_client->sftp_session,
|
||||||
vnc_client->sftp_session, "/");
|
settings->sftp_root_directory, NULL);
|
||||||
|
|
||||||
/* Expose filesystem to connection owner */
|
/* Expose filesystem to connection owner */
|
||||||
guac_client_for_owner(client,
|
guac_client_for_owner(client,
|
||||||
|
Loading…
Reference in New Issue
Block a user