diff --git a/configure.ac b/configure.ac index 87eaf181..bee0332b 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,7 @@ AC_PROG_LIBTOOL AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/socket.h time.h sys/time.h syslog.h unistd.h cairo/cairo.h pngstruct.h]) # Source characteristics -AC_DEFINE([_POSIX_C_SOURCE], [199309L], [Uses POSIX APIs]) +AC_DEFINE([_POSIX_C_SOURCE], [200809L], [Uses POSIX APIs]) AC_DEFINE([_BSD_SOURCE], [], [Uses BSD APIs]) # libdl diff --git a/src/protocols/ssh/client.c b/src/protocols/ssh/client.c index 820eb933..e2b469b9 100644 --- a/src/protocols/ssh/client.c +++ b/src/protocols/ssh/client.c @@ -149,6 +149,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { client_data->enable_sftp = strcmp(argv[IDX_ENABLE_SFTP], "true") == 0; client_data->sftp_session = NULL; client_data->sftp_ssh_session = NULL; + strcpy(client_data->sftp_upload_path, "."); /* Read port */ if (argv[IDX_PORT][0] != 0) diff --git a/src/protocols/ssh/client.h b/src/protocols/ssh/client.h index 45902e13..f35b25b0 100644 --- a/src/protocols/ssh/client.h +++ b/src/protocols/ssh/client.h @@ -45,6 +45,7 @@ #include "terminal.h" #include "cursor.h" +#include "sftp.h" /** * SSH-specific client data. @@ -106,6 +107,11 @@ typedef struct ssh_guac_client_data { */ sftp_session sftp_session; + /** + * The path files will be sent to. + */ + char sftp_upload_path[GUAC_SFTP_MAX_PATH]; + /** * SSH terminal channel, used by the SSH client thread. */ diff --git a/src/protocols/ssh/sftp.c b/src/protocols/ssh/sftp.c index ae51a274..f5b0259c 100644 --- a/src/protocols/ssh/sftp.c +++ b/src/protocols/ssh/sftp.c @@ -84,7 +84,9 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream, char* mimetype, char* filename) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; + char fullpath[GUAC_SFTP_MAX_PATH]; sftp_file file; + int i; /* Ensure filename is a valid filename and not a path */ if (!__ssh_guac_valid_filename(filename)) { @@ -95,8 +97,39 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream, return 0; } + /* Copy upload path, append trailing slash */ + for (i=0; isftp_upload_path[i]; + if (c == '\0') { + fullpath[i++] = '/'; + break; + } + + fullpath[i] = c; + } + + /* Append filename */ + for (; isocket, stream, "SFTP: Name too long", + GUAC_PROTOCOL_STATUS_INVALID_PARAMETER); + guac_socket_flush(client->socket); + return 0; + } + + /* Terminate path string */ + fullpath[i] = '\0'; + /* Open file via SFTP */ - file = sftp_open(client_data->sftp_session, filename, + file = sftp_open(client_data->sftp_session, fullpath, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); /* Inform of status */ @@ -106,8 +139,8 @@ int guac_sftp_file_handler(guac_client* client, guac_stream* stream, guac_socket_flush(client->socket); } else { - guac_client_log_error(client, "Unable to open file: %s", - ssh_get_error(client_data->sftp_ssh_session)); + guac_client_log_error(client, "Unable to open file \"%s\": %s", + fullpath, ssh_get_error(client_data->sftp_ssh_session)); guac_protocol_send_ack(client->socket, stream, "SFTP: Open failed", GUAC_PROTOCOL_STATUS_INTERNAL_ERROR); guac_socket_flush(client->socket); @@ -240,3 +273,21 @@ guac_stream* guac_sftp_download_file(guac_client* client, } +void guac_sftp_set_upload_path(guac_client* client, char* path) { + + ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; + int length = strnlen(path, GUAC_SFTP_MAX_PATH); + + /* Ignore requests which exceed maximum-allowed path */ + if (length > GUAC_SFTP_MAX_PATH) { + guac_client_log_error(client, + "Submitted path exceeds limit of %i bytes", + GUAC_SFTP_MAX_PATH); + return; + } + + /* Copy path */ + memcpy(client_data->sftp_upload_path, path, length); + +} + diff --git a/src/protocols/ssh/sftp.h b/src/protocols/ssh/sftp.h index b621507e..8ecce1cb 100644 --- a/src/protocols/ssh/sftp.h +++ b/src/protocols/ssh/sftp.h @@ -41,6 +41,11 @@ #include #include +/** + * Maximum number of bytes per path. + */ +#define GUAC_SFTP_MAX_PATH 2048 + /** * Handler for file messages which begins an SFTP data transfer (upload). */ @@ -69,5 +74,10 @@ int guac_sftp_ack_handler(guac_client* client, guac_stream* stream, */ guac_stream* guac_sftp_download_file(guac_client* client, char* filename); +/** + * Set the destination directory for future uploads. + */ +void guac_sftp_set_upload_path(guac_client* client, char* path); + #endif diff --git a/src/protocols/ssh/terminal_handlers.c b/src/protocols/ssh/terminal_handlers.c index 349c9cad..919044ec 100644 --- a/src/protocols/ssh/terminal_handlers.c +++ b/src/protocols/ssh/terminal_handlers.c @@ -900,7 +900,7 @@ int guac_terminal_guac_set_directory(guac_terminal* term, char c) { if (c == 0x9C || c == 0x5C || c == 0x07) { filename[length++] = '\0'; term->char_handler = guac_terminal_echo; - guac_client_log_info(term->client, "STUB: set: %s", filename); + guac_sftp_set_upload_path(term->client, filename); length = 0; }