diff --git a/src/protocols/ssh/ssh_client.c b/src/protocols/ssh/ssh_client.c index 71552bf4..aadf8f57 100644 --- a/src/protocols/ssh/ssh_client.c +++ b/src/protocols/ssh/ssh_client.c @@ -84,9 +84,28 @@ static int __sign_callback(LIBSSH2_SESSION* session, *sig_len = length; return 0; - } +/** + * Callback for the keyboard-interactive authentication method. Currently + * suports just one prompt for the password. + */ +static void __kbd_callback(const char *name, int name_len, + const char *instruction, int instruction_len, + int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) +{ + guac_client *client = (guac_client *) *abstract; + ssh_guac_client_data *client_data = (ssh_guac_client_data *) client->data; + if (num_prompts == 1) { + responses[0].text = strdup(client_data->password); + responses[0].length = strlen(client_data->password); + } +} + + static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client, int* socket_fd) { @@ -98,6 +117,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client, char connected_address[1024]; char connected_port[64]; + char *user_authlist; ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; @@ -182,8 +202,19 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client, if (socket_fd != NULL) *socket_fd = fd; + /* Get list of suported authentication methods */ + user_authlist = libssh2_userauth_list(session, client_data->username, strlen(client_data->username)); + guac_client_log_info (client, "Supported authentications: %s", user_authlist); + /* Authenticate with key if available */ if (client_data->key != NULL) { + /* Check if public key auth is suported on the server */ + if (strstr(user_authlist, "publickey") == NULL) { + guac_client_abort (client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED, + "Public key authentication not suported"); + return NULL; + } + if (!libssh2_userauth_publickey(session, client_data->username, (unsigned char*) client_data->key->public_key, client_data->key->public_key_length, @@ -199,10 +230,19 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client, } /* Authenticate with password */ - if (!libssh2_userauth_password(session, client_data->username, - client_data->password)) - return session; + if (strstr(user_authlist, "password") != NULL) { + guac_client_log_info(client, "Using password authentication method"); + retval = libssh2_userauth_password(session, client_data->username, client_data->password); + } else if (strstr(user_authlist, "keyboard-interactive") != NULL) { + guac_client_log_info(client, "Using keyboard-interactive authentication method"); + retval = libssh2_userauth_keyboard_interactive(session, client_data->username, &__kbd_callback); + } else { + guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE, "No known authentication methods"); + return NULL; + } + if (retval == 0) + return session; else { char* error_message; libssh2_session_last_error(session, &error_message, NULL, 0);