guacamole-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmuehl...@apache.org
Subject [2/9] incubator-guacamole-server git commit: GUACAMOLE-169: Move common-ssh headers to namespaced directory.
Date Tue, 28 Feb 2017 18:40:38 GMT
GUACAMOLE-169: Move common-ssh headers to namespaced directory.


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/d371f2d9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/d371f2d9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/d371f2d9

Branch: refs/heads/master
Commit: d371f2d9eee689d717dcd0eae4238812a835258c
Parents: a808a6b
Author: Michael Jumper <mjumper@apache.org>
Authored: Mon Feb 27 14:28:23 2017 -0800
Committer: Michael Jumper <mjumper@apache.org>
Committed: Mon Feb 27 14:28:23 2017 -0800

----------------------------------------------------------------------
 src/common-ssh/Makefile.am         |  24 +-
 src/common-ssh/buffer.c            | 135 ++++++
 src/common-ssh/common-ssh/buffer.h | 134 ++++++
 src/common-ssh/common-ssh/key.h    | 170 +++++++
 src/common-ssh/common-ssh/sftp.h   | 242 ++++++++++
 src/common-ssh/common-ssh/ssh.h    | 114 +++++
 src/common-ssh/common-ssh/user.h   | 108 +++++
 src/common-ssh/guac_sftp.c         | 783 --------------------------------
 src/common-ssh/guac_sftp.h         | 242 ----------
 src/common-ssh/guac_ssh.c          | 544 ----------------------
 src/common-ssh/guac_ssh.h          | 114 -----
 src/common-ssh/guac_ssh_buffer.c   | 135 ------
 src/common-ssh/guac_ssh_buffer.h   | 134 ------
 src/common-ssh/guac_ssh_key.c      | 217 ---------
 src/common-ssh/guac_ssh_key.h      | 170 -------
 src/common-ssh/guac_ssh_user.c     |  82 ----
 src/common-ssh/guac_ssh_user.h     | 108 -----
 src/common-ssh/key.c               | 217 +++++++++
 src/common-ssh/sftp.c              | 783 ++++++++++++++++++++++++++++++++
 src/common-ssh/ssh.c               | 544 ++++++++++++++++++++++
 src/common-ssh/user.c              |  82 ++++
 src/protocols/rdp/client.c         |   6 +-
 src/protocols/rdp/rdp.c            |   6 +-
 src/protocols/rdp/rdp.h            |   6 +-
 src/protocols/rdp/sftp.c           |   2 +-
 src/protocols/ssh/client.c         |   2 +-
 src/protocols/ssh/sftp.c           |   2 +-
 src/protocols/ssh/ssh.c            |   4 +-
 src/protocols/ssh/ssh.h            |   6 +-
 src/protocols/vnc/client.c         |   6 +-
 src/protocols/vnc/sftp.c           |   2 +-
 src/protocols/vnc/vnc.c            |   4 +-
 src/protocols/vnc/vnc.h            |   6 +-
 33 files changed, 2567 insertions(+), 2567 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/Makefile.am
----------------------------------------------------------------------
diff --git a/src/common-ssh/Makefile.am b/src/common-ssh/Makefile.am
index a53f2cf..c05f264 100644
--- a/src/common-ssh/Makefile.am
+++ b/src/common-ssh/Makefile.am
@@ -23,18 +23,18 @@ ACLOCAL_AMFLAGS = -I m4
 noinst_LTLIBRARIES = libguac_common_ssh.la
 
 libguac_common_ssh_la_SOURCES = \
