diff --git a/src/protocols/rdp/Makefile.am b/src/protocols/rdp/Makefile.am index d67c9976..327cadea 100644 --- a/src/protocols/rdp/Makefile.am +++ b/src/protocols/rdp/Makefile.am @@ -119,6 +119,7 @@ endif libguac_client_rdp_la_CFLAGS = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ libguac_client_rdp_la_LDFLAGS = \ @@ -129,6 +130,7 @@ libguac_client_rdp_la_LDFLAGS = \ libguac_client_rdp_la_LIBADD = \ @COMMON_LTLIB@ \ + @COMMON_SSH_LTLIB@ \ @LIBGUAC_LTLIB@ # @@ -138,6 +140,7 @@ libguac_client_rdp_la_LIBADD = \ guacdr_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ guacdr_ldflags = \ @@ -156,6 +159,7 @@ guacdr_libadd = \ guacsnd_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ guacsnd_ldflags = \ @@ -174,6 +178,7 @@ guacsnd_libadd = \ guacsvc_cflags = \ -Werror -Wall -Iinclude \ @COMMON_INCLUDE@ \ + @COMMON_SSH_INCLUDE@ \ @LIBGUAC_INCLUDE@ guacsvc_ldflags = \ diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index b0966403..cf1b3295 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -122,6 +122,17 @@ const char* GUAC_CLIENT_ARGS[] = { "enable-full-window-drag", "enable-desktop-composition", "enable-menu-animations", + +#ifdef ENABLE_COMMON_SSH + "enable-sftp", + "sftp-hostname", + "sftp-port", + "sftp-username", + "sftp-password", + "sftp-private-key", + "sftp-passphrase", +#endif + NULL }; @@ -158,6 +169,17 @@ enum RDP_ARGS_IDX { IDX_ENABLE_FULL_WINDOW_DRAG, IDX_ENABLE_DESKTOP_COMPOSITION, IDX_ENABLE_MENU_ANIMATIONS, + +#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 + RDP_ARGS_COUNT }; @@ -789,6 +811,86 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Load keymap into client */ __guac_rdp_client_load_keymap(client, settings->server_layout); +#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."); + + /* Parse username - use RDP username by default */ + const char* sftp_username = argv[IDX_SFTP_USERNAME]; + if (sftp_username[0] == '\0') + sftp_username = settings->username; + + guac_common_ssh_user* user = guac_common_ssh_create_user(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."); + + /* Parse password - use RDP password by default */ + const char* sftp_password = argv[IDX_SFTP_USERNAME]; + if (sftp_password[0] == '\0') + sftp_password = settings->password; + + guac_common_ssh_user_set_password(user, sftp_password); + + } + + /* Parse hostname - use RDP hostname by default */ + const char* sftp_hostname = argv[IDX_SFTP_HOSTNAME]; + if (sftp_hostname[0] == '\0') + sftp_hostname = settings->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 + /* Create default surface */ guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, settings->width, settings->height); diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 349c88a5..b23f8e79 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -33,6 +33,10 @@ #include "rdp_keymap.h" #include "rdp_settings.h" +#ifdef ENABLE_COMMON_SSH +#include "guac_sftp.h" +#endif + #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT #include "rdp_disp.h" #endif @@ -157,6 +161,13 @@ typedef struct rdp_guac_client_data { */ guac_rdp_fs* filesystem; +#ifdef ENABLE_COMMON_SSH + /** + * The exposed filesystem object, implemented with SFTP. + */ + guac_object* sftp_filesystem; +#endif + #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /** * Display size update module. diff --git a/src/protocols/rdp/guac_handlers.c b/src/protocols/rdp/guac_handlers.c index 4693a4fd..a660f34e 100644 --- a/src/protocols/rdp/guac_handlers.c +++ b/src/protocols/rdp/guac_handlers.c @@ -33,6 +33,11 @@ #include "rdp_rail.h" #include "rdp_stream.h" +#ifdef ENABLE_COMMON_SSH +#include +#include +#endif + #include #include #include @@ -89,6 +94,14 @@ int rdp_guac_client_free_handler(guac_client* client) { if (guac_client_data->filesystem != NULL) guac_rdp_fs_free(guac_client_data->filesystem); +#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 + #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT /* Free display update module */ guac_rdp_disp_free(guac_client_data->disp);