From 1500e63050187e8535fdd2cca52e95bd0b997eb4 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 10 Jul 2015 21:37:53 -0700 Subject: [PATCH] GUAC-1171: Add SFTP filesystem support to VNC. --- src/protocols/vnc/Makefile.am | 2 + src/protocols/vnc/client.c | 90 +++++++++++++++++++++++++++++++ src/protocols/vnc/client.h | 11 ++++ src/protocols/vnc/guac_handlers.c | 13 +++++ 4 files changed, 116 insertions(+) diff --git a/src/protocols/vnc/Makefile.am b/src/protocols/vnc/Makefile.am index 39b38e41..cd4a4366 100644 --- a/src/protocols/vnc/Makefile.am +++ b/src/protocols/vnc/Makefile.am @@ -46,6 +46,7 @@ endif libguac_client_vnc_la_CFLAGS = \ -Werror -Wall -pedantic -Iinclude \ @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ libguac_client_vnc_la_LDFLAGS = \ @@ -56,5 +57,6 @@ libguac_client_vnc_la_LDFLAGS = \ libguac_client_vnc_la_LIBADD = \ @COMMON_LTLIB@ \ + @COMMON_SSH_LTLIB@ \ @LIBGUAC_LTLIB@ diff --git a/src/protocols/vnc/client.c b/src/protocols/vnc/client.c index a36fb9a9..ce0bd55e 100644 --- a/src/protocols/vnc/client.c +++ b/src/protocols/vnc/client.c @@ -28,6 +28,8 @@ #include "guac_dot_cursor.h" #include "guac_handlers.h" #include "guac_pointer_cursor.h" +#include "guac_sftp.h" +#include "guac_ssh.h" #include "vnc_handlers.h" #ifdef ENABLE_PULSE @@ -71,6 +73,16 @@ const char* GUAC_CLIENT_ARGS[] = { "listen-timeout", #endif +#ifdef ENABLE_COMMON_SSH + "enable-sftp", + "sftp-hostname", + "sftp-port", + "sftp-username", + "sftp-password", + "sftp-private-key", + "sftp-passphrase", +#endif + NULL }; @@ -101,6 +113,16 @@ enum VNC_ARGS_IDX { IDX_LISTEN_TIMEOUT, #endif +#ifdef ENABLE_COMMON_SSH + IDX_ENABLE_SFTP, + IDX_SFTP_HOSTNAME, + IDX_SFTP_PORT, + IDX_SFTP_USERNAME, + IDX_SFTP_PASSWORD, + IDX_SFTP_PRIVATE_KEY, + IDX_SFTP_PASSPHRASE, +#endif + VNC_ARGS_COUNT }; @@ -337,6 +359,74 @@ int guac_client_init(guac_client* client, int argc, char** argv) { } /* end if audio enabled */ #endif +#ifdef ENABLE_COMMON_SSH + guac_common_ssh_init(client); + + /* Connect via SSH if SFTP is enabled */ + if (strcmp(argv[IDX_ENABLE_SFTP], "true") == 0) { + + guac_client_log(client, GUAC_LOG_DEBUG, + "Connecting via SSH for SFTP filesystem access."); + + guac_common_ssh_user* user = + guac_common_ssh_create_user(argv[IDX_SFTP_USERNAME]); + + /* Import private key, if given */ + if (argv[IDX_SFTP_PRIVATE_KEY][0] != '\0') { + + guac_client_log(client, GUAC_LOG_DEBUG, + "Authenticating with private key."); + + /* Abort if private key cannot be read */ + if (guac_common_ssh_user_import_key(user, + argv[IDX_SFTP_PRIVATE_KEY], + argv[IDX_SFTP_PASSPHRASE])) + return 1; + + } + + /* Otherwise, use specified password */ + else { + guac_client_log(client, GUAC_LOG_DEBUG, + "Authenticating with password."); + guac_common_ssh_user_set_password(user, argv[IDX_SFTP_PASSWORD]); + } + + /* Parse hostname - use VNC hostname by default */ + const char* sftp_hostname = argv[IDX_SFTP_HOSTNAME]; + if (sftp_hostname[0] == '\0') + sftp_hostname = guac_client_data->hostname; + + /* Parse port, defaulting to standard SSH port */ + const char* sftp_port = argv[IDX_SFTP_PORT]; + if (sftp_port[0] == '\0') + sftp_port = "22"; + + /* Attempt SSH connection */ + guac_common_ssh_session* session = + guac_common_ssh_create_session(client, sftp_hostname, sftp_port, + user); + + /* Fail if SSH connection does not succeed */ + if (session == NULL) { + /* Already aborted within guac_common_ssh_create_session() */ + return 1; + } + + /* Load and expose filesystem */ + guac_client_data->sftp_filesystem = + guac_common_ssh_create_sftp_filesystem(session, "/"); + + /* Abort if SFTP connection fails */ + if (guac_client_data->sftp_filesystem == NULL) + return 1; + + guac_client_log(client, GUAC_LOG_DEBUG, + "SFTP connection succeeded."); + + } +#endif + /* Set remaining client data */ guac_client_data->rfb_client = rfb_client; guac_client_data->copy_rect_used = 0; diff --git a/src/protocols/vnc/client.h b/src/protocols/vnc/client.h index 4c13b54e..7ad322dd 100644 --- a/src/protocols/vnc/client.h +++ b/src/protocols/vnc/client.h @@ -36,6 +36,10 @@ #include #endif +#ifdef ENABLE_COMMON_SSH +#include "guac_sftp.h" +#endif + /** * The maximum duration of a frame in milliseconds. */ @@ -186,6 +190,13 @@ typedef struct vnc_guac_client_data { */ guac_common_surface* default_surface; +#ifdef ENABLE_COMMON_SSH + /** + * The exposed filesystem object, implemented with SFTP. + */ + guac_object* sftp_filesystem; +#endif + } vnc_guac_client_data; #endif diff --git a/src/protocols/vnc/guac_handlers.c b/src/protocols/vnc/guac_handlers.c index e8fea8bd..92667628 100644 --- a/src/protocols/vnc/guac_handlers.c +++ b/src/protocols/vnc/guac_handlers.c @@ -31,6 +31,11 @@ #include #include +#ifdef ENABLE_COMMON_SSH +#include +#include +#endif + #ifdef ENABLE_PULSE #include "pulse.h" #endif @@ -135,6 +140,14 @@ int vnc_guac_client_free_handler(guac_client* client) { guac_pa_stop_stream(client); #endif +#ifdef ENABLE_COMMON_SSH + /* Free SFTP filesystem, if loaded */ + if (guac_client_data->sftp_filesystem) + guac_common_ssh_destroy_sftp_filesystem(guac_client_data->sftp_filesystem); + + guac_common_ssh_uninit(); +#endif + /* Free encodings string, if used */ if (guac_client_data->encodings != NULL) free(guac_client_data->encodings);