GUAC-556: Send proper errors for SSH.
This commit is contained in:
parent
d0dadf6a9c
commit
6e6af91cfa
@ -35,7 +35,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
|
||||
@ -132,7 +131,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
client_data->term_channel = NULL;
|
||||
|
||||
if (argc != SSH_ARGS_COUNT) {
|
||||
guac_client_log_error(client, "Wrong number of arguments");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Wrong number of arguments");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -182,8 +181,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
|
||||
/* Fail if terminal init failed */
|
||||
if (client_data->term == NULL) {
|
||||
guac_error = GUAC_STATUS_BAD_STATE;
|
||||
guac_error_message = "Terminal initialization failed";
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Terminal initialization failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -212,7 +210,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
|
||||
|
||||
/* Start client thread */
|
||||
if (pthread_create(&(client_data->client_thread), NULL, ssh_client_thread, (void*) client)) {
|
||||
guac_client_log_error(client, "Unable to SSH client thread");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start SSH client thread");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -358,13 +358,14 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
|
||||
|
||||
font = pango_font_map_load_font(font_map, context, display->font_desc);
|
||||
if (font == NULL) {
|
||||
guac_client_log_error(display->client, "Unable to get font \"%s\"", font_name);
|
||||
guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to get font \"%s\"", font_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
metrics = pango_font_get_metrics(font, NULL);
|
||||
if (metrics == NULL) {
|
||||
guac_client_log_error(display->client, "Unable to get font metrics for font \"%s\"", font_name);
|
||||
guac_client_abort(display->client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
|
||||
"Unable to get font metrics for font \"%s\"", font_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -37,13 +37,11 @@
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/error.h>
|
||||
#include <libssh2.h>
|
||||
#include <pango/pangocairo.h>
|
||||
|
||||
int ssh_guac_client_handle_messages(guac_client* client) {
|
||||
|
||||
guac_socket* socket = client->socket;
|
||||
ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data;
|
||||
char buffer[8192];
|
||||
|
||||
@ -72,16 +70,16 @@ int ssh_guac_client_handle_messages(guac_client* client) {
|
||||
/* Read data, write to terminal */
|
||||
if ((bytes_read = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
|
||||
if (guac_terminal_write(client_data->term, buffer, bytes_read))
|
||||
if (guac_terminal_write(client_data->term, buffer, bytes_read)) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error writing data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Notify on error */
|
||||
if (bytes_read < 0) {
|
||||
guac_protocol_send_error(socket, "Error reading data.",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error reading data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -96,8 +94,7 @@ int ssh_guac_client_handle_messages(guac_client* client) {
|
||||
|
||||
}
|
||||
else if (ret_val < 0) {
|
||||
guac_error_message = "Error waiting for pipe";
|
||||
guac_error = GUAC_STATUS_SEE_ERRNO;
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error waiting for data");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,7 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
||||
|
||||
/* Ensure filename is a valid filename and not a path */
|
||||
if (!__ssh_guac_valid_filename(filename)) {
|
||||
guac_protocol_send_ack(client->socket, stream,
|
||||
"SFTP: Illegal filename",
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Illegal filename",
|
||||
GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST);
|
||||
guac_socket_flush(client->socket);
|
||||
return 0;
|
||||
@ -103,8 +102,7 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
||||
|
||||
/* If path + filename exceeds max length, abort */
|
||||
if (i == GUAC_SFTP_MAX_PATH) {
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Name too long",
|
||||
GUAC_PROTOCOL_STATUS_CLIENT_BAD_REQUEST);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Name too long", GUAC_PROTOCOL_STATUS_CLIENT_OVERRUN);
|
||||
guac_socket_flush(client->socket);
|
||||
return 0;
|
||||
}
|
||||
@ -119,15 +117,13 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream,
|
||||
|
||||
/* Inform of status */
|
||||
if (file != NULL) {
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: File opened",
|
||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: File opened", GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
else {
|
||||
guac_client_log_error(client, "Unable to open file \"%s\": %s",
|
||||
fullpath, libssh2_sftp_last_error(client_data->sftp_session));
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed", GUAC_PROTOCOL_STATUS_RESOURCE_NOT_FOUND);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
@ -146,8 +142,7 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
||||
|
||||
/* Attempt write */
|
||||
if (libssh2_sftp_write(file, data, length) == length) {
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
@ -155,8 +150,7 @@ int guac_sftp_blob_handler(guac_client* client, guac_stream* stream,
|
||||
else {
|
||||
guac_client_log_error(client, "Unable to write to file: %s",
|
||||
libssh2_sftp_last_error(client_data->sftp_session));
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Write failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
@ -171,14 +165,12 @@ int guac_sftp_end_handler(guac_client* client, guac_stream* stream) {
|
||||
|
||||
/* Attempt to close file */
|
||||
if (libssh2_sftp_close(file) == 0) {
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK",
|
||||
GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: OK", GUAC_PROTOCOL_STATUS_SUCCESS);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
else {
|
||||
guac_client_log_error(client, "Unable to close file");
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Close failed",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_protocol_send_ack(client->socket, stream, "SFTP: Close failed", GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(client->socket);
|
||||
}
|
||||
|
||||
|
@ -168,9 +168,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
/* Get addresses connection */
|
||||
if ((retval = getaddrinfo(client_data->hostname, client_data->port,
|
||||
&hints, &addresses))) {
|
||||
|
||||
guac_client_log_error(client,
|
||||
"Error parsing given address or port: %s",
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Error parsing given address or port: %s",
|
||||
gai_strerror(retval));
|
||||
return NULL;
|
||||
|
||||
@ -188,8 +186,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
connected_address, sizeof(connected_address),
|
||||
connected_port, sizeof(connected_port),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV)))
|
||||
guac_client_log_error(client, "Unable to resolve host: %s",
|
||||
gai_strerror(retval));
|
||||
guac_client_log_info(client, "Unable to resolve host: %s", gai_strerror(retval));
|
||||
|
||||
/* Connect */
|
||||
if (connect(fd, current_address->ai_addr,
|
||||
@ -215,7 +212,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
|
||||
/* If unable to connect to anything, fail */
|
||||
if (current_address == NULL) {
|
||||
guac_client_log_error(client, "Unable to connect to any addresses.");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to connect to any addresses.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -226,13 +223,13 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
LIBSSH2_SESSION* session = libssh2_session_init_ex(NULL, NULL,
|
||||
NULL, client);
|
||||
if (session == NULL) {
|
||||
guac_client_log_error(client, "Session allocation failed");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Session allocation failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Perform handshake */
|
||||
if (libssh2_session_handshake(session, fd)) {
|
||||
guac_client_log_error(client, "SSH handshake failed");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "SSH handshake failed.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -250,7 +247,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
else {
|
||||
char* error_message;
|
||||
libssh2_session_last_error(session, &error_message, NULL, 0);
|
||||
guac_client_log_error(client,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Public key authentication failed: %s", error_message);
|
||||
return NULL;
|
||||
}
|
||||
@ -264,7 +261,7 @@ static LIBSSH2_SESSION* __guac_ssh_create_session(guac_client* client,
|
||||
else {
|
||||
char* error_message;
|
||||
libssh2_session_last_error(session, &error_message, NULL, 0);
|
||||
guac_client_log_error(client,
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_CLIENT_UNAUTHORIZED,
|
||||
"Password authentication failed: %s", error_message);
|
||||
return NULL;
|
||||
}
|
||||
@ -290,9 +287,8 @@ void* ssh_client_thread(void* data) {
|
||||
libssh2_init(0);
|
||||
|
||||
/* Get username */
|
||||
if (client_data->username[0] == 0 &&
|
||||
prompt(client, "Login as: ", client_data->username, sizeof(client_data->username), true) == NULL)
|
||||
return NULL;
|
||||
if (client_data->username[0] == 0)
|
||||
prompt(client, "Login as: ", client_data->username, sizeof(client_data->username), true);
|
||||
|
||||
/* Send new name */
|
||||
snprintf(name, sizeof(name)-1, "%s@%s", client_data->username, client_data->hostname);
|
||||
@ -309,12 +305,9 @@ void* ssh_client_thread(void* data) {
|
||||
if (client_data->key == NULL) {
|
||||
|
||||
/* Prompt for passphrase if missing */
|
||||
if (client_data->key_passphrase[0] == 0) {
|
||||
if (prompt(client, "Key passphrase: ",
|
||||
client_data->key_passphrase,
|
||||
sizeof(client_data->key_passphrase), false) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (client_data->key_passphrase[0] == 0)
|
||||
prompt(client, "Key passphrase: ", client_data->key_passphrase,
|
||||
sizeof(client_data->key_passphrase), false);
|
||||
|
||||
/* Import key with passphrase */
|
||||
client_data->key = ssh_key_alloc(client_data->key_base64,
|
||||
@ -335,11 +328,8 @@ void* ssh_client_thread(void* data) {
|
||||
} /* end if key given */
|
||||
|
||||
/* Otherwise, get password if not provided */
|
||||
else if (client_data->password[0] == 0) {
|
||||
if (prompt(client, "Password: ", client_data->password,
|
||||
sizeof(client_data->password), false) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
else if (client_data->password[0] == 0)
|
||||
prompt(client, "Password: ", client_data->password, sizeof(client_data->password), false);
|
||||
|
||||
/* Clear screen */
|
||||
guac_terminal_write_all(stdout_fd, "\x1B[H\x1B[J", 6);
|
||||
@ -347,19 +337,14 @@ void* ssh_client_thread(void* data) {
|
||||
/* Open SSH session */
|
||||
client_data->session = __guac_ssh_create_session(client, &socket_fd);
|
||||
if (client_data->session == NULL) {
|
||||
guac_protocol_send_error(socket, "Unable to create SSH session.",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
/* Already aborted within __guac_ssh_create_session() */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Open channel for terminal */
|
||||
client_data->term_channel =
|
||||
libssh2_channel_open_session(client_data->session);
|
||||
client_data->term_channel = libssh2_channel_open_session(client_data->session);
|
||||
if (client_data->term_channel == NULL) {
|
||||
guac_protocol_send_error(socket, "Unable to open channel.",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to open terminal channel.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -385,14 +370,15 @@ void* ssh_client_thread(void* data) {
|
||||
/* Create SSH session specific for SFTP */
|
||||
guac_client_log_info(client, "Reconnecting for SFTP...");
|
||||
client_data->sftp_ssh_session = __guac_ssh_create_session(client, NULL);
|
||||
if (client_data->sftp_ssh_session == NULL) {
|
||||
/* Already aborted within __guac_ssh_create_session() */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Request SFTP */
|
||||
client_data->sftp_session =
|
||||
libssh2_sftp_init(client_data->sftp_ssh_session);
|
||||
client_data->sftp_session = libssh2_sftp_init(client_data->sftp_ssh_session);
|
||||
if (client_data->sftp_session == NULL) {
|
||||
guac_protocol_send_error(socket, "Unable to start SFTP session..",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to start SFTP session.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -407,21 +393,15 @@ void* ssh_client_thread(void* data) {
|
||||
}
|
||||
|
||||
/* Request PTY */
|
||||
if (libssh2_channel_request_pty_ex(client_data->term_channel,
|
||||
"linux", sizeof("linux")-1, NULL, 0,
|
||||
client_data->term->term_width, client_data->term->term_height,
|
||||
0, 0)) {
|
||||
guac_protocol_send_error(socket, "Unable to allocate PTY for channel.",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
if (libssh2_channel_request_pty_ex(client_data->term_channel, "linux", sizeof("linux")-1, NULL, 0,
|
||||
client_data->term->term_width, client_data->term->term_height, 0, 0)) {
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to allocate PTY.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Request shell */
|
||||
if (libssh2_channel_shell(client_data->term_channel)) {
|
||||
guac_protocol_send_error(socket, "Unable to associate shell with PTY.",
|
||||
GUAC_PROTOCOL_STATUS_SERVER_ERROR);
|
||||
guac_socket_flush(socket);
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR, "Unable to associate shell with PTY.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -430,7 +410,7 @@ void* ssh_client_thread(void* data) {
|
||||
|
||||
/* Start input thread */
|
||||
if (pthread_create(&(input_thread), NULL, ssh_input_thread, (void*) client)) {
|
||||
guac_client_log_error(client, "Unable to start SSH input thread");
|
||||
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR, "Unable to start input thread");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user