You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@guacamole.apache.org by vn...@apache.org on 2017/07/03 21:52:09 UTC

[1/3] incubator-guacamole-server git commit: GUACAMOLE-303: Extend common SFTP filesystem such that arbitrary directories can be used as the root of the filesystem.

Repository: incubator-guacamole-server
Updated Branches:
  refs/heads/master 836fc3eaa -> 07db9808a


GUACAMOLE-303: Extend common SFTP filesystem such that arbitrary directories can be used as the root of the filesystem.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/0474f86c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/0474f86c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/0474f86c

Branch: refs/heads/master
Commit: 0474f86c46309ddae785359c92374820cc768525
Parents: 836fc3e
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Jun 29 15:28:21 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Jun 29 15:36:10 2017 -0700

----------------------------------------------------------------------
 src/common-ssh/common-ssh/sftp.h |  21 ++-
 src/common-ssh/sftp.c            | 259 ++++++++++++++++++++++++++++++++--
 src/protocols/rdp/rdp.c          |   2 +-
 src/protocols/ssh/ssh.c          |   2 +-
 src/protocols/vnc/vnc.c          |   2 +-
 5 files changed, 270 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/0474f86c/src/common-ssh/common-ssh/sftp.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/common-ssh/sftp.h b/src/common-ssh/common-ssh/sftp.h
index 038a577..0ec2d12 100644
--- a/src/common-ssh/common-ssh/sftp.h
+++ b/src/common-ssh/common-ssh/sftp.h
@@ -34,6 +34,11 @@
 #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
  * structure is not tied to any particular user.
  */
@@ -55,6 +60,11 @@ typedef struct guac_common_ssh_sftp_filesystem {
     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"
      * 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
  *     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
  *     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
  *     A new SFTP filesystem object, not yet exposed to users.
  */
 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

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/0474f86c/src/common-ssh/sftp.c
----------------------------------------------------------------------
diff --git a/src/common-ssh/sftp.c b/src/common-ssh/sftp.c
index 4be1568..e0e029f 100644
--- a/src/common-ssh/sftp.c
+++ b/src/common-ssh/sftp.c
@@ -33,6 +33,111 @@
 #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
  * session into a Guacamole protocol status code.
  *
@@ -184,6 +289,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
  * (upload). The data associated with the given stream is expected to be a
  * pointer to an open LIBSSH2_SFTP_HANDLE for the file to which the data
@@ -568,6 +740,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
  * the Guacamole protocol, get messages request the body of a file within the
  * filesystem.
@@ -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,
         guac_object* object, char* name) {
 
+    char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH];
+
     guac_common_ssh_sftp_filesystem* filesystem =
         (guac_common_ssh_sftp_filesystem*) object->data;
 
     LIBSSH2_SFTP* sftp = filesystem->sftp_session;
     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 */
-    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\"",
-                name);
+                fullpath);
         return 0;
     }
 
@@ -604,10 +817,10 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
     if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) {
 
         /* Open as directory */
-        LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, name);
+        LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, fullpath);
         if (dir == NULL) {
             guac_user_log(user, GUAC_LOG_INFO,
-                    "Unable to read directory \"%s\"", name);
+                    "Unable to read directory \"%s\"", fullpath);
             return 0;
         }
 
@@ -638,11 +851,11 @@ static int guac_common_ssh_sftp_get_handler(guac_user* user,
     else {
 
         /* 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);
         if (file == NULL) {
             guac_user_log(user, GUAC_LOG_INFO,
-                    "Unable to read file \"%s\"", name);
+                    "Unable to read file \"%s\"", fullpath);
             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,
         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*) object->data;
 
     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 */
-    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,
             S_IRUSR | S_IWUSR);
 
     /* Acknowledge stream if successful */
     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_STATUS_SUCCESS);
     }
@@ -708,7 +930,7 @@ static int guac_common_ssh_sftp_put_handler(guac_user* user,
     /* Abort on failure */
     else {
         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_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_session* session, const char* name) {
+        guac_common_ssh_session* session, const char* root_path,
+        const char* name) {
 
     /* Request SFTP */
     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));
 
     /* Associate SSH session with SFTP data and user */
