GUACAMOLE-547: Use a call-back function for getting the password.
diff --git a/src/common-ssh/common-ssh/ssh.h b/src/common-ssh/common-ssh/ssh.h
index 672e776..ecc1c4b 100644
--- a/src/common-ssh/common-ssh/ssh.h
+++ b/src/common-ssh/common-ssh/ssh.h
@@ -26,6 +26,11 @@
 #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
  * Guacamole client.
  */
@@ -50,6 +55,11 @@
      * 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 @@
  */
 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 7691bf5..3e6d934 100644
--- a/src/common-ssh/ssh.c
+++ b/src/common-ssh/ssh.c
@@ -304,20 +304,18 @@
     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 @@
         }
 
         /* 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 @@
 
     }
 
+    /* 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 @@
         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 @@
 
 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 @@
     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 042d389..86f5096 100644
--- a/src/protocols/rdp/rdp.c
+++ b/src/protocols/rdp/rdp.c
@@ -975,7 +975,7 @@
         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 9db545b..0b7dd32 100644
--- a/src/protocols/ssh/ssh.c
+++ b/src/protocols/ssh/ssh.c
@@ -130,19 +130,6 @@
 
     } /* 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 @@
 
 }
 
+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 @@
     /* 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 @@
         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 d9f9dbb..afffaac 100644
--- a/src/protocols/vnc/vnc.c
+++ b/src/protocols/vnc/vnc.c
@@ -262,7 +262,7 @@
         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) {