GUACAMOLE-527: Add host key and type settings.
This commit is contained in:
parent
171bae1f5c
commit
0d82cd1e6c
@ -98,7 +98,8 @@ void guac_common_ssh_uninit();
|
|||||||
* if the connection or authentication were not successful.
|
* if the connection or authentication were not successful.
|
||||||
*/
|
*/
|
||||||
guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
||||||
const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive);
|
const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive,
|
||||||
|
const char* host_key_type, const char* host_key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects and destroys the given SSH session, freeing all associated
|
* Disconnects and destroys the given SSH session, freeing all associated
|
||||||
|
@ -415,7 +415,8 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
||||||
const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive) {
|
const char* hostname, const char* port, guac_common_ssh_user* user, int keepalive,
|
||||||
|
const char* host_key_type, const char* host_key) {
|
||||||
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@ -511,44 +512,68 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check known_hosts */
|
/* Check known_hosts */
|
||||||
size_t len;
|
/* Get known hosts file from user running guacd */
|
||||||
int type;
|
|
||||||
struct passwd *pw = getpwuid(getuid());
|
struct passwd *pw = getpwuid(getuid());
|
||||||
char *homedir = pw->pw_dir;
|
char *homedir = pw->pw_dir;
|
||||||
char *known_hosts = strcat(homedir, "/.ssh/known_hosts");
|
char *known_hosts = strcat(homedir, "/.ssh/known_hosts");
|
||||||
LIBSSH2_KNOWNHOSTS *ssh_known_hosts = libssh2_knownhost_init(session);
|
LIBSSH2_KNOWNHOSTS *ssh_known_hosts = libssh2_knownhost_init(session);
|
||||||
|
|
||||||
libssh2_knownhost_readfile(ssh_known_hosts, known_hosts, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
|
libssh2_knownhost_readfile(ssh_known_hosts, known_hosts, LIBSSH2_KNOWNHOST_FILE_OPENSSH);
|
||||||
const char *fingerprint = libssh2_session_hostkey(session, &len, &type);
|
|
||||||
|
|
||||||
if (fingerprint) {
|
/* Add host key provided from settings */
|
||||||
struct libssh2_knownhost *host;
|
if (strcmp(host_key, "") > 0) {
|
||||||
int check = libssh2_knownhost_checkp(ssh_known_hosts, hostname, atoi(port),
|
|
||||||
fingerprint, len,
|
|
||||||
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
|
|
||||||
LIBSSH2_KNOWNHOST_KEYENC_RAW,
|
|
||||||
&host);
|
|
||||||
|
|
||||||
switch (check) {
|
int kh_key_type = 0;
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_MATCH:
|
if (strcmp(host_key_type, "ssh-rsa") == 0)
|
||||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
kh_key_type = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
|
||||||
"Host key match found.");
|
else if(strcmp(host_key_type, "ssh-dss") == 0)
|
||||||
break;
|
kh_key_type = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
|
else if(strcmp(host_key_type, "rsa1") == 0)
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
kh_key_type = LIBSSH2_KNOWNHOST_KEY_RSA1;
|
||||||
"Host key not found in known hosts file.");
|
else
|
||||||
break;
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
|
"Invalid SSH host key type %s", host_key_type);
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
|
||||||
"Host key does not match host entry.");
|
|
||||||
break;
|
|
||||||
case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
|
|
||||||
default:
|
|
||||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
|
||||||
"Host could not be checked against known hosts.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (libssh2_knownhost_addc(ssh_known_hosts, hostname, NULL, host_key, strlen(host_key),
|
||||||
|
NULL, 0, LIBSSH2_KNOWNHOST_TYPE_PLAIN|LIBSSH2_KNOWNHOST_KEYENC_BASE64|
|
||||||
|
kh_key_type, NULL))
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Failed to add host key to known hosts store for %s", hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get fingerprint of host we're connecting to */
|
||||||
|
size_t fp_len;
|
||||||
|
int fp_type;
|
||||||
|
const char *fingerprint = libssh2_session_hostkey(session, &fp_len, &fp_type);
|
||||||
|
|
||||||
|
if (!fingerprint || strcmp(fingerprint, "") == 0) {
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Could not retrieve fingerprint of SSH server %s", hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libssh2_knownhost *host;
|
||||||
|
int kh_check = libssh2_knownhost_checkp(ssh_known_hosts, hostname, atoi(port),
|
||||||
|
fingerprint, fp_len,
|
||||||
|
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
|
||||||
|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
|
||||||
|
&host);
|
||||||
|
|
||||||
|
switch (kh_check) {
|
||||||
|
case LIBSSH2_KNOWNHOST_CHECK_MATCH:
|
||||||
|
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||||
|
"Host key match found.");
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND:
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Host key not found in known hosts file.");
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_CHECK_MISMATCH:
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Host key does not match host entry.");
|
||||||
|
break;
|
||||||
|
case LIBSSH2_KNOWNHOST_CHECK_FAILURE:
|
||||||
|
default:
|
||||||
|
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||||
|
"Host could not be checked against known hosts.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform handshake */
|
/* Perform handshake */
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
/* Client plugin arguments */
|
/* Client plugin arguments */
|
||||||
const char* GUAC_SSH_CLIENT_ARGS[] = {
|
const char* GUAC_SSH_CLIENT_ARGS[] = {
|
||||||
"hostname",
|
"hostname",
|
||||||
|
"host_key_type",
|
||||||
|
"host_key",
|
||||||
"port",
|
"port",
|
||||||
"username",
|
"username",
|
||||||
"password",
|
"password",
|
||||||
@ -68,6 +70,16 @@ enum SSH_ARGS_IDX {
|
|||||||
*/
|
*/
|
||||||
IDX_HOSTNAME,
|
IDX_HOSTNAME,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of public SSH host key provided. Optional.
|
||||||
|
*/
|
||||||
|
IDX_HOST_KEY_TYPE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Base64-encoded public SSH host key. Optional.
|
||||||
|
*/
|
||||||
|
IDX_HOST_KEY,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The port to connect to. Optional.
|
* The port to connect to. Optional.
|
||||||
*/
|
*/
|
||||||
@ -247,6 +259,14 @@ guac_ssh_settings* guac_ssh_parse_args(guac_user* user,
|
|||||||
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
IDX_HOSTNAME, "");
|
IDX_HOSTNAME, "");
|
||||||
|
|
||||||
|
settings->host_key_type =
|
||||||
|
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
|
IDX_HOST_KEY_TYPE, "ssh-rsa");
|
||||||
|
|
||||||
|
settings->host_key =
|
||||||
|
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
|
IDX_HOST_KEY, NULL);
|
||||||
|
|
||||||
settings->username =
|
settings->username =
|
||||||
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
guac_user_parse_args_string(user, GUAC_SSH_CLIENT_ARGS, argv,
|
||||||
IDX_USERNAME, NULL);
|
IDX_USERNAME, NULL);
|
||||||
@ -384,6 +404,8 @@ void guac_ssh_settings_free(guac_ssh_settings* settings) {
|
|||||||
|
|
||||||
/* Free network connection information */
|
/* Free network connection information */
|
||||||
free(settings->hostname);
|
free(settings->hostname);
|
||||||
|
free(settings->host_key_type);
|
||||||
|
free(settings->host_key);
|
||||||
free(settings->port);
|
free(settings->port);
|
||||||
|
|
||||||
/* Free credentials */
|
/* Free credentials */
|
||||||
|
@ -70,6 +70,16 @@ typedef struct guac_ssh_settings {
|
|||||||
*/
|
*/
|
||||||
char* hostname;
|
char* hostname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of public SSH host key.
|
||||||
|
*/
|
||||||
|
char* host_key_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public SSH host key.
|
||||||
|
*/
|
||||||
|
char* host_key;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The port of the SSH server to connect to.
|
* The port of the SSH server to connect to.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user