GUACAMOLE-547: Use a call-back function for getting the password.

This commit is contained in:
Nick Couchman 2018-12-27 01:01:06 -05:00
parent 4641da06ac
commit 3d15454097
5 changed files with 35 additions and 28 deletions

View File

@ -25,6 +25,11 @@
#include <guacamole/client.h> #include <guacamole/client.h>
#include <libssh2.h> #include <libssh2.h>
/**
* Handler for retrieving additional credentials.
*/
typedef char* guac_ssh_credential_handler(guac_client* client, char* credName);
/** /**
* An SSH session, backed by libssh2 and associated with a particular * An SSH session, backed by libssh2 and associated with a particular
* Guacamole client. * Guacamole client.
@ -51,6 +56,11 @@ typedef struct guac_common_ssh_session {
*/ */
int fd; int fd;
/**
* Callback function to retrieve credentials.
*/
guac_ssh_credential_handler* credential_handler;
} guac_common_ssh_session; } guac_common_ssh_session;
/** /**
@ -99,7 +109,7 @@ void guac_common_ssh_uninit();
*/ */
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); const char* host_key, guac_ssh_credential_handler* credential_callback);
/** /**
* Disconnects and destroys the given SSH session, freeing all associated * Disconnects and destroys the given SSH session, freeing all associated

View File

@ -304,20 +304,18 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
LIBSSH2_SESSION* session = common_session->session; LIBSSH2_SESSION* session = common_session->session;
/* Get user credentials */ /* Get user credentials */
char* username = user->username;
char* password = user->password;
guac_common_ssh_key* key = user->private_key; guac_common_ssh_key* key = user->private_key;
/* Validate username provided */ /* Validate username provided */
if (username == NULL) { if (user->username == NULL) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
"SSH authentication requires a username."); "SSH authentication requires a username.");
return 1; return 1;
} }
/* Get list of supported authentication methods */ /* Get list of supported authentication methods */
char* user_authlist = libssh2_userauth_list(session, username, char* user_authlist = libssh2_userauth_list(session, user->username,
strlen(username)); strlen(user->username));
/* If auth list is NULL, then authentication has succeeded with NONE */ /* If auth list is NULL, then authentication has succeeded with NONE */
if (user_authlist == NULL) { if (user_authlist == NULL) {
@ -342,7 +340,7 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
} }
/* Attempt public key auth */ /* Attempt public key auth */
if (libssh2_userauth_publickey(session, username, if (libssh2_userauth_publickey(session, user->username,
(unsigned char*) key->public_key, key->public_key_length, (unsigned char*) key->public_key, key->public_key_length,
guac_common_ssh_sign_callback, (void**) key)) { guac_common_ssh_sign_callback, (void**) key)) {
@ -361,14 +359,18 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
} }
/* Down to username + password authentication. */
if (user->password == NULL && common_session->credential_handler)
user->password = common_session->credential_handler(client, "Password: ");
/* Authenticate with password, if provided */ /* Authenticate with password, if provided */
else if (password != NULL) { if (user->password != NULL) {
/* Check if password auth is supported on the server */ /* Check if password auth is supported on the server */
if (strstr(user_authlist, "password") != NULL) { if (strstr(user_authlist, "password") != NULL) {
/* Attempt password authentication */ /* Attempt password authentication */
if (libssh2_userauth_password(session, username, password)) { if (libssh2_userauth_password(session, user->username, user->password)) {
/* Abort on failure */ /* Abort on failure */
char* error_message; char* error_message;
@ -389,7 +391,7 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session)
if (strstr(user_authlist, "keyboard-interactive") != NULL) { if (strstr(user_authlist, "keyboard-interactive") != NULL) {
/* Attempt keyboard-interactive auth using provided password */ /* Attempt keyboard-interactive auth using provided password */
if (libssh2_userauth_keyboard_interactive(session, username, if (libssh2_userauth_keyboard_interactive(session, user->username,
&guac_common_ssh_kbd_callback)) { &guac_common_ssh_kbd_callback)) {
/* Abort on failure */ /* Abort on failure */
@ -425,7 +427,7 @@ 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) { const char* host_key, guac_ssh_credential_handler* credential_handler) {
int retval; int retval;
@ -570,6 +572,7 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
common_session->user = user; common_session->user = user;
common_session->session = session; common_session->session = session;
common_session->fd = fd; common_session->fd = fd;
common_session->credential_handler = credential_handler;
/* Attempt authentication */ /* Attempt authentication */
if (guac_common_ssh_authenticate(common_session)) { if (guac_common_ssh_authenticate(common_session)) {

View File

@ -975,7 +975,7 @@ void* guac_rdp_client_thread(void* data) {
rdp_client->sftp_session = rdp_client->sftp_session =
guac_common_ssh_create_session(client, settings->sftp_hostname, guac_common_ssh_create_session(client, settings->sftp_hostname,
settings->sftp_port, rdp_client->sftp_user, settings->sftp_server_alive_interval, settings->sftp_port, rdp_client->sftp_user, settings->sftp_server_alive_interval,
settings->sftp_host_key); settings->sftp_host_key, NULL);
/* Fail if SSH connection does not succeed */ /* Fail if SSH connection does not succeed */
if (rdp_client->sftp_session == NULL) { if (rdp_client->sftp_session == NULL) {

View File

@ -130,19 +130,6 @@ static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) {
} /* end if key given */ } /* end if key given */
/* Otherwise, use password */
else {
/* Get password if not provided */
if (settings->password == NULL)
settings->password = guac_terminal_prompt(ssh_client->term,
"Password: ", false);
/* Set provided password */
guac_common_ssh_user_set_password(user, settings->password);
}
/* Clear screen of any prompts */ /* Clear screen of any prompts */
guac_terminal_printf(ssh_client->term, "\x1B[H\x1B[J"); guac_terminal_printf(ssh_client->term, "\x1B[H\x1B[J");
@ -150,6 +137,13 @@ static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) {
} }
char* guac_ssh_get_credential(guac_client *client, char* credName) {
guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
return guac_terminal_prompt(ssh_client->term, credName, false);
}
void* ssh_input_thread(void* data) { void* ssh_input_thread(void* data) {
guac_client* client = (guac_client*) data; guac_client* client = (guac_client*) data;
@ -239,7 +233,7 @@ void* ssh_client_thread(void* data) {
/* Open SSH session */ /* Open SSH session */
ssh_client->session = guac_common_ssh_create_session(client, ssh_client->session = guac_common_ssh_create_session(client,
settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval, settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval,
settings->host_key); settings->host_key, guac_ssh_get_credential);
if (ssh_client->session == NULL) { if (ssh_client->session == NULL) {
/* Already aborted within guac_common_ssh_create_session() */ /* Already aborted within guac_common_ssh_create_session() */
return NULL; return NULL;
@ -291,7 +285,7 @@ void* ssh_client_thread(void* data) {
ssh_client->sftp_session = ssh_client->sftp_session =
guac_common_ssh_create_session(client, settings->hostname, guac_common_ssh_create_session(client, settings->hostname,
settings->port, ssh_client->user, settings->server_alive_interval, settings->port, ssh_client->user, settings->server_alive_interval,
settings->host_key); settings->host_key, NULL);
if (ssh_client->sftp_session == NULL) { if (ssh_client->sftp_session == NULL) {
/* Already aborted within guac_common_ssh_create_session() */ /* Already aborted within guac_common_ssh_create_session() */
return NULL; return NULL;

View File

@ -262,7 +262,7 @@ void* guac_vnc_client_thread(void* data) {
vnc_client->sftp_session = vnc_client->sftp_session =
guac_common_ssh_create_session(client, settings->sftp_hostname, guac_common_ssh_create_session(client, settings->sftp_hostname,
settings->sftp_port, vnc_client->sftp_user, settings->sftp_server_alive_interval, settings->sftp_port, vnc_client->sftp_user, settings->sftp_server_alive_interval,
settings->sftp_host_key); settings->sftp_host_key, NULL);
/* Fail if SSH connection does not succeed */ /* Fail if SSH connection does not succeed */
if (vnc_client->sftp_session == NULL) { if (vnc_client->sftp_session == NULL) {