diff --git a/src/protocols/ssh/argv.c b/src/protocols/ssh/argv.c index 00a2cbba..8db2b242 100644 --- a/src/protocols/ssh/argv.c +++ b/src/protocols/ssh/argv.c @@ -26,15 +26,44 @@ #include #include +#include #include #include +/** + * All SSH connection settings which may be updated by unprivileged users + * through "argv" streams. + */ +typedef enum guac_ssh_argv_setting { + + /** + * The color scheme of the terminal. + */ + GUAC_SSH_ARGV_SETTING_COLOR_SCHEME, + + /** + * The name of the font family used by the terminal. + */ + GUAC_SSH_ARGV_SETTING_FONT_NAME, + + /** + * The size of the font used by the terminal, in points. + */ + GUAC_SSH_ARGV_SETTING_FONT_SIZE + +} guac_ssh_argv_setting; + /** * The value or current status of a connection parameter received over an * "argv" stream. */ typedef struct guac_ssh_argv { + /** + * The specific setting being updated. + */ + guac_ssh_argv_setting setting; + /** * Buffer space for containing the received argument value. */ @@ -81,16 +110,51 @@ static int guac_ssh_argv_blob_handler(guac_user* user, static int guac_ssh_argv_end_handler(guac_user* user, guac_stream* stream) { + int size; + guac_client* client = user->client; - guac_ssh_client* telnet_client = (guac_ssh_client*) client->data; - guac_terminal* terminal = telnet_client->term; + guac_ssh_client* ssh_client = (guac_ssh_client*) client->data; + guac_terminal* terminal = ssh_client->term; /* Append null terminator to value */ guac_ssh_argv* argv = (guac_ssh_argv*) stream->data; argv->buffer[argv->length] = '\0'; - /* Update color scheme */ - guac_terminal_apply_color_scheme(terminal, argv->buffer); + /* Apply changes to chosen setting */ + switch (argv->setting) { + + /* Update color scheme */ + case GUAC_SSH_ARGV_SETTING_COLOR_SCHEME: + guac_terminal_apply_color_scheme(terminal, argv->buffer); + break; + + /* Update font name */ + case GUAC_SSH_ARGV_SETTING_FONT_NAME: + guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + break; + + /* Update font size */ + case GUAC_SSH_ARGV_SETTING_FONT_SIZE: + + /* Update only if font size is sane */ + size = atoi(argv->buffer); + if (size > 0) { + guac_terminal_apply_font(terminal, NULL, size, + ssh_client->settings->resolution); + } + + break; + + } + + /* Update SSH pty size if connected */ + if (ssh_client->term_channel != NULL) { + pthread_mutex_lock(&(ssh_client->term_channel_lock)); + libssh2_channel_request_pty_size(ssh_client->term_channel, + terminal->term_width, terminal->term_height); + pthread_mutex_unlock(&(ssh_client->term_channel_lock)); + } + free(argv); return 0; @@ -99,28 +163,36 @@ static int guac_ssh_argv_end_handler(guac_user* user, int guac_ssh_argv_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { - /* Allow users to update the color scheme */ - if (strcmp(name, "color-scheme") == 0) { + guac_ssh_argv_setting setting; - guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv)); - argv->length = 0; - - /* Prepare stream to receive argument value */ - stream->blob_handler = guac_ssh_argv_blob_handler; - stream->end_handler = guac_ssh_argv_end_handler; - stream->data = argv; - - /* Signal stream is ready */ - guac_protocol_send_ack(user->socket, stream, "Ready for color " - "scheme.", GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; - - } + /* Allow users to update the color scheme and font details */ + if (strcmp(name, "color-scheme") == 0) + setting = GUAC_SSH_ARGV_SETTING_COLOR_SCHEME; + else if (strcmp(name, "font-name") == 0) + setting = GUAC_SSH_ARGV_SETTING_FONT_NAME; + else if (strcmp(name, "font-size") == 0) + setting = GUAC_SSH_ARGV_SETTING_FONT_SIZE; /* No other connection parameters may be updated */ - guac_protocol_send_ack(user->socket, stream, "Not allowed.", - GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + else { + guac_protocol_send_ack(user->socket, stream, "Not allowed.", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv)); + argv->setting = setting; + argv->length = 0; + + /* Prepare stream to receive argument value */ + stream->blob_handler = guac_ssh_argv_blob_handler; + stream->end_handler = guac_ssh_argv_end_handler; + stream->data = argv; + + /* Signal stream is ready */ + guac_protocol_send_ack(user->socket, stream, "Ready for updated " + "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0; diff --git a/src/protocols/telnet/argv.c b/src/protocols/telnet/argv.c index 07359286..450c7f35 100644 --- a/src/protocols/telnet/argv.c +++ b/src/protocols/telnet/argv.c @@ -29,12 +29,40 @@ #include #include +/** + * All telnet connection settings which may be updated by unprivileged users + * through "argv" streams. + */ +typedef enum guac_telnet_argv_setting { + + /** + * The color scheme of the terminal. + */ + GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME, + + /** + * The name of the font family used by the terminal. + */ + GUAC_TELNET_ARGV_SETTING_FONT_NAME, + + /** + * The size of the font used by the terminal, in points. + */ + GUAC_TELNET_ARGV_SETTING_FONT_SIZE + +} guac_telnet_argv_setting; + /** * The value or current status of a connection parameter received over an * "argv" stream. */ typedef struct guac_telnet_argv { + /** + * The specific setting being updated. + */ + guac_telnet_argv_setting setting; + /** * Buffer space for containing the received argument value. */ @@ -81,6 +109,8 @@ static int guac_telnet_argv_blob_handler(guac_user* user, static int guac_telnet_argv_end_handler(guac_user* user, guac_stream* stream) { + int size; + guac_client* client = user->client; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_terminal* terminal = telnet_client->term; @@ -89,8 +119,38 @@ static int guac_telnet_argv_end_handler(guac_user* user, guac_telnet_argv* argv = (guac_telnet_argv*) stream->data; argv->buffer[argv->length] = '\0'; - /* Update color scheme */ - guac_terminal_apply_color_scheme(terminal, argv->buffer); + /* Apply changes to chosen setting */ + switch (argv->setting) { + + /* Update color scheme */ + case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME: + guac_terminal_apply_color_scheme(terminal, argv->buffer); + break; + + /* Update font name */ + case GUAC_TELNET_ARGV_SETTING_FONT_NAME: + guac_terminal_apply_font(terminal, argv->buffer, -1, 0); + break; + + /* Update font size */ + case GUAC_TELNET_ARGV_SETTING_FONT_SIZE: + + /* Update only if font size is sane */ + size = atoi(argv->buffer); + if (size > 0) { + guac_terminal_apply_font(terminal, NULL, size, + telnet_client->settings->resolution); + } + + break; + + } + + /* Update terminal window size if connected */ + if (telnet_client->telnet != NULL && telnet_client->naws_enabled) + guac_telnet_send_naws(telnet_client->telnet, terminal->term_width, + terminal->term_height); + free(argv); return 0; @@ -99,28 +159,36 @@ static int guac_telnet_argv_end_handler(guac_user* user, int guac_telnet_argv_handler(guac_user* user, guac_stream* stream, char* mimetype, char* name) { - /* Allow users to update the color scheme */ - if (strcmp(name, "color-scheme") == 0) { + guac_telnet_argv_setting setting; - guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv)); - argv->length = 0; - - /* Prepare stream to receive argument value */ - stream->blob_handler = guac_telnet_argv_blob_handler; - stream->end_handler = guac_telnet_argv_end_handler; - stream->data = argv; - - /* Signal stream is ready */ - guac_protocol_send_ack(user->socket, stream, "Ready for color " - "scheme.", GUAC_PROTOCOL_STATUS_SUCCESS); - guac_socket_flush(user->socket); - return 0; - - } + /* Allow users to update the color scheme and font details */ + if (strcmp(name, "color-scheme") == 0) + setting = GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME; + else if (strcmp(name, "font-name") == 0) + setting = GUAC_TELNET_ARGV_SETTING_FONT_NAME; + else if (strcmp(name, "font-size") == 0) + setting = GUAC_TELNET_ARGV_SETTING_FONT_SIZE; /* No other connection parameters may be updated */ - guac_protocol_send_ack(user->socket, stream, "Not allowed.", - GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + else { + guac_protocol_send_ack(user->socket, stream, "Not allowed.", + GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN); + guac_socket_flush(user->socket); + return 0; + } + + guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv)); + argv->setting = setting; + argv->length = 0; + + /* Prepare stream to receive argument value */ + stream->blob_handler = guac_telnet_argv_blob_handler; + stream->end_handler = guac_telnet_argv_end_handler; + stream->data = argv; + + /* Signal stream is ready */ + guac_protocol_send_ack(user->socket, stream, "Ready for updated " + "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS); guac_socket_flush(user->socket); return 0;