diff --git a/src/common-ssh/common-ssh/ssh.h b/src/common-ssh/common-ssh/ssh.h index 672e7767..ecc1c4b3 100644 --- a/src/common-ssh/common-ssh/ssh.h +++ b/src/common-ssh/common-ssh/ssh.h @@ -25,6 +25,11 @@ #include #include +/** + * 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 * Guacamole client. @@ -50,6 +55,11 @@ typedef struct guac_common_ssh_session { * The file descriptor of the socket being used for the SSH connection. */ int fd; + + /** + * Callback function to retrieve credentials. + */ + guac_ssh_credential_handler* credential_handler; } 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, 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 diff --git a/src/common-ssh/ssh.c b/src/common-ssh/ssh.c index 7691bf5d..3e6d9346 100644 --- a/src/common-ssh/ssh.c +++ b/src/common-ssh/ssh.c @@ -304,20 +304,18 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session) LIBSSH2_SESSION* session = common_session->session; /* Get user credentials */ - char* username = user->username; - char* password = user->password; guac_common_ssh_key* key = user->private_key; /* Validate username provided */ - if (username == NULL) { + if (user->username == NULL) { guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, "SSH authentication requires a username."); return 1; } /* Get list of supported authentication methods */ - char* user_authlist = libssh2_userauth_list(session, username, - strlen(username)); + char* user_authlist = libssh2_userauth_list(session, user->username, + strlen(user->username)); /* If auth list is NULL, then authentication has succeeded with NONE */ if (user_authlist == NULL) { @@ -342,7 +340,7 @@ static int guac_common_ssh_authenticate(guac_common_ssh_session* common_session) } /* 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, 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 */ - else if (password != NULL) { + if (user->password != NULL) { /* Check if password auth is supported on the server */ if (strstr(user_authlist, "password") != NULL) { /* Attempt password authentication */ - if (libssh2_userauth_password(session, username, password)) { + if (libssh2_userauth_password(session, user->username, user->password)) { /* Abort on failure */ 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) { /* 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)) { /* 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, 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; @@ -570,6 +572,7 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client, common_session->user = user; common_session->session = session; common_session->fd = fd; + common_session->credential_handler = credential_handler; /* Attempt authentication */ if (guac_common_ssh_authenticate(common_session)) { diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index 042d3893..86f50967 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -975,7 +975,7 @@ void* guac_rdp_client_thread(void* data) { rdp_client->sftp_session = guac_common_ssh_create_session(client, settings->sftp_hostname, 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 */ if (rdp_client->sftp_session == NULL) { diff --git a/src/protocols/ssh/ssh.c b/src/protocols/ssh/ssh.c index 9db545bf..0b7dd320 100644 --- a/src/protocols/ssh/ssh.c +++ b/src/protocols/ssh/ssh.c @@ -130,19 +130,6 @@ static guac_common_ssh_user* guac_ssh_get_user(guac_client* client) { } /* 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 */ 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) { guac_client* client = (guac_client*) data; @@ -239,7 +233,7 @@ void* ssh_client_thread(void* data) { /* Open SSH session */ ssh_client->session = guac_common_ssh_create_session(client, 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) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; @@ -291,7 +285,7 @@ void* ssh_client_thread(void* data) { ssh_client->sftp_session = guac_common_ssh_create_session(client, settings->hostname, settings->port, ssh_client->user, settings->server_alive_interval, - settings->host_key); + settings->host_key, NULL); if (ssh_client->sftp_session == NULL) { /* Already aborted within guac_common_ssh_create_session() */ return NULL; diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index d9f9dbbb..afffaac4 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -262,7 +262,7 @@ void* guac_vnc_client_thread(void* data) { vnc_client->sftp_session = guac_common_ssh_create_session(client, settings->sftp_hostname, 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 */ if (vnc_client->sftp_session == NULL) {