[WIP] Add SSH tunneling settings for Telnet.
This commit is contained in:
parent
8394ef0ed6
commit
ad751f109a
@ -50,11 +50,13 @@ noinst_HEADERS = \
|
|||||||
|
|
||||||
libguac_client_telnet_la_CFLAGS = \
|
libguac_client_telnet_la_CFLAGS = \
|
||||||
-Werror -Wall -Iinclude \
|
-Werror -Wall -Iinclude \
|
||||||
|
@COMMON_SSH_INCLUDE@ \
|
||||||
@LIBGUAC_INCLUDE@ \
|
@LIBGUAC_INCLUDE@ \
|
||||||
@TERMINAL_INCLUDE@
|
@TERMINAL_INCLUDE@
|
||||||
|
|
||||||
libguac_client_telnet_la_LIBADD = \
|
libguac_client_telnet_la_LIBADD = \
|
||||||
@COMMON_LTLIB@ \
|
@COMMON_LTLIB@ \
|
||||||
|
@COMMON_SSH_LTLIB@ \
|
||||||
@LIBGUAC_LTLIB@ \
|
@LIBGUAC_LTLIB@ \
|
||||||
@TERMINAL_LTLIB@
|
@TERMINAL_LTLIB@
|
||||||
|
|
||||||
|
@ -24,6 +24,13 @@
|
|||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
#include "common-ssh/sftp.h"
|
||||||
|
#include "common-ssh/ssh.h"
|
||||||
|
#include "common-ssh/tunnel.h"
|
||||||
|
#include "common-ssh/user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -54,6 +61,10 @@ int guac_client_init(guac_client* client) {
|
|||||||
client->free_handler = guac_telnet_client_free_handler;
|
client->free_handler = guac_telnet_client_free_handler;
|
||||||
client->leave_handler = guac_telnet_user_leave_handler;
|
client->leave_handler = guac_telnet_user_leave_handler;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
guac_common_ssh_init(client);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Register handlers for argument values that may be sent after the handshake */
|
/* Register handlers for argument values that may be sent after the handshake */
|
||||||
guac_argv_register(GUAC_TELNET_ARGV_COLOR_SCHEME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
|
guac_argv_register(GUAC_TELNET_ARGV_COLOR_SCHEME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
|
||||||
guac_argv_register(GUAC_TELNET_ARGV_FONT_NAME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
|
guac_argv_register(GUAC_TELNET_ARGV_FONT_NAME, guac_telnet_argv_callback, NULL, GUAC_ARGV_OPTION_ECHO);
|
||||||
@ -93,6 +104,25 @@ int guac_telnet_client_free_handler(guac_client* client) {
|
|||||||
telnet_free(telnet_client->telnet);
|
telnet_free(telnet_client->telnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
/* Free SFTP filesystem, if loaded */
|
||||||
|
if (telnet_client->sftp_filesystem)
|
||||||
|
guac_common_ssh_destroy_sftp_filesystem(telnet_client->sftp_filesystem);
|
||||||
|
|
||||||
|
/* Free SFTP session */
|
||||||
|
if (telnet_client->sftp_session)
|
||||||
|
guac_common_ssh_destroy_session(telnet_client->sftp_session);
|
||||||
|
|
||||||
|
/* Free SFTP user */
|
||||||
|
if (telnet_client->sftp_user)
|
||||||
|
guac_common_ssh_destroy_user(telnet_client->sftp_user);
|
||||||
|
|
||||||
|
if (telnet_client->ssh_tunnel)
|
||||||
|
guac_common_ssh_tunnel_cleanup(telnet_client->ssh_tunnel);
|
||||||
|
|
||||||
|
guac_common_ssh_uninit();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Free settings */
|
/* Free settings */
|
||||||
if (telnet_client->settings != NULL)
|
if (telnet_client->settings != NULL)
|
||||||
guac_telnet_settings_free(telnet_client->settings);
|
guac_telnet_settings_free(telnet_client->settings);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "argv.h"
|
#include "argv.h"
|
||||||
#include "common/defaults.h"
|
#include "common/defaults.h"
|
||||||
|
#include "common-ssh/ssh-constants.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "terminal/terminal.h"
|
#include "terminal/terminal.h"
|
||||||
|
|
||||||
@ -66,6 +67,32 @@ const char* GUAC_TELNET_CLIENT_ARGS[] = {
|
|||||||
"wol-broadcast-addr",
|
"wol-broadcast-addr",
|
||||||
"wol-udp-port",
|
"wol-udp-port",
|
||||||
"wol-wait-time",
|
"wol-wait-time",
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
"enable-sftp",
|
||||||
|
"sftp-hostname",
|
||||||
|
"sftp-host-key",
|
||||||
|
"sftp-port",
|
||||||
|
"sftp-username",
|
||||||
|
"sftp-password",
|
||||||
|
"sftp-private-key",
|
||||||
|
"sftp-passphrase",
|
||||||
|
"sftp-directory",
|
||||||
|
"sftp-root-directory",
|
||||||
|
"sftp-server-alive-interval",
|
||||||
|
"sftp-disable-download",
|
||||||
|
"sftp-disable-upload",
|
||||||
|
"ssh-tunnel",
|
||||||
|
"ssh-tunnel-host",
|
||||||
|
"ssh-tunnel-port",
|
||||||
|
"ssh-tunnel-host-key",
|
||||||
|
"ssh-tunnel-username",
|
||||||
|
"ssh-tunnel-password",
|
||||||
|
"ssh-tunnel-private-key",
|
||||||
|
"ssh-tunnel-passphrase",
|
||||||
|
"ssh-tunnel-alive-interval",
|
||||||
|
#endif
|
||||||
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -272,6 +299,137 @@ enum TELNET_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_WOL_WAIT_TIME,
|
IDX_WOL_WAIT_TIME,
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
/**
|
||||||
|
* "true" if SFTP should be enabled for the connection, "false" or
|
||||||
|
* blank otherwise.
|
||||||
|
*/
|
||||||
|
IDX_ENABLE_SFTP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hostname of the SSH server to connect to for SFTP. If blank, the
|
||||||
|
* hostname of the telnet server will be used.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_HOSTNAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public SSH host key to identify the SFTP server.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_HOST_KEY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port of the SSH server to connect to for SFTP. If blank, the default
|
||||||
|
* SSH port of "22" will be used.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_PORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username to provide when authenticating with the SSH server for
|
||||||
|
* SFTP.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_USERNAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password to provide when authenticating with the SSH server for
|
||||||
|
* SFTP (if not using a private key).
|
||||||
|
*/
|
||||||
|
IDX_SFTP_PASSWORD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base64-encoded private key to use when authenticating with the SSH
|
||||||
|
* server for SFTP (if not using a password).
|
||||||
|
*/
|
||||||
|
IDX_SFTP_PRIVATE_KEY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The passphrase to use to decrypt the provided base64-encoded private
|
||||||
|
* key.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_PASSPHRASE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default location for file uploads within the SSH server. This will
|
||||||
|
* apply only to uploads which do not use the filesystem guac_object (where
|
||||||
|
* the destination directory is otherwise ambiguous).
|
||||||
|
*/
|
||||||
|
IDX_SFTP_DIRECTORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object. If omitted, "/" will be used by default.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
|
* of 1 is automatically incremented to 2 by libssh2 to avoid busy loop corner
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_SERVER_ALIVE_INTERVAL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to "true", file downloads over SFTP will be blocked. If set to
|
||||||
|
* "false" or not set, file downloads will be allowed.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_DISABLE_DOWNLOAD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to "true", file uploads over SFTP will be blocked. If set to
|
||||||
|
* "false" or not set, file uploads will be allowed.
|
||||||
|
*/
|
||||||
|
IDX_SFTP_DISABLE_UPLOAD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if SSH tunneling should be enabled. If false or not set, SSH
|
||||||
|
* tunneling will not be used.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hostname or IP address of the SSH server to use for tunneling.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_HOST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TCP port of the SSH server to use for tunneling.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_PORT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If host key checking should be done, the public key of the SSH host
|
||||||
|
* to be used for tunneling.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_HOST_KEY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username for authenticating to the SSH hsot for tunneling.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_USERNAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password to use to authenticate to the SSH host for tunneling.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_PASSWORD,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The private key to use to authenticate to the SSH host for tunneling,
|
||||||
|
* as an alternative to password-based authentication.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_PRIVATE_KEY,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The passphrase to use to decrypt the private key.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_PASSPHRASE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval at which keepalive packets should be sent to the SSH
|
||||||
|
* tunneling server, or zero if keepalive should be disabled.
|
||||||
|
*/
|
||||||
|
IDX_SSH_TUNNEL_ALIVE_INTERVAL,
|
||||||
|
#endif
|
||||||
|
|
||||||
TELNET_ARGS_COUNT
|
TELNET_ARGS_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -530,6 +688,118 @@ guac_telnet_settings* guac_telnet_parse_args(guac_user* user,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
/* SFTP enable/disable */
|
||||||
|
settings->enable_sftp =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_ENABLE_SFTP, false);
|
||||||
|
|
||||||
|
/* If SFTP is not enabled, no reason to parse the rest. */
|
||||||
|
if (settings->enable_sftp) {
|
||||||
|
/* Hostname for SFTP connection */
|
||||||
|
settings->sftp_hostname =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_HOSTNAME, settings->hostname);
|
||||||
|
|
||||||
|
/* The public SSH host key. */
|
||||||
|
settings->sftp_host_key =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_HOST_KEY, NULL);
|
||||||
|
|
||||||
|
/* Port for SFTP connection */
|
||||||
|
settings->sftp_port =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_PORT, "22");
|
||||||
|
|
||||||
|
/* Username for SSH/SFTP authentication */
|
||||||
|
settings->sftp_username =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_USERNAME, "");
|
||||||
|
|
||||||
|
/* Password for SFTP (if not using private key) */
|
||||||
|
settings->sftp_password =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_PASSWORD, "");
|
||||||
|
|
||||||
|
/* Private key for SFTP (if not using password) */
|
||||||
|
settings->sftp_private_key =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_PRIVATE_KEY, NULL);
|
||||||
|
|
||||||
|
/* Passphrase for decrypting the SFTP private key (if applicable */
|
||||||
|
settings->sftp_passphrase =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_PASSPHRASE, "");
|
||||||
|
|
||||||
|
/* Default upload directory */
|
||||||
|
settings->sftp_directory =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_DIRECTORY, NULL);
|
||||||
|
|
||||||
|
/* SFTP root directory */
|
||||||
|
settings->sftp_root_directory =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_ROOT_DIRECTORY, GUAC_COMMON_SSH_SFTP_DEFAULT_ROOT);
|
||||||
|
|
||||||
|
/* Default keepalive value */
|
||||||
|
settings->sftp_server_alive_interval =
|
||||||
|
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_SERVER_ALIVE_INTERVAL,
|
||||||
|
GUAC_COMMON_SSH_DEFAULT_ALIVE_INTERVAL);
|
||||||
|
|
||||||
|
settings->sftp_disable_download =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_DISABLE_DOWNLOAD, false);
|
||||||
|
|
||||||
|
settings->sftp_disable_upload =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SFTP_DISABLE_UPLOAD, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse SSH tunneling. */
|
||||||
|
settings->ssh_tunnel =
|
||||||
|
guac_user_parse_args_boolean(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL, false);
|
||||||
|
|
||||||
|
/* Only parse remaining tunneling settings if it has been enabled. */
|
||||||
|
if (settings->ssh_tunnel) {
|
||||||
|
|
||||||
|
settings->ssh_tunnel_host =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_HOST, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_port =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_PORT, GUAC_COMMON_SSH_DEFAULT_PORT);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_host_key =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_HOST_KEY, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_username =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_USERNAME, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_password =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_PASSWORD, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_private_key =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_PRIVATE_KEY, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_passphrase =
|
||||||
|
guac_user_parse_args_string(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_PASSPHRASE, NULL);
|
||||||
|
|
||||||
|
settings->ssh_tunnel_alive_interval =
|
||||||
|
guac_user_parse_args_int(user, GUAC_TELNET_CLIENT_ARGS, argv,
|
||||||
|
IDX_SSH_TUNNEL_ALIVE_INTERVAL,
|
||||||
|
GUAC_COMMON_SSH_DEFAULT_ALIVE_INTERVAL);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Parsing was successful */
|
/* Parsing was successful */
|
||||||
return settings;
|
return settings;
|
||||||
|
|
||||||
@ -570,6 +840,23 @@ void guac_telnet_settings_free(guac_telnet_settings* settings) {
|
|||||||
free(settings->wol_mac_addr);
|
free(settings->wol_mac_addr);
|
||||||
free(settings->wol_broadcast_addr);
|
free(settings->wol_broadcast_addr);
|
||||||
|
|
||||||
|
/* Free SSH and SFTP settings. */
|
||||||
|
free(settings->sftp_hostname);
|
||||||
|
free(settings->sftp_host_key);
|
||||||
|
free(settings->sftp_username);
|
||||||
|
free(settings->sftp_password);
|
||||||
|
free(settings->sftp_private_key);
|
||||||
|
free(settings->sftp_passphrase);
|
||||||
|
free(settings->sftp_directory);
|
||||||
|
free(settings->sftp_root_directory);
|
||||||
|
free(settings->ssh_tunnel_host);
|
||||||
|
free(settings->ssh_tunnel_host_key);
|
||||||
|
free(settings->ssh_tunnel_port);
|
||||||
|
free(settings->ssh_tunnel_username);
|
||||||
|
free(settings->ssh_tunnel_password);
|
||||||
|
free(settings->ssh_tunnel_private_key);
|
||||||
|
free(settings->ssh_tunnel_passphrase);
|
||||||
|
|
||||||
/* Free overall structure */
|
/* Free overall structure */
|
||||||
free(settings);
|
free(settings);
|
||||||
|
|
||||||
|
@ -269,6 +269,150 @@ typedef struct guac_telnet_settings {
|
|||||||
*/
|
*/
|
||||||
int wol_wait_time;
|
int wol_wait_time;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
/**
|
||||||
|
* Whether SFTP should be enabled for the VNC connection.
|
||||||
|
*/
|
||||||
|
bool enable_sftp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hostname of the SSH server to connect to for SFTP.
|
||||||
|
*/
|
||||||
|
char* sftp_hostname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public SSH host key.
|
||||||
|
*/
|
||||||
|
char* sftp_host_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port of the SSH server to connect to for SFTP.
|
||||||
|
*/
|
||||||
|
char* sftp_port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username to provide when authenticating with the SSH server for
|
||||||
|
* SFTP.
|
||||||
|
*/
|
||||||
|
char* sftp_username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password to provide when authenticating with the SSH server for
|
||||||
|
* SFTP (if not using a private key).
|
||||||
|
*/
|
||||||
|
char* sftp_password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base64-encoded private key to use when authenticating with the SSH
|
||||||
|
* server for SFTP (if not using a password).
|
||||||
|
*/
|
||||||
|
char* sftp_private_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The passphrase to use to decrypt the provided base64-encoded private
|
||||||
|
* key.
|
||||||
|
*/
|
||||||
|
char* sftp_passphrase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default location for file uploads within the SSH server. This will
|
||||||
|
* apply only to uploads which do not use the filesystem guac_object (where
|
||||||
|
* the destination directory is otherwise ambiguous).
|
||||||
|
*/
|
||||||
|
char* sftp_directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the directory within the SSH server to expose as a
|
||||||
|
* filesystem guac_object.
|
||||||
|
*/
|
||||||
|
char* sftp_root_directory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval at which SSH keepalive messages are sent to the server for
|
||||||
|
* SFTP connections. The default is 0 (disabling keepalives), and a value
|
||||||
|
* of 1 is automatically increased to 2 by libssh2 to avoid busy loop corner
|
||||||
|
* cases.
|
||||||
|
*/
|
||||||
|
int sftp_server_alive_interval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether file downloads over SFTP should be blocked. If set to "true",
|
||||||
|
* the local client will not be able to download files from the SFTP server.
|
||||||
|
* If set to "false" or not set, file downloads will be allowed.
|
||||||
|
*/
|
||||||
|
bool sftp_disable_download;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether file uploads over SFTP should be blocked. If set to "true", the
|
||||||
|
* local client will not be able to upload files to the SFTP server. If set
|
||||||
|
* to "false" or not set, file uploads will be allowed.
|
||||||
|
*/
|
||||||
|
bool sftp_disable_upload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to enable tunneling of this connection through the specified
|
||||||
|
* SSH server. If set to "true", guacd will attempt to connect to the SSH
|
||||||
|
* server and tunnel all of the traffic through the SSH connection. If
|
||||||
|
* set to "false" or not set, SSH tunneling will not be used.
|
||||||
|
*/
|
||||||
|
bool ssh_tunnel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hostname or address of the host through which traffic should be
|
||||||
|
* tunneled over SSH. If tunneling is enabled, this is required, or the
|
||||||
|
* connection will be aborted.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The port on which to connect to the SSH server to tunnel traffic, if
|
||||||
|
* SSH tunneling is enabled. If not specified, this will default to 22, the
|
||||||
|
* normal SSH port.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_port;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public key of the SSH host through which this connection will be
|
||||||
|
* tunneled. If unset, no host key checking will be done and the connection
|
||||||
|
* will be attempted regardless of the identity of the remote host.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_host_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username to use when connecting to the SSH host to tunnel traffic.
|
||||||
|
* This is required if SSH tunneling is enabled.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The password to use when connecting to the SSH host to tunnel traffic,
|
||||||
|
* if password authentication is used.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The private key to use to authenticate to the SSH server to tunnel traffic,
|
||||||
|
* if key-based authentication is used.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_private_key;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The passphrase of the private key to use to decrypt the private key when
|
||||||
|
* using key-based authentication, if the key is encrypted.
|
||||||
|
*/
|
||||||
|
char* ssh_tunnel_passphrase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interval at which keepalive messages will be sent to the SSH server
|
||||||
|
* over which the connection is being tunneled. The default is 0, meaning
|
||||||
|
* that keepalive messages will be disabled. The minimum value is 2 to avoid
|
||||||
|
* busy loop scenarios, and a value of 1 is automatically increased to 2 by
|
||||||
|
* the underlying libssh2 implementation.
|
||||||
|
*/
|
||||||
|
int ssh_tunnel_alive_interval;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} guac_telnet_settings;
|
} guac_telnet_settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <guacamole/client.h>
|
#include <guacamole/client.h>
|
||||||
#include <guacamole/protocol.h>
|
#include <guacamole/protocol.h>
|
||||||
#include <guacamole/recording.h>
|
#include <guacamole/recording.h>
|
||||||
|
#include <guacamole/string.h>
|
||||||
#include <guacamole/timestamp.h>
|
#include <guacamole/timestamp.h>
|
||||||
#include <guacamole/wol.h>
|
#include <guacamole/wol.h>
|
||||||
#include <libtelnet.h>
|
#include <libtelnet.h>
|
||||||
@ -40,6 +41,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,69 +394,184 @@ static telnet_t* __guac_telnet_create_session(guac_client* client) {
|
|||||||
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
|
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
|
||||||
guac_telnet_settings* settings = telnet_client->settings;
|
guac_telnet_settings* settings = telnet_client->settings;
|
||||||
|
|
||||||
struct addrinfo hints = {
|
if (settings->ssh_tunnel) {
|
||||||
.ai_family = AF_UNSPEC,
|
|
||||||
.ai_socktype = SOCK_STREAM,
|
|
||||||
.ai_protocol = IPPROTO_TCP
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Get socket */
|
/* Allocate memory for the SSH tunnel data. */
|
||||||
fd = socket(AF_INET, SOCK_STREAM, 0);
|
telnet_client->ssh_tunnel = malloc(sizeof(guac_ssh_tunnel));
|
||||||
|
|
||||||
/* Get addresses connection */
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
if ((retval = getaddrinfo(settings->hostname, settings->port,
|
"SSH tunneling is enabled, connecting via SSH.");
|
||||||
&hints, &addresses))) {
|
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error parsing given address or port: %s",
|
|
||||||
gai_strerror(retval));
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
}
|
/* Associate the guac_client object with the tunnel. */
|
||||||
|
telnet_client->ssh_tunnel->client = client;
|
||||||
|
|
||||||
/* Attempt connection to each address until success */
|
/* Abort if tunnel username is missing */
|
||||||
current_address = addresses;
|
if (settings->ssh_tunnel_username == NULL) {
|
||||||
while (current_address != NULL) {
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"An SSH tunnel-specific username is required if "
|
||||||
|
"SSH tunneling is enabled.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int retval;
|
telnet_client->ssh_tunnel->user =
|
||||||
|
guac_common_ssh_create_user(settings->ssh_tunnel_username);
|
||||||
|
|
||||||
/* Resolve hostname */
|
/* Import SSH tunnel private key, if given */
|
||||||
if ((retval = getnameinfo(current_address->ai_addr,
|
if (settings->ssh_tunnel_private_key != NULL) {
|
||||||
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 */
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
if (connect(fd, current_address->ai_addr,
|
"Authenticating SSH tunnel with private key.");
|
||||||
current_address->ai_addrlen) == 0) {
|
|
||||||
|
|
||||||
guac_client_log(client, GUAC_LOG_DEBUG, "Successfully connected to "
|
/* Abort if SSH tunnel private key cannot be read */
|
||||||
"host %s, port %s", connected_address, connected_port);
|
if (guac_common_ssh_user_import_key(telnet_client->ssh_tunnel->user,
|
||||||
|
settings->ssh_tunnel_private_key,
|
||||||
/* Done if successful connect */
|
settings->ssh_tunnel_passphrase)) {
|
||||||
break;
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"SSH tunnel private key unreadable.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Otherwise log information regarding bind failure */
|
/* Otherwise, use specified SSH tunnel password */
|
||||||
else
|
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;
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"Authenticating SSH tunnel with password.");
|
||||||
|
|
||||||
|
guac_common_ssh_user_set_password(telnet_client->ssh_tunnel->user,
|
||||||
|
settings->ssh_tunnel_password);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt SSH tunnel connection */
|
||||||
|
telnet_client->ssh_tunnel->session =
|
||||||
|
guac_common_ssh_create_session(client, settings->ssh_tunnel_host,
|
||||||
|
settings->ssh_tunnel_port, telnet_client->ssh_tunnel->user,
|
||||||
|
settings->ssh_tunnel_alive_interval,
|
||||||
|
settings->ssh_tunnel_host_key, NULL);
|
||||||
|
|
||||||
|
/* Fail if SSH tunnel connection does not succeed */
|
||||||
|
if (telnet_client->ssh_tunnel->session == NULL) {
|
||||||
|
/* Already aborted within guac_common_ssh_create_session() */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"SSH session created for tunneling, initializing the tunnel.");
|
||||||
|
|
||||||
|
/* Initialize the tunnel or fail. */
|
||||||
|
if (guac_common_ssh_tunnel_init(telnet_client->ssh_tunnel,
|
||||||
|
settings->hostname, strtol(settings->port, NULL, 10))) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Unable to initialize SSH tunnel, aborting connection.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If tunnel socket is not returned, bail out. */
|
||||||
|
if (telnet_client->ssh_tunnel->socket_path == NULL) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Unable to obtain socket for SSH tunnel, aborting.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overwrite the hostname with the path to the socket and zero out port. */
|
||||||
|
settings->hostname = guac_strdup(telnet_client->ssh_tunnel->socket_path);
|
||||||
|
settings->port = 0;
|
||||||
|
|
||||||
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"SSH tunnel connection succeeded.");
|
||||||
|
|
||||||
|
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
if (fd < 0) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Error opening UNIX socket for telnet connection: %s",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_un socket_addr = {
|
||||||
|
.sun_family = AF_UNIX
|
||||||
|
};
|
||||||
|
strncpy(socket_addr.sun_path, telnet_client->ssh_tunnel->socket_path,
|
||||||
|
sizeof(socket_addr.sun_path) - 1);
|
||||||
|
|
||||||
|
if (connect(fd, (const struct sockaddr *) &socket_addr, sizeof(struct sockaddr_un))) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Error connecting to UNIX socket for SSH tunnel: %s",
|
||||||
|
telnet_client->ssh_tunnel->socket_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If unable to connect to anything, fail */
|
/* SSH tunneling is not in use, so open the standard TCP socket. */
|
||||||
if (current_address == NULL) {
|
else {
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
struct addrinfo hints = {
|
||||||
"Unable to connect to any addresses.");
|
.ai_family = AF_UNSPEC,
|
||||||
return NULL;
|
.ai_socktype = SOCK_STREAM,
|
||||||
}
|
.ai_protocol = IPPROTO_TCP
|
||||||
|
};
|
||||||
|
|
||||||
/* Free addrinfo */
|
/* Get socket */
|
||||||
freeaddrinfo(addresses);
|
fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
||||||
|
/* Get addresses connection */
|
||||||
|
if ((retval = getaddrinfo(settings->hostname, settings->port,
|
||||||
|
&hints, &addresses))) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error parsing given address or port: %s",
|
||||||
|
gai_strerror(retval));
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt connection to each address until success */
|
||||||
|
current_address = addresses;
|
||||||
|
while (current_address != NULL) {
|
||||||
|
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If unable to connect to anything, fail */
|
||||||
|
if (current_address == NULL) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_NOT_FOUND,
|
||||||
|
"Unable to connect to any addresses.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free addrinfo */
|
||||||
|
freeaddrinfo(addresses);
|
||||||
|
}
|
||||||
|
|
||||||
/* Open telnet session */
|
/* Open telnet session */
|
||||||
telnet_t* telnet = telnet_init(__telnet_options, __guac_telnet_event_handler, 0, client);
|
telnet_t* telnet = telnet_init(__telnet_options, __guac_telnet_event_handler, 0, client);
|
||||||
|
@ -24,6 +24,13 @@
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "terminal/terminal.h"
|
#include "terminal/terminal.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
#include "common-ssh/sftp.h"
|
||||||
|
#include "common-ssh/ssh.h"
|
||||||
|
#include "common-ssh/tunnel.h"
|
||||||
|
#include "common-ssh/user.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <guacamole/recording.h>
|
#include <guacamole/recording.h>
|
||||||
#include <libtelnet.h>
|
#include <libtelnet.h>
|
||||||
|
|
||||||
@ -77,6 +84,29 @@ typedef struct guac_telnet_client {
|
|||||||
*/
|
*/
|
||||||
guac_recording* recording;
|
guac_recording* recording;
|
||||||
|
|
||||||
|
#ifdef ENABLE_COMMON_SSH
|
||||||
|
/**
|
||||||
|
* The user and credentials used to authenticate for SFTP.
|
||||||
|
*/
|
||||||
|
guac_common_ssh_user* sftp_user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SSH session used for SFTP.
|
||||||
|
*/
|
||||||
|
guac_common_ssh_session* sftp_session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An SFTP-based filesystem.
|
||||||
|
*/
|
||||||
|
guac_common_ssh_sftp_filesystem* sftp_filesystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SSH tunnel data.
|
||||||
|
*/
|
||||||
|
guac_ssh_tunnel* ssh_tunnel;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
} guac_telnet_client;
|
} guac_telnet_client;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user