-    filesystem->name = strdup(name);
     filesystem->ssh_session = 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 */
     strcpy(filesystem->upload_path, ".");
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/0474f86c/src/protocols/rdp/rdp.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
index d06fad3..c1be71e 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -988,7 +988,7 @@ void* guac_rdp_client_thread(void* data) {
         /* Load and expose filesystem */
         rdp_client->sftp_filesystem =
             guac_common_ssh_create_sftp_filesystem(
-                    rdp_client->sftp_session, "/");
+                    rdp_client->sftp_session, "/", NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/0474f86c/src/protocols/ssh/ssh.c
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c
index aa9fdae..18a0dcb 100644
--- a/src/protocols/ssh/ssh.c
+++ b/src/protocols/ssh/ssh.c
@@ -266,7 +266,7 @@ void* ssh_client_thread(void* data) {
 
         /* Request SFTP */
         ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(
-                    ssh_client->sftp_session, "/");
+                    ssh_client->sftp_session, "/", NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/0474f86c/src/protocols/vnc/vnc.c
----------------------------------------------------------------------
diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c
index 81d46f1..2b7263a 100644
--- a/src/protocols/vnc/vnc.c
+++ b/src/protocols/vnc/vnc.c
@@ -272,7 +272,7 @@ void* guac_vnc_client_thread(void* data) {
         /* Load filesystem */
         vnc_client->sftp_filesystem =
             guac_common_ssh_create_sftp_filesystem(
-                    vnc_client->sftp_session, "/");
+                    vnc_client->sftp_session, "/", NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,


[2/3] incubator-guacamole-server git commit: GUACAMOLE-303: Add "sftp-root-directory" parameter to VNC, RDP, and SSH.

Posted by vn...@apache.org.
GUACAMOLE-303: Add "sftp-root-directory" parameter to VNC, RDP, and SSH.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/d51e92eb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/d51e92eb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/d51e92eb

Branch: refs/heads/master
Commit: d51e92eb312735ec857e7ede0a202728ae9dcb26
Parents: 0474f86
Author: Michael Jumper <mj...@apache.org>
Authored: Thu Jun 29 15:48:23 2017 -0700
Committer: Michael Jumper <mj...@apache.org>
Committed: Thu Jun 29 15:48:23 2017 -0700

----------------------------------------------------------------------
 src/protocols/rdp/rdp.c          |  4 ++--
 src/protocols/rdp/rdp_settings.c | 13 +++++++++++++
 src/protocols/rdp/rdp_settings.h |  6 ++++++
 src/protocols/ssh/settings.c     | 15 +++++++++++++++
 src/protocols/ssh/settings.h     |  6 ++++++
 src/protocols/ssh/ssh.c          |  3 ++-
 src/protocols/vnc/settings.c     | 13 +++++++++++++
 src/protocols/vnc/settings.h     |  6 ++++++
 src/protocols/vnc/vnc.c          |  4 ++--
 9 files changed, 65 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/rdp/rdp.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c
index c1be71e..0b15d05 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -987,8 +987,8 @@ void* guac_rdp_client_thread(void* data) {
 
         /* Load and expose filesystem */
         rdp_client->sftp_filesystem =
-            guac_common_ssh_create_sftp_filesystem(
-                    rdp_client->sftp_session, "/", NULL);
+            guac_common_ssh_create_sftp_filesystem(rdp_client->sftp_session,
+                    settings->sftp_root_directory, NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/rdp/rdp_settings.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c
index f73ef9d..57e6016 100644
--- a/src/protocols/rdp/rdp_settings.c
+++ b/src/protocols/rdp/rdp_settings.c
@@ -84,6 +84,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = {
     "sftp-private-key",
     "sftp-passphrase",
     "sftp-directory",
+    "sftp-root-directory",
     "sftp-server-alive-interval",
 #endif
 
@@ -368,6 +369,12 @@ enum RDP_ARGS_IDX {
     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
      * SFTP connections.  The default is 0 (disabling keepalives), and a value
      * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner
@@ -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,
                 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 */
     settings->sftp_server_alive_interval =
         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
     /* Free SFTP settings */
     free(settings->sftp_directory);
+    free(settings->sftp_root_directory);
     free(settings->sftp_hostname);
     free(settings->sftp_passphrase);
     free(settings->sftp_password);

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/rdp/rdp_settings.h
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h
index 8edb79e..ec540ef 100644
--- a/src/protocols/rdp/rdp_settings.h
+++ b/src/protocols/rdp/rdp_settings.h
@@ -361,6 +361,12 @@ typedef struct guac_rdp_settings {
     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
      * SFTP connections.  The default is 0 (disabling keepalives), and a value
      * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/ssh/settings.c
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/settings.c b/src/protocols/ssh/settings.c
index 8843923..832dcfa 100644
--- a/src/protocols/ssh/settings.c
+++ b/src/protocols/ssh/settings.c
@@ -37,6 +37,7 @@ const char* GUAC_SSH_CLIENT_ARGS[] = {
     "font-name",
     "font-size",
     "enable-sftp",
+    "sftp-root-directory",
     "private-key",
     "passphrase",
 #ifdef ENABLE_SSH_AGENT
@@ -93,6 +94,12 @@ enum SSH_ARGS_IDX {
     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.
      */
     IDX_PRIVATE_KEY,
@@ -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,
                 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
     settings->enable_agent =
         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(settings->command);
 
+    /* Free SFTP settings */
+    free(settings->sftp_root_directory);
+
     /* Free typescript settings */
     free(settings->typescript_name);
     free(settings->typescript_path);

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/ssh/settings.h
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/settings.h b/src/protocols/ssh/settings.h
index f49d054..f093023 100644
--- a/src/protocols/ssh/settings.h
+++ b/src/protocols/ssh/settings.h
@@ -145,6 +145,12 @@ typedef struct guac_ssh_settings {
      */
     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
     /**
      * Whether the SSH agent is enabled.

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/ssh/ssh.c
----------------------------------------------------------------------
diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c
index 18a0dcb..b9bb59b 100644
--- a/src/protocols/ssh/ssh.c
+++ b/src/protocols/ssh/ssh.c
@@ -266,7 +266,8 @@ void* ssh_client_thread(void* data) {
 
         /* Request SFTP */
         ssh_client->sftp_filesystem = guac_common_ssh_create_sftp_filesystem(
-                    ssh_client->sftp_session, "/", NULL);
+                    ssh_client->sftp_session, settings->sftp_root_directory,
+                    NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/vnc/settings.c
----------------------------------------------------------------------
diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c
index 697466d..0bcd5ab 100644
--- a/src/protocols/vnc/settings.c
+++ b/src/protocols/vnc/settings.c
@@ -66,6 +66,7 @@ const char* GUAC_VNC_CLIENT_ARGS[] = {
     "sftp-private-key",
     "sftp-passphrase",
     "sftp-directory",
+    "sftp-root-directory",
     "sftp-server-alive-interval",
 #endif
 
@@ -230,6 +231,12 @@ enum VNC_ARGS_IDX {
     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
      * SFTP connections.  The default is 0 (disabling keepalives), and a value
      * of 1 is automatically incremented to 2 by libssh2 to avoid busy loop corner
@@ -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,
                 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 */
     settings->sftp_server_alive_interval =
         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
     /* Free SFTP settings */
     free(settings->sftp_directory);
+    free(settings->sftp_root_directory);
     free(settings->sftp_hostname);
     free(settings->sftp_passphrase);
     free(settings->sftp_password);

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/vnc/settings.h
----------------------------------------------------------------------
diff --git a/src/protocols/vnc/settings.h b/src/protocols/vnc/settings.h
index 3c7b258..4fa8eb4 100644
--- a/src/protocols/vnc/settings.h
+++ b/src/protocols/vnc/settings.h
@@ -175,6 +175,12 @@ typedef struct guac_vnc_settings {
     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
      * SFTP connections.  The default is 0 (disabling keepalives), and a value
      * of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d51e92eb/src/protocols/vnc/vnc.c
----------------------------------------------------------------------
diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c
index 2b7263a..38c7cd6 100644
--- a/src/protocols/vnc/vnc.c
+++ b/src/protocols/vnc/vnc.c
@@ -271,8 +271,8 @@ void* guac_vnc_client_thread(void* data) {
 
         /* Load filesystem */
         vnc_client->sftp_filesystem =
-            guac_common_ssh_create_sftp_filesystem(
-                    vnc_client->sftp_session, "/", NULL);
+            guac_common_ssh_create_sftp_filesystem(vnc_client->sftp_session,
+                    settings->sftp_root_directory, NULL);
 
         /* Expose filesystem to connection owner */
         guac_client_for_owner(client,


[3/3] incubator-guacamole-server git commit: GUACAMOLE-303: Merge Allow root directory of SFTP filesystem to be configured.

Posted by vn...@apache.org.
GUACAMOLE-303: Merge Allow root directory of SFTP filesystem to be configured.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/07db9808
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/07db9808
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/07db9808

Branch: refs/heads/master
Commit: 07db9808a09d40d4a4e38fe605ae2c9b453afa84
Parents: 836fc3e d51e92e
Author: Nick Couchman <vn...@apache.org>
Authored: Mon Jul 3 17:47:05 2017 -0400
Committer: Nick Couchman <vn...@apache.org>
Committed: Mon Jul 3 17:47:05 2017 -0400

----------------------------------------------------------------------
 src/common-ssh/common-ssh/sftp.h |  21 ++-
 src/common-ssh/sftp.c            | 259 ++++++++++++++++++++++++++++++++--
 src/protocols/rdp/rdp.c          |   4 +-
 src/protocols/rdp/rdp_settings.c |  13 ++
 src/protocols/rdp/rdp_settings.h |   6 +
 src/protocols/ssh/settings.c     |  15 ++
 src/protocols/ssh/settings.h     |   6 +
 src/protocols/ssh/ssh.c          |   3 +-
 src/protocols/vnc/settings.c     |  13 ++
 src/protocols/vnc/settings.h     |   6 +
 src/protocols/vnc/vnc.c          |   4 +-
 11 files changed, 332 insertions(+), 18 deletions(-)
----------------------------------------------------------------------