-    guac_sftp.c                 \
-    guac_ssh.c                  \
-    guac_ssh_buffer.c           \
-    guac_ssh_key.c              \
-    guac_ssh_user.c
-
-noinst_HEADERS =      \
-    guac_sftp.h       \
-    guac_ssh.h        \
-    guac_ssh_buffer.h \
-    guac_ssh_key.h    \
-    guac_ssh_user.h
+    buffer.c                    \
+    sftp.c                      \
+    ssh.c                       \
+    key.c                       \
+    user.c
+
+noinst_HEADERS =        \
+    common-ssh/buffer.h \
+    common-ssh/key.h    \
+    common-ssh/sftp.h   \
+    common-ssh/ssh.h    \
+    common-ssh/user.h
 
 libguac_common_ssh_la_CFLAGS = \
     -Werror -Wall -pedantic    \

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/buffer.c
----------------------------------------------------------------------
diff --git a/src/common-ssh/buffer.c b/src/common-ssh/buffer.c
new file mode 100644
index 0000000..b3d8d57
--- /dev/null
+++ b/src/common-ssh/buffer.c
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "config.h"
+
+#include <openssl/bn.h>
+#include <openssl/ossl_typ.h>
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+void guac_common_ssh_buffer_write_byte(char** buffer, uint8_t value) {
+
+    uint8_t* data = (uint8_t*) *buffer;
+    *data = value;
+
+    (*buffer)++;
+
+}
+
+void guac_common_ssh_buffer_write_uint32(char** buffer, uint32_t value) {
+
+    uint8_t* data = (uint8_t*) *buffer;
+
+    data[0] = (value & 0xFF000000) >> 24;
+    data[1] = (value & 0x00FF0000) >> 16;
+    data[2] = (value & 0x0000FF00) >> 8;
+    data[3] =  value & 0x000000FF;
+
+    *buffer += 4;
+
+}
+
+void guac_common_ssh_buffer_write_data(char** buffer, const char* data,
+        int length) {
+    memcpy(*buffer, data, length);
+    *buffer += length;
+}
+
+void guac_common_ssh_buffer_write_bignum(char** buffer, BIGNUM* value) {
+
+    unsigned char* bn_buffer;
+    int length;
+
+    /* If zero, just write zero length */
+    if (BN_is_zero(value)) {
+        guac_common_ssh_buffer_write_uint32(buffer, 0);
+        return;
+    }
+
+    /* Allocate output buffer, add padding byte */
+    length = BN_num_bytes(value);
+    bn_buffer = malloc(length);
+
+    /* Convert BIGNUM */
+    BN_bn2bin(value, bn_buffer);
+
+    /* If first byte has high bit set, write padding byte */
+    if (bn_buffer[0] & 0x80) {
+        guac_common_ssh_buffer_write_uint32(buffer, length+1);
+        guac_common_ssh_buffer_write_byte(buffer, 0);
+    }
+    else
+        guac_common_ssh_buffer_write_uint32(buffer, length);
+
+    /* Write data */
+    memcpy(*buffer, bn_buffer, length);
+    *buffer += length;
+
+    free(bn_buffer);
+
+}
+
+void guac_common_ssh_buffer_write_string(char** buffer, const char* string,
+        int length) {
+    guac_common_ssh_buffer_write_uint32(buffer, length);
+    guac_common_ssh_buffer_write_data(buffer, string, length);
+}
+
+uint8_t guac_common_ssh_buffer_read_byte(char** buffer) {
+
+    uint8_t* data = (uint8_t*) *buffer;
+    uint8_t value = *data;
+
+    (*buffer)++;
+
+    return value;
+
+}
+
+uint32_t guac_common_ssh_buffer_read_uint32(char** buffer) {
+
+    uint8_t* data = (uint8_t*) *buffer;
+    uint32_t value =
+          (data[0] << 24)
+        | (data[1] << 16)
+        | (data[2] <<  8)
+        |  data[3];
+
+    *buffer += 4;
+
+    return value;
+
+}
+
+char* guac_common_ssh_buffer_read_string(char** buffer, int* length) {
+
+    char* value;
+
+    *length = guac_common_ssh_buffer_read_uint32(buffer);
+    value = *buffer;
+
+    *buffer += *length;
+
+    return value;
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/common-ssh/buffer.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/common-ssh/buffer.h b/src/common-ssh/common-ssh/buffer.h
new file mode 100644
index 0000000..b42a2ac
--- /dev/null
+++ b/src/common-ssh/common-ssh/buffer.h
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_COMMON_SSH_BUFFER_H
+#define GUAC_COMMON_SSH_BUFFER_H
+
+#include "config.h"
+
+#include <openssl/bn.h>
+#include <stdint.h>
+
+/**
+ * Writes the given byte to the given buffer, advancing the buffer pointer by
+ * one byte.
+ *
+ * @param buffer
+ *     The buffer to write to.
+ *
+ * @param value
+ *     The value to write.
+ */
+void guac_common_ssh_buffer_write_byte(char** buffer, uint8_t value);
+
+/**
+ * Writes the given integer to the given buffer, advancing the buffer pointer
+ * four bytes.
+ *
+ * @param buffer
+ *     The buffer to write to.
+ *
+ * @param value
+ *     The value to write.
+ */
+void guac_common_ssh_buffer_write_uint32(char** buffer, uint32_t value);
+
+/**
+ * Writes the given string and its length to the given buffer, advancing the
+ * buffer pointer by the size of the length (four bytes) and the size of the
+ * string.
+ *
+ * @param buffer
+ *     The buffer to write to.
+ *
+ * @param string
+ *     The string value to write.
+ *
+ * @param length
+ *     The length of the string to write, in bytes.
+ */
+void guac_common_ssh_buffer_write_string(char** buffer, const char* string,
+        int length);
+
+/**
+ * Writes the given BIGNUM the given buffer, advancing the buffer pointer by
+ * the size of the length (four bytes) and the size of the BIGNUM.
+ *
+ * @param buffer
+ *     The buffer to write to.
+ *
+ * @param value
+ *     The value to write.
+ */
+void guac_common_ssh_buffer_write_bignum(char** buffer, BIGNUM* value);
+
+/**
+ * Writes the given data the given buffer, advancing the buffer pointer by the
+ * given length.
+ *
+ * @param data
+ *     The arbitrary data to write.
+ *
+ * @param length
+ *     The length of data to write, in bytes.
+ */
+void guac_common_ssh_buffer_write_data(char** buffer, const char* data, int length);
+
+/**
+ * Reads a single byte from the given buffer, advancing the buffer by one byte.
+ *
+ * @param buffer
+ *     The buffer to read from.
+ *
+ * @return
+ *     The value read from the buffer.
+ */
+uint8_t guac_common_ssh_buffer_read_byte(char** buffer);
+
+/**
+ * Reads an integer from the given buffer, advancing the buffer by four bytes.
+ *
+ * @param buffer
+ *     The buffer to read from.
+ *
+ * @return
+ *     The value read from the buffer.
+ */
+uint32_t guac_common_ssh_buffer_read_uint32(char** buffer);
+
+/**
+ * Reads a string and its length from the given buffer, advancing the buffer
+ * by the size of the length (four bytes) and the size of the string, and
+ * returning a pointer to the buffer. The length of the string is stored in
+ * the given int.
+ *
+ * @param buffer
+ *     The buffer to read from.
+ *
+ * @param length
+ *     A pointer to an integer into which the length of the read string will
+ *     be stored.
+ *
+ * @return
+ *     A pointer to the value within the buffer.
+ */
+char* guac_common_ssh_buffer_read_string(char** buffer, int* length);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/common-ssh/key.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/common-ssh/key.h b/src/common-ssh/common-ssh/key.h
new file mode 100644
index 0000000..1754dea
--- /dev/null
+++ b/src/common-ssh/common-ssh/key.h
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_COMMON_SSH_KEY_H
+#define GUAC_COMMON_SSH_KEY_H
+
+#include "config.h"
+
+#include <openssl/ossl_typ.h>
+
+/**
+ * The expected header of RSA private keys.
+ */
+#define SSH_RSA_KEY_HEADER "-----BEGIN RSA PRIVATE KEY-----"
+
+/**
+ * The expected header of DSA private keys.
+ */
+#define SSH_DSA_KEY_HEADER "-----BEGIN DSA PRIVATE KEY-----"
+
+/**
+ * The size of single number within a DSA signature, in bytes.
+ */
+#define DSA_SIG_NUMBER_SIZE 20
+
+/**
+ * The size of a DSA signature, in bytes.
+ */
+#define DSA_SIG_SIZE DSA_SIG_NUMBER_SIZE*2 
+
+/**
+ * The type of an SSH key.
+ */
+typedef enum guac_common_ssh_key_type {
+
+    /**
+     * RSA key.
+     */
+    SSH_KEY_RSA,
+
+    /**
+     * DSA key.
+     */
+    SSH_KEY_DSA
+
+} guac_common_ssh_key_type;
+
+/**
+ * Abstraction of a key used for SSH authentication.
+ */
+typedef struct guac_common_ssh_key {
+
+    /**
+     * The type of this key.
+     */
+    guac_common_ssh_key_type type;
+
+    /**
+     * Underlying RSA private key, if any.
+     */
+    RSA* rsa;
+
+    /**
+     * Underlying DSA private key, if any.
+     */
+    DSA* dsa;
+
+    /**
+     * The associated public key, encoded as necessary for SSH.
+     */
+    char* public_key;
+
+    /**
+     * The length of the public key, in bytes.
+     */
+    int public_key_length;
+
+    /**
+     * The private key, encoded as necessary for SSH.
+     */
+    char* private_key;
+
+    /**
+     * The length of the private key, in bytes.
+     */
+    int private_key_length;
+
+} guac_common_ssh_key;
+
+/**
+ * Allocates a new key containing the given private key data and specified
+ * passphrase. If unable to read the key, NULL is returned.
+ *
+ * @param data
+ *     The base64-encoded data to decode when reading the key.
+ *
+ * @param length
+ *     The length of the provided data, in bytes.
+ *
+ * @param passphrase
+ *     The passphrase to use when decrypting the key, if any, or an empty
+ *     string or NULL if no passphrase is needed.
+ *
+ * @return
+ *     The decoded, decrypted private key, or NULL if the key could not be
+ *     decoded.
+ */
+guac_common_ssh_key* guac_common_ssh_key_alloc(char* data, int length,
+        char* passphrase);
+
+/**
+ * Returns a statically-allocated string describing the most recent SSH key
+ * error.
+ *
+ * @return
+ *     A statically-allocated string describing the most recent SSH key error.
+ */
+const char* guac_common_ssh_key_error();
+
+/**
+ * Frees all memory associated with the given key.
+ *
+ * @param key
+ *     The key to free.
+ */
+void guac_common_ssh_key_free(guac_common_ssh_key* key);
+
+/**
+ * Signs the given data using the given key, returning the length of the
+ * signature in bytes, or a value less than zero on error.
+ *
+ * @param key
+ *     The key to use when signing the given data.
+ *
+ * @param data
+ *     The arbitrary data to sign.
+ *
+ * @param length
+ *     The length of the arbitrary data being signed, in bytes.
+ *
+ * @param sig
+ *     The buffer into which the signature should be written. The buffer must
+ *     be at least DSA_SIG_SIZE for DSA keys. For RSA keys, the signature size
+ *     is dependent only on key size, and is equal to the length of the
+ *     modulus, in bytes.
+ *
+ * @return
+ *     The number of bytes in the resulting signature.
+ */
+int guac_common_ssh_key_sign(guac_common_ssh_key* key, const char* data,
+        int length, unsigned char* sig);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/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
new file mode 100644
index 0000000..038a577
--- /dev/null
+++ b/src/common-ssh/common-ssh/sftp.h
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_COMMON_SSH_SFTP_H
+#define GUAC_COMMON_SSH_SFTP_H
+
+#include "common/json.h"
+#include "ssh.h"
+
+#include <guacamole/object.h>
+#include <guacamole/user.h>
+#include <libssh2.h>
+#include <libssh2_sftp.h>
+
+/**
+ * Maximum number of bytes per path.
+ */
+#define GUAC_COMMON_SSH_SFTP_MAX_PATH 2048
+
+/**
+ * Representation of an SFTP-driven filesystem object. Unlike guac_object, this
+ * structure is not tied to any particular user.
+ */
+typedef struct guac_common_ssh_sftp_filesystem {
+
+    /**
+     * The human-readable display name of this filesystem.
+     */
+    char* name;
+
+    /**
+     * The distinct SSH session used for SFTP.
+     */
+    guac_common_ssh_session* ssh_session;
+
+    /**
+     * SFTP session, used for file transfers.
+     */
+    LIBSSH2_SFTP* sftp_session;
+
+    /**
+     * The path files will be sent to, if uploaded directly via a "file"
+     * instruction.
+     */
+    char upload_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
+
+} guac_common_ssh_sftp_filesystem;
+
+/**
+ * The current state of a directory listing operation.
+ */
+typedef struct guac_common_ssh_sftp_ls_state {
+
+    /**
+     * The SFTP filesystem being listed.
+     */
+    guac_common_ssh_sftp_filesystem* filesystem;
+
+    /**
+     * Reference to the directory currently being listed over SFTP. This
+     * directory must already be open from a call to libssh2_sftp_opendir().
+     */
+    LIBSSH2_SFTP_HANDLE* directory;
+
+    /**
+     * The absolute path of the directory being listed.
+     */
+    char directory_name[GUAC_COMMON_SSH_SFTP_MAX_PATH];
+
+    /**
+     * The current state of the JSON directory object being written.
+     */
+    guac_common_json_state json_state;
+
+} guac_common_ssh_sftp_ls_state;
+
+/**
+ * Creates a new Guacamole filesystem object which provides access to files
+ * and directories via SFTP using the given SSH session. When the filesystem
+ * will no longer be used, it must be explicitly destroyed with
+ * guac_common_ssh_destroy_sftp_filesystem(). The resulting object is not
+ * automatically exposed to users of the connection - filesystem operations
+ * must be mediated either through various handlers or through exposing a
+ * filesystem guac_object via guac_common_ssh_alloc_sftp_filesystem_object().
+ *
+ * @param session
+ *     The session to use to provide SFTP. This session will automatically be
+ *     destroyed when this filesystem is destroyed.
+ *
+ * @param name
+ *     The name to send as the name of the filesystem whenever it is exposed
+ *     to a user.
+ *
+ * @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);
+
+/**
+ * Destroys the given filesystem object, disconnecting from SFTP and freeing
+ * and associated resources. Any associated session or user objects must be
+ * explicitly destroyed.
+ *
+ * @param filesystem
+ *     The filesystem object to destroy.
+ */
+void guac_common_ssh_destroy_sftp_filesystem(
+        guac_common_ssh_sftp_filesystem* filesystem);
+
+/**
+ * Creates and exposes a new filesystem guac_object to the given user,
+ * providing access to the files within the given SFTP filesystem. The
+ * allocated guac_object must eventually be freed via guac_user_free_object().
+ *
+ * @param filesystem
+ *     The filesystem object to expose.
+ *
+ * @param user
+ *     The user that the SFTP filesystem should be exposed to.
+ *
+ * @return
+ *     A new Guacamole filesystem object, configured to use SFTP for uploading
+ *     and downloading files.
+ */
+guac_object* guac_common_ssh_alloc_sftp_filesystem_object(
+        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user);
+
+/**
+ * Allocates a new filesystem guac_object for the given user, returning the
+ * resulting guac_object. This function is provided for convenience, as it is
+ * can be used as the callback for guac_client_foreach_user() or
+ * guac_client_for_owner(). Note that this guac_object will be tracked
+ * internally by libguac, will be provided to us in the parameters of handlers
+ * related to that guac_object, and will automatically be freed when the
+ * associated guac_user is freed, so the return value of this function can
+ * safely be ignored.
+ *
+ * If either the given user or the given filesystem are NULL, then this
+ * function has no effect.
+ *
+ * @param user
+ *     The use to expose the filesystem to, or NULL if nothing should be
+ *     exposed.
+ *
+ * @param data
+ *     A pointer to the guac_common_ssh_sftp_filesystem instance to expose
+ *     to the given user, or NULL if nothing should be exposed.
+ *
+ * @return
+ *     The guac_object allocated for the newly-exposed filesystem, or NULL if
+ *     no filesystem object could be allocated.
+ */
+void* guac_common_ssh_expose_sftp_filesystem(guac_user* user, void* data);
+
+/**
+ * Initiates an SFTP file download to the user via the Guacamole "file"
+ * instruction. The download will be automatically monitored and continued
+ * after this function terminates in response to "ack" instructions received by
+ * the user.
+ *
+ * @param filesystem
+ *     The filesystem containing the file to be downloaded.
+ *
+ * @param user
+ *     The user that should receive the file (via a "file" instruction).
+ *
+ * @param filename
+ *     The filename of the file to download, relative to the given filesystem.
+ *
+ * @return
+ *     The file stream created for the file download, already configured to
+ *     properly handle "ack" responses, etc. from the user.
+ */
+guac_stream* guac_common_ssh_sftp_download_file(
+        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
+        char* filename);
+
+/**
+ * Handles an incoming stream from a Guacamole "file" instruction, saving the
+ * contents of that stream to the file having the given name within the
+ * upload directory set by guac_common_ssh_sftp_set_upload_path().
+ *
+ * @param filesystem
+ *     The filesystem that should receive the uploaded file.
+ *
+ * @param user
+ *     The user who is attempting to open the file stream (the user that sent
+ *     the "file" instruction).
+ *
+ * @param stream
+ *     The stream through which the uploaded file data will be received.
+ *
+ * @param mimetype
+ *     The mimetype of the data being received.
+ *
+ * @param filename
+ *     The filename of the file to write to. This filename will always be taken
+ *     relative to the upload path set by
+ *     guac_common_ssh_sftp_set_upload_path().
+ *
+ * @return
+ *     Zero if the incoming stream has been handled successfully, non-zero on
+ *     failure.
+ */
+int guac_common_ssh_sftp_handle_file_stream(
+        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
+        guac_stream* stream, char* mimetype, char* filename);
+
+/**
+ * Set the destination directory for future uploads submitted via
+ * guac_common_ssh_sftp_handle_file_stream(). This function has no bearing
+ * on the destination directories of files uploaded with "put" instructions.
+ *
+ * @param filesystem
+ *     The filesystem to set the upload path of.
+ *
+ * @param path
+ *     The path to use for future uploads submitted via the
+ *     guac_common_ssh_sftp_handle_file_stream() function.
+ */
+void guac_common_ssh_sftp_set_upload_path(
+        guac_common_ssh_sftp_filesystem* filesystem, const char* path);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/common-ssh/ssh.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/common-ssh/ssh.h b/src/common-ssh/common-ssh/ssh.h
new file mode 100644
index 0000000..d96ce44
--- /dev/null
+++ b/src/common-ssh/common-ssh/ssh.h
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_COMMON_SSH_H
+#define GUAC_COMMON_SSH_H
+
+#include "user.h"
+
+#include <guacamole/client.h>
+#include <libssh2.h>
+
+/**
+ * An SSH session, backed by libssh2 and associated with a particular
+ * Guacamole client.
+ */
+typedef struct guac_common_ssh_session {
+
+    /**
+     * The Guacamole client using this SSH session.
+     */
+    guac_client* client;
+
+    /**
+     * The user that will be authenticating via SSH.
+     */
+    guac_common_ssh_user* user;
+
+    /**
+     * The underlying SSH session from libssh2.
+     */
+    LIBSSH2_SESSION* session;
+
+    /**
+     * The file descriptor of the socket being used for the SSH connection.
+     */
+    int fd;
+
+} guac_common_ssh_session;
+
+/**
+ * Initializes the underlying SSH and encryption libraries used by Guacamole.
+ * This function must be called before any other guac_common_ssh_*() functions
+ * are called.
+ *
+ * @param client
+ *     The Guacamole client that will be using SSH.
+ *
+ * @return
+ *     Zero if initialization, or non-zero if an error occurs.
+ */
+int guac_common_ssh_init(guac_client* client);
+
+/**
+ * Cleans up the underlying SSH and encryption libraries used by Guacamole.
+ * This function must be called once no other guac_common_ssh_*() functions
+ * will be used.
+ */
+void guac_common_ssh_uninit();
+
+/**
+ * Connects to the SSH server running at the given hostname and port, and
+ * authenticates as the given user. If an error occurs while connecting or
+ * authenticating, the Guacamole client will automatically and fatally abort.
+ * The user object provided must eventually be explicitly destroyed, but should
+ * not be destroyed until this session is destroyed, assuming the session is
+ * successfully created.
+ *
+ * @param client
+ *     The Guacamole client that will be using SSH.
+ *
+ * @param hostname
+ *     The hostname of the SSH server to connect to.
+ *
+ * @param port
+ *     The port to connect to on the given hostname.
+ *
+ * @param user
+ *     The user to authenticate as, once connected.
+ *
+ * @return
+ *     A new SSH session if the connection and authentication succeed, or NULL
+ *     if the connection or authentication were not successful.
+ */
+guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
+        const char* hostname, const char* port, guac_common_ssh_user* user);
+
+/**
+ * Disconnects and destroys the given SSH session, freeing all associated
+ * resources. Any associated user must be explicitly destroyed, and will not
+ * be destroyed automatically.
+ *
+ * @param session
+ *     The SSH session to destroy.
+ */
+void guac_common_ssh_destroy_session(guac_common_ssh_session* session);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/common-ssh/user.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/common-ssh/user.h b/src/common-ssh/common-ssh/user.h
new file mode 100644
index 0000000..745728f
--- /dev/null
+++ b/src/common-ssh/common-ssh/user.h
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_COMMON_SSH_USER_H
+#define GUAC_COMMON_SSH_USER_H
+
+#include "key.h"
+
+/**
+ * Data describing an SSH user, including their credentials.
+ */
+typedef struct guac_common_ssh_user {
+
+    /**
+     * The username of this user.
+     */
+    char* username;
+
+    /**
+     * The password which should be used to authenticate this user, if any, or
+     * NULL if a private key will be used instead.
+     */
+    char* password;
+
+    /**
+     * The private key which should be used to authenticate this user, if any,
+     * or NULL if a password will be used instead.
+     */
+    guac_common_ssh_key* private_key;
+
+} guac_common_ssh_user;
+
+/**
+ * Creates a new SSH user with the given username. When additionally populated
+ * with a password or private key, this user can then be used for
+ * authentication.
+ *
+ * @param username
+ *     The username of the user being created.
+ *
+ * @return
+ *     A new SSH user having the given username, but no associated password
+ *     or private key.
+ */
+guac_common_ssh_user* guac_common_ssh_create_user(const char* username);
+
+/**
+ * Destroys the given user object, releasing all associated resources.
+ *
+ * @param user
+ *     The user to destroy.
+ */
+void guac_common_ssh_destroy_user(guac_common_ssh_user* user);
+
+/**
+ * Associates the given user with the given password, such that that password
+ * is used for future authentication attempts.
+ *
+ * @param user
+ *     The user to associate with the given password.
+ *
+ * @param password
+ *     The password to associate with the given user.
+ */
+void guac_common_ssh_user_set_password(guac_common_ssh_user* user,
+        const char* password);
+
+/**
+ * Imports the given private key, associating that key with the given user. If
+ * necessary to decrypt the key, a passphrase may be specified. The private key
+ * must be provided in base64 form. If the private key is imported
+ * successfully, it will be used for future authentication attempts.
+ *
+ * @param user
+ *     The user to associate with the given private key.
+ *
+ * @param private_key
+ *     The base64-encoded private key to import.
+ *
+ * @param passphrase
+ *     The passphrase to use to decrypt the given private key, or NULL if no
+ *     passphrase should be used.
+ *
+ * @return
+ *     Zero if the private key is successfully imported, or non-zero if the
+ *     private key could not be imported due to an error.
+ */
+int guac_common_ssh_user_import_key(guac_common_ssh_user* user,
+        char* private_key, char* passphrase);
+
+#endif
+

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/guac_sftp.c
----------------------------------------------------------------------
diff --git a/src/common-ssh/guac_sftp.c b/src/common-ssh/guac_sftp.c
deleted file mode 100644
index e7314d2..0000000
--- a/src/common-ssh/guac_sftp.c
+++ /dev/null
@@ -1,783 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "guac_sftp.h"
-#include "guac_ssh.h"
-
-#include <guacamole/client.h>
-#include <guacamole/object.h>
-#include <guacamole/protocol.h>
-#include <guacamole/socket.h>
-#include <guacamole/user.h>
-#include <libssh2.h>
-
-#include <fcntl.h>
-#include <libgen.h>
-#include <stdlib.h>
-#include <string.h>
-
-/**
- * Translates the last error message received by the SFTP layer of an SSH
- * session into a Guacamole protocol status code.
- *
- * @param filesystem
- *     The object (not guac_object) defining the filesystem associated with the
- *     SFTP and SSH sessions.
- *
- * @return
- *     The Guacamole protocol status code corresponding to the last reported
- *     error of the SFTP layer, if nay, or GUAC_PROTOCOL_STATUS_SUCCESS if no
- *     error has occurred.
- */
-static guac_protocol_status guac_sftp_get_status(
-        guac_common_ssh_sftp_filesystem* filesystem) {
-
-    /* Get libssh2 objects */
-    LIBSSH2_SFTP*    sftp    = filesystem->sftp_session;
-    LIBSSH2_SESSION* session = filesystem->ssh_session->session;
-
-    /* Return success code if no error occurred */
-    if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_SFTP_PROTOCOL)
-        return GUAC_PROTOCOL_STATUS_SUCCESS;
-
-    /* Translate SFTP error codes defined by
-     * https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02 (the most
-     * commonly-implemented standard) */
-    switch (libssh2_sftp_last_error(sftp)) {
-
-        /* SSH_FX_OK (not an error) */
-        case 0:
-            return GUAC_PROTOCOL_STATUS_SUCCESS;
-
-        /* SSH_FX_EOF (technically not an error) */
-        case 1:
-            return GUAC_PROTOCOL_STATUS_SUCCESS;
-
-        /* SSH_FX_NO_SUCH_FILE */
-        case 2:
-            return GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND;
-
-        /* SSH_FX_PERMISSION_DENIED */
-        case 3:
-            return GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN;
-
-        /* SSH_FX_FAILURE */
-        case 4:
-            return GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR;
-
-        /* SSH_FX_BAD_MESSAGE */
-        case 5:
-            return GUAC_PROTOCOL_STATUS_SERVER_ERROR;
-
-        /* SSH_FX_NO_CONNECTION / SSH_FX_CONNECTION_LOST */
-        case 6:
-        case 7:
-            return GUAC_PROTOCOL_STATUS_UPSTREAM_TIMEOUT;
-
-        /* SSH_FX_OP_UNSUPPORTED */
-        case 8:
-            return GUAC_PROTOCOL_STATUS_UNSUPPORTED;
-
-        /* Return generic error if cause unknown */
-        default:
-            return GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR;
-
-    }
-
-}
-
-/**
- * Concatenates the given filename with the given path, 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
- *     The path to append the filename to.
- *
- * @param filename
- *     The filename to append to the path.
- *
- * @return
- *     Non-zero if the filename is valid and was successfully appended to the
- *     path, zero otherwise.
- */
-static int guac_ssh_append_filename(char* fullpath, const char* path,
-        const char* filename) {
-
-    int i;
-
-    /* Disallow "." as a filename */
-    if (strcmp(filename, ".") == 0)
-        return 0;
-
-    /* Disallow ".." as a filename */
-    if (strcmp(filename, "..") == 0)
-        return 0;
-
-    /* Copy path, append trailing slash */
-    for (i=0; i<GUAC_COMMON_SSH_SFTP_MAX_PATH; i++) {
-
-        /*
-         * Append trailing slash only if:
-         *  1) Trailing slash is not already present
-         *  2) Path is non-empty
-         */
-
-        char c = path[i];
-        if (c == '\0') {
-            if (i > 0 && path[i-1] != '/')
-                fullpath[i++] = '/';
-            break;
-        }
-
-        /* Copy character if not end of string */
-        fullpath[i] = c;
-
-    }
-
-    /* Append filename */
-    for (; i<GUAC_COMMON_SSH_SFTP_MAX_PATH; i++) {
-
-        char c = *(filename++);
-        if (c == '\0')
-            break;
-
-        /* Filenames may not contain slashes */
-        if (c == '\\' || c == '/')
-            return 0;
-
-        /* Append each character within filename */
-        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
- * should be written.
- *
- * @param user
- *     The user receiving the blob message.
- *
- * @param stream
- *     The Guacamole protocol stream associated with the received blob message.
- *
- * @param data
- *     The data received within the blob.
- *
- * @param length
- *     The length of the received data, in bytes.
- *
- * @return
- *     Zero if the blob is handled successfully, or non-zero on error.
- */
-static int guac_common_ssh_sftp_blob_handler(guac_user* user,
-        guac_stream* stream, void* data, int length) {
-
-    /* Pull file from stream */
-    LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
-
-    /* Attempt write */
-    if (libssh2_sftp_write(file, data, length) == length) {
-        guac_user_log(user, GUAC_LOG_DEBUG, "%i bytes written", length);
-        guac_protocol_send_ack(user->socket, stream, "SFTP: OK",
-                GUAC_PROTOCOL_STATUS_SUCCESS);
-        guac_socket_flush(user->socket);
-    }
-
-    /* Inform of any errors */
-    else {
-        guac_user_log(user, GUAC_LOG_INFO, "Unable to write to file");
-        guac_protocol_send_ack(user->socket, stream, "SFTP: Write failed",
-                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
-        guac_socket_flush(user->socket);
-    }
-
-    return 0;
-
-}
-
-/**
- * Handler for end messages which terminate 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
- * has been written and which should now be closed.
- *
- * @param user
- *     The user receiving the end message.
- *
- * @param stream
- *     The Guacamole protocol stream associated with the received end message.
- *
- * @return
- *     Zero if the file is closed successfully, or non-zero on error.
- */
-static int guac_common_ssh_sftp_end_handler(guac_user* user,
-        guac_stream* stream) {
-
-    /* Pull file from stream */
-    LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
-
-    /* Attempt to close file */
-    if (libssh2_sftp_close(file) == 0) {
-        guac_user_log(user, GUAC_LOG_DEBUG, "File closed");
-        guac_protocol_send_ack(user->socket, stream, "SFTP: OK",
-                GUAC_PROTOCOL_STATUS_SUCCESS);
-        guac_socket_flush(user->socket);
-    }
-    else {
-        guac_user_log(user, GUAC_LOG_INFO, "Unable to close file");
-        guac_protocol_send_ack(user->socket, stream, "SFTP: Close failed",
-                GUAC_PROTOCOL_STATUS_SERVER_ERROR);
-        guac_socket_flush(user->socket);
-    }
-
-    return 0;
-
-}
-
-int guac_common_ssh_sftp_handle_file_stream(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
-        guac_stream* stream, char* mimetype, char* filename) {
-
-    char fullpath[GUAC_COMMON_SSH_SFTP_MAX_PATH];
-    LIBSSH2_SFTP_HANDLE* file;
-
-    /* Concatenate filename with path */
-    if (!guac_ssh_append_filename(fullpath, filesystem->upload_path,
-                filename)) {
-
-        guac_user_log(user, GUAC_LOG_DEBUG,
-                "Filename \"%s\" is invalid or resulting path is too long",
-                filename);
-
-        /* Abort transfer - invalid filename */
-        guac_protocol_send_ack(user->socket, stream, 
-                "SFTP: Illegal filename",
-                GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST);
-
-        guac_socket_flush(user->socket);
-        return 0;
-    }
-
-    /* Open file via SFTP */
-    file = libssh2_sftp_open(filesystem->sftp_session, fullpath,
-            LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC,
-            S_IRUSR | S_IWUSR);
-
-    /* Inform of status */
-    if (file != NULL) {
-
-        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);
-        guac_socket_flush(user->socket);
-    }
-    else {
-        guac_user_log(user, GUAC_LOG_INFO,
-                "Unable to open file \"%s\"", fullpath);
-        guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed",
-                guac_sftp_get_status(filesystem));
-        guac_socket_flush(user->socket);
-    }
-
-    /* Set handlers for file stream */
-    stream->blob_handler = guac_common_ssh_sftp_blob_handler;
-    stream->end_handler = guac_common_ssh_sftp_end_handler;
-
-    /* Store file within stream */
-    stream->data = file;
-    return 0;
-
-}
-
-/**
- * Handler for ack messages which continue an outbound SFTP data transfer
- * (download), signalling the current status and requesting additional data.
- * 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.
- *
- * @param user
- *     The user receiving the ack message.
- *
- * @param stream
- *     The Guacamole protocol stream associated with the received ack message.
- *
- * @param message
- *     An arbitrary human-readable message describing the nature of the
- *     success or failure denoted by the ack message.
- *
- * @param status
- *     The status code associated with the ack message, which may indicate
- *     success or an error.
- *
- * @return
- *     Zero if the file is read from successfully, or non-zero on error.
- */
-static int guac_common_ssh_sftp_ack_handler(guac_user* user,
-        guac_stream* stream, char* message, guac_protocol_status status) {
-
-    /* Pull file from stream */
-    LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data;
-
-    /* If successful, read data */
-    if (status == GUAC_PROTOCOL_STATUS_SUCCESS) {
-
-        /* Attempt read into buffer */
-        char buffer[4096];
-        int bytes_read = libssh2_sftp_read(file, buffer, sizeof(buffer)); 
-
-        /* If bytes read, send as blob */
-        if (bytes_read > 0) {
-            guac_protocol_send_blob(user->socket, stream,
-                    buffer, bytes_read);
-
-            guac_user_log(user, GUAC_LOG_DEBUG, "%i bytes sent to user",
-                    bytes_read);
-
-        }
-
-        /* If EOF, send end */
-        else if (bytes_read == 0) {
-            guac_user_log(user, GUAC_LOG_DEBUG, "File sent");
-            guac_protocol_send_end(user->socket, stream);
-            guac_user_free_stream(user, stream);
-        }
-
-        /* Otherwise, fail stream */
-        else {
-            guac_user_log(user, GUAC_LOG_INFO, "Error reading file");
-            guac_protocol_send_end(user->socket, stream);
-            guac_user_free_stream(user, stream);
-        }
-
-        guac_socket_flush(user->socket);
-
-    }
-
-    /* Otherwise, return stream to user */
-    else
-        guac_user_free_stream(user, stream);
-
-    return 0;
-}
-
-guac_stream* guac_common_ssh_sftp_download_file(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
-        char* filename) {
-
-    guac_stream* stream;
-    LIBSSH2_SFTP_HANDLE* file;
-
-    /* Attempt to open file for reading */
-    file = libssh2_sftp_open(filesystem->sftp_session, filename,
-            LIBSSH2_FXF_READ, 0);
-    if (file == NULL) {
-        guac_user_log(user, GUAC_LOG_INFO, 
-                "Unable to read file \"%s\"", filename);
-        return NULL;
-    }
-
-    /* Allocate stream */
-    stream = guac_user_alloc_stream(user);
-    stream->ack_handler = guac_common_ssh_sftp_ack_handler;
-    stream->data = file;
-
-    /* Send stream start, strip name */
-    filename = basename(filename);
-    guac_protocol_send_file(user->socket, stream,
-            "application/octet-stream", filename);
-    guac_socket_flush(user->socket);
-
-    guac_user_log(user, GUAC_LOG_DEBUG, "Sending file \"%s\"", filename);
-    return stream;
-
-}
-
-void guac_common_ssh_sftp_set_upload_path(
-        guac_common_ssh_sftp_filesystem* filesystem, const char* path) {
-
-    guac_client* client = filesystem->ssh_session->client;
-
-    /* Ignore requests which exceed maximum-allowed path */
-    int length = strnlen(path, GUAC_COMMON_SSH_SFTP_MAX_PATH)+1;
-    if (length > GUAC_COMMON_SSH_SFTP_MAX_PATH) {
-        guac_client_log(client, GUAC_LOG_ERROR,
-                "Submitted path exceeds limit of %i bytes",
-                GUAC_COMMON_SSH_SFTP_MAX_PATH);
-        return;
-    }
-
-    /* Copy path */
-    memcpy(filesystem->upload_path, path, length);
-    guac_client_log(client, GUAC_LOG_DEBUG, "Upload path set to \"%s\"", path);
-
-}
-
-/**
- * Handler for ack messages received due to receipt of a "body" or "blob"
- * instruction associated with a SFTP directory list operation.
- *
- * @param user
- *     The user receiving the ack message.
- *
- * @param stream
- *     The Guacamole protocol stream associated with the received ack message.
- *
- * @param message
- *     An arbitrary human-readable message describing the nature of the
- *     success or failure denoted by this ack message.
- *
- * @param status
- *     The status code associated with this ack message, which may indicate
- *     success or an error.
- *
- * @return
- *     Zero on success, non-zero on error.
- */
-static int guac_common_ssh_sftp_ls_ack_handler(guac_user* user,
-        guac_stream* stream, char* message, guac_protocol_status status) {
-
-    int bytes_read;
-    int blob_written = 0;
-
-    char filename[GUAC_COMMON_SSH_SFTP_MAX_PATH];
-    LIBSSH2_SFTP_ATTRIBUTES attributes;
-
-    guac_common_ssh_sftp_ls_state* list_state =
-        (guac_common_ssh_sftp_ls_state*) stream->data;
-
-    guac_common_ssh_sftp_filesystem* filesystem = list_state->filesystem;
-
-    LIBSSH2_SFTP* sftp = filesystem->sftp_session;
-
-    /* If unsuccessful, free stream and abort */
-    if (status != GUAC_PROTOCOL_STATUS_SUCCESS) {
-        libssh2_sftp_closedir(list_state->directory);
-        guac_user_free_stream(user, stream);
-        free(list_state);
-        return 0;
-    }
-
-    /* While directory entries remain */
-    while ((bytes_read = libssh2_sftp_readdir(list_state->directory,
-                filename, sizeof(filename), &attributes)) > 0
-            && !blob_written) {
-
-        char absolute_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
-
-        /* Skip current and parent directory entries */
-        if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
-            continue;
-
-        /* Concatenate into absolute path - skip if invalid */
-        if (!guac_ssh_append_filename(absolute_path, 
-                    list_state->directory_name, filename)) {
-
-            guac_user_log(user, GUAC_LOG_DEBUG,
-                    "Skipping filename \"%s\" - filename is invalid or "
-                    "resulting path is too long", filename);
-
-            continue;
-        }
-
-        /* Stat explicitly if symbolic link (might point to directory) */
-        if (LIBSSH2_SFTP_S_ISLNK(attributes.permissions))
-            libssh2_sftp_stat(sftp, absolute_path, &attributes);
-
-        /* Determine mimetype */
-        const char* mimetype;
-        if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions))
-            mimetype = GUAC_USER_STREAM_INDEX_MIMETYPE;
-        else
-            mimetype = "application/octet-stream";
-
-        /* Write entry */
-        blob_written |= guac_common_json_write_property(user, stream,
-                &list_state->json_state, absolute_path, mimetype);
-
-    }
-
-    /* Complete JSON and cleanup at end of directory */
-    if (bytes_read <= 0) {
-
-        /* Complete JSON object */
-        guac_common_json_end_object(user, stream, &list_state->json_state);
-        guac_common_json_flush(user, stream, &list_state->json_state);
-
-        /* Clean up resources */
-        libssh2_sftp_closedir(list_state->directory);
-        free(list_state);
-
-        /* Signal of stream */
-        guac_protocol_send_end(user->socket, stream);
-        guac_user_free_stream(user, stream);
-
-    }
-
-    guac_socket_flush(user->socket);
-    return 0;
-
-}
-
-/**
- * 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.
- *
- * @param user
- *     The user who sent the get message.
- *
- * @param object
- *     The Guacamole protocol object associated with the get request itself.
- *
- * @param name
- *     The name of the input stream (file) being requested.
- *
- * @return
- *     Zero on success, non-zero on error.
- */
-static int guac_common_ssh_sftp_get_handler(guac_user* user,
-        guac_object* object, char* name) {
-
-    guac_common_ssh_sftp_filesystem* filesystem =
-        (guac_common_ssh_sftp_filesystem*) object->data;
-
-    LIBSSH2_SFTP* sftp = filesystem->sftp_session;
-    LIBSSH2_SFTP_ATTRIBUTES attributes;
-
-    /* Attempt to read file information */
-    if (libssh2_sftp_stat(sftp, name, &attributes)) {
-        guac_user_log(user, GUAC_LOG_INFO, "Unable to read file \"%s\"",
-                name);
-        return 0;
-    }
-
-    /* If directory, send contents of directory */
-    if (LIBSSH2_SFTP_S_ISDIR(attributes.permissions)) {
-
-        /* Open as directory */
-        LIBSSH2_SFTP_HANDLE* dir = libssh2_sftp_opendir(sftp, name);
-        if (dir == NULL) {
-            guac_user_log(user, GUAC_LOG_INFO,
-                    "Unable to read directory \"%s\"", name);
-            return 0;
-        }
-
-        /* Init directory listing state */
-        guac_common_ssh_sftp_ls_state* list_state =
-            malloc(sizeof(guac_common_ssh_sftp_ls_state));
-
-        list_state->directory = dir;
-        list_state->filesystem = filesystem;
-        strncpy(list_state->directory_name, name,
-                sizeof(list_state->directory_name) - 1);
-
-        /* Allocate stream for body */
-        guac_stream* stream = guac_user_alloc_stream(user);
-        stream->ack_handler = guac_common_ssh_sftp_ls_ack_handler;
-        stream->data = list_state;
-
-        /* Init JSON object state */
-        guac_common_json_begin_object(user, stream, &list_state->json_state);
-
-        /* Associate new stream with get request */
-        guac_protocol_send_body(user->socket, object, stream,
-                GUAC_USER_STREAM_INDEX_MIMETYPE, name);
-
-    }
-
-    /* Otherwise, send file contents */
-    else {
-
-        /* Open as normal file */
-        LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, name,
-            LIBSSH2_FXF_READ, 0);
-        if (file == NULL) {
-            guac_user_log(user, GUAC_LOG_INFO,
-                    "Unable to read file \"%s\"", name);
-            return 0;
-        }
-
-        /* Allocate stream for body */
-        guac_stream* stream = guac_user_alloc_stream(user);
-        stream->ack_handler = guac_common_ssh_sftp_ack_handler;
-        stream->data = file;
-
-        /* Associate new stream with get request */
-        guac_protocol_send_body(user->socket, object, stream,
-                "application/octet-stream", name);
-
-    }
-
-    guac_socket_flush(user->socket);
-    return 0;
-}
-
-/**
- * Handler for put messages. In context of SFTP and the filesystem exposed via
- * the Guacamole protocol, put messages request write access to a file within
- * the filesystem.
- *
- * @param user
- *     The user who sent the put message.
- *
- * @param object
- *     The Guacamole protocol object associated with the put request itself.
- *
- * @param stream
- *     The Guacamole protocol stream along which the user will be sending
- *     file data.
- *
- * @param mimetype
- *     The mimetype of the data being send along the stream.
- *
- * @param name
- *     The name of the input stream (file) being requested.
- *
- * @return
- *     Zero on success, non-zero on error.
- */
-static int guac_common_ssh_sftp_put_handler(guac_user* user,
-        guac_object* object, guac_stream* stream, char* mimetype, char* name) {
-
-    guac_common_ssh_sftp_filesystem* filesystem =
-        (guac_common_ssh_sftp_filesystem*) object->data;
-
-    LIBSSH2_SFTP* sftp = filesystem->sftp_session;
-
-    /* Open file via SFTP */
-    LIBSSH2_SFTP_HANDLE* file = libssh2_sftp_open(sftp, name,
-            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_protocol_send_ack(user->socket, stream, "SFTP: File opened",
-                GUAC_PROTOCOL_STATUS_SUCCESS);
-    }
-
-    /* Abort on failure */
-    else {
-        guac_user_log(user, GUAC_LOG_INFO,
-                "Unable to open file \"%s\"", name);
-        guac_protocol_send_ack(user->socket, stream, "SFTP: Open failed",
-                guac_sftp_get_status(filesystem));
-    }
-
-    /* Set handlers for file stream */
-    stream->blob_handler = guac_common_ssh_sftp_blob_handler;
-    stream->end_handler = guac_common_ssh_sftp_end_handler;
-
-    /* Store file within stream */
-    stream->data = file;
-
-    guac_socket_flush(user->socket);
-    return 0;
-}
-
-void* guac_common_ssh_expose_sftp_filesystem(guac_user* user, void* data) {
-
-    guac_common_ssh_sftp_filesystem* filesystem =
-        (guac_common_ssh_sftp_filesystem*) data;
-
-    /* No need to expose if there is no filesystem or the user has left */
-    if (user == NULL || filesystem == NULL)
-        return NULL;
-
-    /* Allocate and expose filesystem object for user */
-    return guac_common_ssh_alloc_sftp_filesystem_object(filesystem, user);
-
-}
-
-guac_object* guac_common_ssh_alloc_sftp_filesystem_object(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user) {
-
-    /* Init filesystem */
-    guac_object* fs_object = guac_user_alloc_object(user);
-    fs_object->get_handler = guac_common_ssh_sftp_get_handler;
-    fs_object->put_handler = guac_common_ssh_sftp_put_handler;
-    fs_object->data = filesystem;
-
-    /* Send filesystem to user */
-    guac_protocol_send_filesystem(user->socket, fs_object, filesystem->name);
-    guac_socket_flush(user->socket);
-
-    return fs_object;
-
-}
-
-guac_common_ssh_sftp_filesystem* guac_common_ssh_create_sftp_filesystem(
-        guac_common_ssh_session* session, const char* name) {
-
-    /* Request SFTP */
-    LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session->session);
-    if (sftp_session == NULL)
-        return NULL;
-
-    /* Allocate data for SFTP session */
-    guac_common_ssh_sftp_filesystem* 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;
-
-    /* Initially upload files to current directory */
-    strcpy(filesystem->upload_path, ".");
-
-    /* Return allocated filesystem */
-    return filesystem;
-
-}
-
-void guac_common_ssh_destroy_sftp_filesystem(
-        guac_common_ssh_sftp_filesystem* filesystem) {
-
-    /* Shutdown SFTP session */
-    libssh2_sftp_shutdown(filesystem->sftp_session);
-
-    /* Free associated memory */
-    free(filesystem->name);
-    free(filesystem);
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/guac_sftp.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/guac_sftp.h b/src/common-ssh/guac_sftp.h
deleted file mode 100644
index fdc1e72..0000000
--- a/src/common-ssh/guac_sftp.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef GUAC_COMMON_SSH_SFTP_H
-#define GUAC_COMMON_SSH_SFTP_H
-
-#include "common/json.h"
-#include "guac_ssh.h"
-
-#include <guacamole/object.h>
-#include <guacamole/user.h>
-#include <libssh2.h>
-#include <libssh2_sftp.h>
-
-/**
- * Maximum number of bytes per path.
- */
-#define GUAC_COMMON_SSH_SFTP_MAX_PATH 2048
-
-/**
- * Representation of an SFTP-driven filesystem object. Unlike guac_object, this
- * structure is not tied to any particular user.
- */
-typedef struct guac_common_ssh_sftp_filesystem {
-
-    /**
-     * The human-readable display name of this filesystem.
-     */
-    char* name;
-
-    /**
-     * The distinct SSH session used for SFTP.
-     */
-    guac_common_ssh_session* ssh_session;
-
-    /**
-     * SFTP session, used for file transfers.
-     */
-    LIBSSH2_SFTP* sftp_session;
-
-    /**
-     * The path files will be sent to, if uploaded directly via a "file"
-     * instruction.
-     */
-    char upload_path[GUAC_COMMON_SSH_SFTP_MAX_PATH];
-
-} guac_common_ssh_sftp_filesystem;
-
-/**
- * The current state of a directory listing operation.
- */
-typedef struct guac_common_ssh_sftp_ls_state {
-
-    /**
-     * The SFTP filesystem being listed.
-     */
-    guac_common_ssh_sftp_filesystem* filesystem;
-
-    /**
-     * Reference to the directory currently being listed over SFTP. This
-     * directory must already be open from a call to libssh2_sftp_opendir().
-     */
-    LIBSSH2_SFTP_HANDLE* directory;
-
-    /**
-     * The absolute path of the directory being listed.
-     */
-    char directory_name[GUAC_COMMON_SSH_SFTP_MAX_PATH];
-
-    /**
-     * The current state of the JSON directory object being written.
-     */
-    guac_common_json_state json_state;
-
-} guac_common_ssh_sftp_ls_state;
-
-/**
- * Creates a new Guacamole filesystem object which provides access to files
- * and directories via SFTP using the given SSH session. When the filesystem
- * will no longer be used, it must be explicitly destroyed with
- * guac_common_ssh_destroy_sftp_filesystem(). The resulting object is not
- * automatically exposed to users of the connection - filesystem operations
- * must be mediated either through various handlers or through exposing a
- * filesystem guac_object via guac_common_ssh_alloc_sftp_filesystem_object().
- *
- * @param session
- *     The session to use to provide SFTP. This session will automatically be
- *     destroyed when this filesystem is destroyed.
- *
- * @param name
- *     The name to send as the name of the filesystem whenever it is exposed
- *     to a user.
- *
- * @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);
-
-/**
- * Destroys the given filesystem object, disconnecting from SFTP and freeing
- * and associated resources. Any associated session or user objects must be
- * explicitly destroyed.
- *
- * @param filesystem
- *     The filesystem object to destroy.
- */
-void guac_common_ssh_destroy_sftp_filesystem(
-        guac_common_ssh_sftp_filesystem* filesystem);
-
-/**
- * Creates and exposes a new filesystem guac_object to the given user,
- * providing access to the files within the given SFTP filesystem. The
- * allocated guac_object must eventually be freed via guac_user_free_object().
- *
- * @param filesystem
- *     The filesystem object to expose.
- *
- * @param user
- *     The user that the SFTP filesystem should be exposed to.
- *
- * @return
- *     A new Guacamole filesystem object, configured to use SFTP for uploading
- *     and downloading files.
- */
-guac_object* guac_common_ssh_alloc_sftp_filesystem_object(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user);
-
-/**
- * Allocates a new filesystem guac_object for the given user, returning the
- * resulting guac_object. This function is provided for convenience, as it is
- * can be used as the callback for guac_client_foreach_user() or
- * guac_client_for_owner(). Note that this guac_object will be tracked
- * internally by libguac, will be provided to us in the parameters of handlers
- * related to that guac_object, and will automatically be freed when the
- * associated guac_user is freed, so the return value of this function can
- * safely be ignored.
- *
- * If either the given user or the given filesystem are NULL, then this
- * function has no effect.
- *
- * @param user
- *     The use to expose the filesystem to, or NULL if nothing should be
- *     exposed.
- *
- * @param data
- *     A pointer to the guac_common_ssh_sftp_filesystem instance to expose
- *     to the given user, or NULL if nothing should be exposed.
- *
- * @return
- *     The guac_object allocated for the newly-exposed filesystem, or NULL if
- *     no filesystem object could be allocated.
- */
-void* guac_common_ssh_expose_sftp_filesystem(guac_user* user, void* data);
-
-/**
- * Initiates an SFTP file download to the user via the Guacamole "file"
- * instruction. The download will be automatically monitored and continued
- * after this function terminates in response to "ack" instructions received by
- * the user.
- *
- * @param filesystem
- *     The filesystem containing the file to be downloaded.
- *
- * @param user
- *     The user that should receive the file (via a "file" instruction).
- *
- * @param filename
- *     The filename of the file to download, relative to the given filesystem.
- *
- * @return
- *     The file stream created for the file download, already configured to
- *     properly handle "ack" responses, etc. from the user.
- */
-guac_stream* guac_common_ssh_sftp_download_file(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
-        char* filename);
-
-/**
- * Handles an incoming stream from a Guacamole "file" instruction, saving the
- * contents of that stream to the file having the given name within the
- * upload directory set by guac_common_ssh_sftp_set_upload_path().
- *
- * @param filesystem
- *     The filesystem that should receive the uploaded file.
- *
- * @param user
- *     The user who is attempting to open the file stream (the user that sent
- *     the "file" instruction).
- *
- * @param stream
- *     The stream through which the uploaded file data will be received.
- *
- * @param mimetype
- *     The mimetype of the data being received.
- *
- * @param filename
- *     The filename of the file to write to. This filename will always be taken
- *     relative to the upload path set by
- *     guac_common_ssh_sftp_set_upload_path().
- *
- * @return
- *     Zero if the incoming stream has been handled successfully, non-zero on
- *     failure.
- */
-int guac_common_ssh_sftp_handle_file_stream(
-        guac_common_ssh_sftp_filesystem* filesystem, guac_user* user,
-        guac_stream* stream, char* mimetype, char* filename);
-
-/**
- * Set the destination directory for future uploads submitted via
- * guac_common_ssh_sftp_handle_file_stream(). This function has no bearing
- * on the destination directories of files uploaded with "put" instructions.
- *
- * @param filesystem
- *     The filesystem to set the upload path of.
- *
- * @param path
- *     The path to use for future uploads submitted via the
- *     guac_common_ssh_sftp_handle_file_stream() function.
- */
-void guac_common_ssh_sftp_set_upload_path(
-        guac_common_ssh_sftp_filesystem* filesystem, const char* path);
-
-#endif
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/guac_ssh.c
----------------------------------------------------------------------
diff --git a/src/common-ssh/guac_ssh.c b/src/common-ssh/guac_ssh.c
deleted file mode 100644
index 488eea2..0000000
--- a/src/common-ssh/guac_ssh.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include "guac_ssh.h"
-#include "guac_ssh_key.h"
-#include "guac_ssh_user.h"
-
-#include <guacamole/client.h>
-#include <libssh2.h>
-
-#ifdef LIBSSH2_USES_GCRYPT
-#include <gcrypt.h>
-#endif
-
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-
-#include <errno.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <pthread.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
-
-#ifdef LIBSSH2_USES_GCRYPT
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
-#endif
-
-/**
- * Array of mutexes, used by OpenSSL.
- */
-static pthread_mutex_t* guac_common_ssh_openssl_locks = NULL;
-
-/**
- * Called by OpenSSL when locking or unlocking the Nth mutex.
- *
- * @param mode
- *     A bitmask denoting the action to be taken on the Nth lock, such as
- *     CRYPTO_LOCK or CRYPTO_UNLOCK.
- *
- * @param n
- *     The index of the lock to lock or unlock.
- *
- * @param file
- *     The filename of the function setting the lock, for debugging purposes.
- *
- * @param line
- *     The line number of the function setting the lock, for debugging
- *     purposes.
- */
-static void guac_common_ssh_openssl_locking_callback(int mode, int n,
-        const char* file, int line){
-
-    /* Lock given mutex upon request */
-    if (mode & CRYPTO_LOCK)
-        pthread_mutex_lock(&(guac_common_ssh_openssl_locks[n]));
-
-    /* Unlock given mutex upon request */
-    else if (mode & CRYPTO_UNLOCK)
-        pthread_mutex_unlock(&(guac_common_ssh_openssl_locks[n]));
-
-}
-
-/**
- * Called by OpenSSL when determining the current thread ID.
- *
- * @return
- *     An ID which uniquely identifies the current thread.
- */
-static unsigned long guac_common_ssh_openssl_id_callback() {
-    return (unsigned long) pthread_self();
-}
-
-/**
- * Creates the given number of mutexes, such that OpenSSL will have at least
- * this number of mutexes at its disposal.
- *
- * @param count
- *     The number of mutexes (locks) to create.
- */
-static void guac_common_ssh_openssl_init_locks(int count) {
-
-    int i;
-
-    /* Allocate required number of locks */
-    guac_common_ssh_openssl_locks =
-        malloc(sizeof(pthread_mutex_t) * count);
-
-    /* Initialize each lock */
-    for (i=0; i < count; i++)
-        pthread_mutex_init(&(guac_common_ssh_openssl_locks[i]), NULL);
-
-}
-
-/**
- * Frees the given number of mutexes.
- *
- * @param count
- *     The number of mutexes (locks) to free.
- */
-static void guac_common_ssh_openssl_free_locks(int count) {
-
-    int i;
-
-    /* SSL lock array was not initialized */
-    if (guac_common_ssh_openssl_locks == NULL)
-        return;
-
-    /* Free all locks */
-    for (i=0; i < count; i++)
-        pthread_mutex_destroy(&(guac_common_ssh_openssl_locks[i]));
-
-    /* Free lock array */
-    free(guac_common_ssh_openssl_locks);
-
-}
-
-int guac_common_ssh_init(guac_client* client) {
-
-#ifdef LIBSSH2_USES_GCRYPT
-    /* Init threadsafety in libgcrypt */
-    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
-    if (!gcry_check_version(GCRYPT_VERSION)) {
-        guac_client_log(client, GUAC_LOG_ERROR, "libgcrypt version mismatch.");
-        return 1;
-    }
-#endif
-
-    /* Init threadsafety in OpenSSL */
-    guac_common_ssh_openssl_init_locks(CRYPTO_num_locks());
-    CRYPTO_set_id_callback(guac_common_ssh_openssl_id_callback);
-    CRYPTO_set_locking_callback(guac_common_ssh_openssl_locking_callback);
-
-    /* Init OpenSSL */
-    SSL_library_init();
-    ERR_load_crypto_strings();
-
-    /* Init libssh2 */
-    libssh2_init(0);
-
-    /* Success */
-    return 0;
-
-}
-
-void guac_common_ssh_uninit() {
-    guac_common_ssh_openssl_free_locks(CRYPTO_num_locks());
-}
-
-/**
- * Callback invoked by libssh2 when libssh2_userauth_publickkey() is invoked.
- * This callback must sign the given data, returning the signature as newly-
- * allocated buffer space.
- *
- * @param session
- *     The SSH session for which the signature is being generated.
- *
- * @param sig
- *     A pointer to the buffer space containing the signature. This callback
- *     MUST allocate and assign this space.
- *
- * @param sig_len
- *     The length of the signature within the allocated buffer space, in bytes.
- *     This value must be set to the size of the signature after the signing
- *     operation completes.
- *
- * @param data
- *     The arbitrary data that must be signed.
- *
- * @param data_len
- *     The length of the arbitrary data to be signed, in bytes.
- *
- * @param abstract
- *     The value of the abstract parameter provided with the corresponding call
- *     to libssh2_userauth_publickey().
- *
- * @return
- *     Zero on success, non-zero if the signing operation failed.
- */
-static int guac_common_ssh_sign_callback(LIBSSH2_SESSION* session,
-        unsigned char** sig, size_t* sig_len,
-        const unsigned char* data, size_t data_len, void **abstract) {
-
-    guac_common_ssh_key* key = (guac_common_ssh_key*) abstract;
-    int length;
-
-    /* Allocate space for signature */
-    *sig = malloc(4096);
-
-    /* Sign with key */
-    length = guac_common_ssh_key_sign(key, (const char*) data, data_len, *sig);
-    if (length < 0)
-        return 1;
-
-    *sig_len = length;
-    return 0;
-}
-
-/**
- * Callback for the keyboard-interactive authentication method. Currently
- * supports just one prompt for the password. This callback is invoked as
- * needed to fullfill a call to libssh2_userauth_keyboard_interactive().
- *
- * @param name
- *     An arbitrary name which should be printed to the terminal for the
- *     benefit of the user. This is currently ignored.
- *
- * @param name_len
- *     The length of the name string, in bytes.
- *
- * @param instruction
- *     Arbitrary instructions which should be printed to the terminal for the
- *     benefit of the user. This is currently ignored.
- *
- * @param instruction_len
- *     The length of the instruction string, in bytes.
- *
- * @param num_prompts
- *     The number of keyboard-interactive prompts for which responses are
- *     requested. This callback currently only supports one prompt, and assumes
- *     that this prompt is requesting the password.
- *
- * @param prompts
- *     An array of all keyboard-interactive prompts for which responses are
- *     requested.
- *
- * @param responses
- *     A parallel array into which all prompt responses should be stored. Each
- *     entry within this array corresponds to the entry in the prompts array
- *     with the same index.
- *
- * @param abstract
- *     The value of the abstract parameter provided when the SSH session was
- *     created with libssh2_session_init_ex().
- */
-static void guac_common_ssh_kbd_callback(const char *name, int name_len,
-        const char *instruction, int instruction_len, int num_prompts,
-        const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
-        LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
-        void **abstract) {
-
-    guac_common_ssh_session* common_session =
-        (guac_common_ssh_session*) *abstract;
-
-    guac_client* client = common_session->client;
-
-    /* Send password if only one prompt */
-    if (num_prompts == 1) {
-        char* password = common_session->user->password;
-        responses[0].text = strdup(password);
-        responses[0].length = strlen(password);
-    }
-
-    /* If more than one prompt, a single password is not enough */
-    else
-        guac_client_log(client, GUAC_LOG_WARNING,
-                "Unsupported number of keyboard-interactive prompts: %i",
-                num_prompts);
-
-}
-
-/**
- * Authenticates the user associated with the given session over SSH. All
- * required credentials must already be present within the user object
- * associated with the given session.
- *
- * @param session
- *     The session associated with the user to be authenticated.
- *
- * @return
- *     Zero if authentication succeeds, or non-zero if authentication has
- *     failed.
- */
-static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session) {
-
-    guac_client* client = common_session->client;
-    guac_common_ssh_user* user = common_session->user;
-    LIBSSH2_SESSION* session = common_session->session;
-
-    /* Get user credentials */
-    char* username = user->username;
-    char* password = user->password;
-    guac_common_ssh_key* key = user->private_key;
-
-    /* Validate username provided */
-    if (username == NULL) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                "SSH authentication requires a username.");
-        return 1;
-    }
-
-    /* Get list of supported authentication methods */
-    char* user_authlist = libssh2_userauth_list(session, username,
-            strlen(username));
-    guac_client_log(client, GUAC_LOG_DEBUG,
-            "Supported authentication methods: %s", user_authlist);
-
-    /* Authenticate with private key, if provided */
-    if (key != NULL) {
-
-        /* Check if public key auth is supported on the server */
-        if (strstr(user_authlist, "publickey") == NULL) {
-            guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                    "Public key authentication is not supported by "
-                    "the SSH server");
-            return 1;
-        }
-
-        /* Attempt public key auth */
-        if (libssh2_userauth_publickey(session, username,
-                    (unsigned char*) key->public_key, key->public_key_length,
-                    guac_common_ssh_sign_callback, (void**) key)) {
-
-            /* Abort on failure */
-            char* error_message;
-            libssh2_session_last_error(session, &error_message, NULL, 0);
-            guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                    "Public key authentication failed: %s", error_message);
-
-            return 1;
-
-        }
-
-        /* Private key authentication succeeded */
-        return 0;
-
-    }
-
-    /* Authenticate with password, if provided */
-    else if (password != NULL) {
-
-        /* Check if password auth is supported on the server */
-        if (strstr(user_authlist, "password") != NULL) {
-
-            /* Attempt password authentication */
-            if (libssh2_userauth_password(session, username, password)) {
-
-                /* Abort on failure */
-                char* error_message;
-                libssh2_session_last_error(session, &error_message, NULL, 0);
-                guac_client_abort(client,
-                        GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                        "Password authentication failed: %s", error_message);
-
-                return 1;
-            }
-
-            /* Password authentication succeeded */
-            return 0;
-
-        }
-
-        /* Check if keyboard-interactive auth is supported on the server */
-        if (strstr(user_authlist, "keyboard-interactive") != NULL) {
-
-            /* Attempt keyboard-interactive auth using provided password */
-            if (libssh2_userauth_keyboard_interactive(session, username,
-                        &guac_common_ssh_kbd_callback)) {
-
-                /* Abort on failure */
-                char* error_message;
-                libssh2_session_last_error(session, &error_message, NULL, 0);
-                guac_client_abort(client,
-                        GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                        "Keyboard-interactive authentication failed: %s",
-                        error_message);
-
-                return 1;
-            }
-
-            /* Keyboard-interactive authentication succeeded */
-            return 0;
-
-        }
-
-        /* No known authentication types available */
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-                "Password and keyboard-interactive authentication are not "
-                "supported by the SSH server");
-        return 1;
-
-    }
-
-    /* No credentials provided */
-    guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
-            "SSH authentication requires either a private key or a password.");
-    return 1;
-
-}
-
-guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
-        const char* hostname, const char* port, guac_common_ssh_user* user) {
-
-    int retval;
-
-    int fd;
-    struct addrinfo* addresses;
-    struct addrinfo* current_address;
-
-    char connected_address[1024];
-    char connected_port[64];
-
-    struct addrinfo hints = {
-        .ai_family   = AF_UNSPEC,
-        .ai_socktype = SOCK_STREAM,
-        .ai_protocol = IPPROTO_TCP
-    };
-
-    /* Get socket */
-    fd = socket(AF_INET, SOCK_STREAM, 0);
-    if (fd < 0) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
-                "Unable to create socket: %s", strerror(errno));
-        return NULL;
-    }
-
-    /* Get addresses connection */
-    if ((retval = getaddrinfo(hostname, port, &hints, &addresses))) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
-                "Error parsing given address or port: %s",
-                gai_strerror(retval));
-        close(fd);
-        return NULL;
-    }
-
-    /* Attempt connection to each address until success */
-    current_address = addresses;
-    while (current_address != NULL) {
-
-        /* Resolve hostname */
-        if ((retval = getnameinfo(current_address->ai_addr,
-                current_address->ai_addrlen,
-                connected_address, sizeof(connected_address),
-                connected_port, sizeof(connected_port),
-                NI_NUMERICHOST | NI_NUMERICSERV)))
-            guac_client_log(client, GUAC_LOG_DEBUG,
-                    "Unable to resolve host: %s", gai_strerror(retval));
-
-        /* Connect */
-        if (connect(fd, current_address->ai_addr,
-                        current_address->ai_addrlen) == 0) {
-
-            guac_client_log(client, GUAC_LOG_DEBUG,
-                    "Successfully connected to host %s, port %s",
-                    connected_address, connected_port);
-
-            /* Done if successful connect */
-            break;
-
-        }
-
-        /* Otherwise log information regarding bind failure */
-        else
-            guac_client_log(client, GUAC_LOG_DEBUG, "Unable to connect to "
-                    "host %s, port %s: %s",
-                    connected_address, connected_port, strerror(errno));
-
-        current_address = current_address->ai_next;
-
-    }
-
-    /* Free addrinfo */
-    freeaddrinfo(addresses);
-
-    /* If unable to connect to anything, fail */
-    if (current_address == NULL) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
-                "Unable to connect to any addresses.");
-        close(fd);
-        return NULL;
-    }
-
-    /* Allocate new session */
-    guac_common_ssh_session* common_session =
-        malloc(sizeof(guac_common_ssh_session));
-
-    /* Open SSH session */
-    LIBSSH2_SESSION* session = libssh2_session_init_ex(NULL, NULL,
-            NULL, common_session);
-    if (session == NULL) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
-                "Session allocation failed.");
-        free(common_session);
-        close(fd);
-        return NULL;
-    }
-
-    /* Perform handshake */
-    if (libssh2_session_handshake(session, fd)) {
-        guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
-                "SSH handshake failed.");
-        free(common_session);
-        close(fd);
-        return NULL;
-    }
-
-    /* Store basic session data */
-    common_session->client = client;
-    common_session->user = user;
-    common_session->session = session;
-    common_session->fd = fd;
-
-    /* Attempt authentication */
-    if (guac_common_ssh_authenticate(common_session)) {
-        free(common_session);
-        close(fd);
-        return NULL;
-    }
-
-    /* Return created session */
-    return common_session;
-
-}
-
-void guac_common_ssh_destroy_session(guac_common_ssh_session* session) {
-
-    /* Disconnect and clean up libssh2 */
-    libssh2_session_disconnect(session->session, "Bye");
-    libssh2_session_free(session->session);
-
-    /* Free all other data */
-    free(session);
-
-}
-

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/d371f2d9/src/common-ssh/guac_ssh.h
----------------------------------------------------------------------
diff --git a/src/common-ssh/guac_ssh.h b/src/common-ssh/guac_ssh.h
deleted file mode 100644
index 36ad176..0000000
--- a/src/common-ssh/guac_ssh.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#ifndef GUAC_COMMON_SSH_H
-#define GUAC_COMMON_SSH_H
-
-#include "guac_ssh_user.h"
-
-#include <guacamole/client.h>
-#include <libssh2.h>
-
-/**
- * An SSH session, backed by libssh2 and associated with a particular
- * Guacamole client.
- */
-typedef struct guac_common_ssh_session {
-
-    /**
-     * The Guacamole client using this SSH session.
-     */
-    guac_client* client;
-
-    /**
-     * The user that will be authenticating via SSH.
-     */
-    guac_common_ssh_user* user;
-
-    /**
-     * The underlying SSH session from libssh2.
-     */
-    LIBSSH2_SESSION* session;
-
-    /**
-     * The file descriptor of the socket being used for the SSH connection.
-     */
-    int fd;
-
-} guac_common_ssh_session;
-
-/**
- * Initializes the underlying SSH and encryption libraries used by Guacamole.
- * This function must be called before any other guac_common_ssh_*() functions
- * are called.
- *
- * @param client
- *     The Guacamole client that will be using SSH.
- *
- * @return
- *     Zero if initialization, or non-zero if an error occurs.
- */
-int guac_common_ssh_init(guac_client* client);
-
-/**
- * Cleans up the underlying SSH and encryption libraries used by Guacamole.
- * This function must be called once no other guac_common_ssh_*() functions
- * will be used.
- */
-void guac_common_ssh_uninit();
-
-/**
- * Connects to the SSH server running at the given hostname and port, and
- * authenticates as the given user. If an error occurs while connecting or
- * authenticating, the Guacamole client will automatically and fatally abort.
- * The user object provided must eventually be explicitly destroyed, but should
- * not be destroyed until this session is destroyed, assuming the session is
- * successfully created.
- *
- * @param client
- *     The Guacamole client that will be using SSH.
- *
- * @param hostname
- *     The hostname of the SSH server to connect to.
- *
- * @param port
- *     The port to connect to on the given hostname.
- *
- * @param user
- *     The user to authenticate as, once connected.
- *
- * @return
- *     A new SSH session if the connection and authentication succeed, or NULL
- *     if the connection or authentication were not successful.
- */
-guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
-        const char* hostname, const char* port, guac_common_ssh_user* user);
-
-/**
- * Disconnects and destroys the given SSH session, freeing all associated
- * resources. Any associated user must be explicitly destroyed, and will not
- * be destroyed automatically.
- *
- * @param session
- *     The SSH session to destroy.
- */
-void guac_common_ssh_destroy_session(guac_common_ssh_session* session);
-
-#endif
-



Mime
View raw message