GUACAMOLE-630: Allow SSH/telnet font family and size to be updated.

This commit is contained in:
Michael Jumper 2018-10-07 23:49:12 -07:00
parent 9e28de70ec
commit 5683be0ea3
2 changed files with 184 additions and 44 deletions

View File

@ -26,15 +26,44 @@
#include <guacamole/socket.h> #include <guacamole/socket.h>
#include <guacamole/user.h> #include <guacamole/user.h>
#include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/**
* 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 * The value or current status of a connection parameter received over an
* "argv" stream. * "argv" stream.
*/ */
typedef struct guac_ssh_argv { typedef struct guac_ssh_argv {
/**
* The specific setting being updated.
*/
guac_ssh_argv_setting setting;
/** /**
* Buffer space for containing the received argument value. * 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, static int guac_ssh_argv_end_handler(guac_user* user,
guac_stream* stream) { guac_stream* stream) {
int size;
guac_client* client = user->client; guac_client* client = user->client;
guac_ssh_client* telnet_client = (guac_ssh_client*) client->data; guac_ssh_client* ssh_client = (guac_ssh_client*) client->data;
guac_terminal* terminal = telnet_client->term; guac_terminal* terminal = ssh_client->term;
/* Append null terminator to value */ /* Append null terminator to value */
guac_ssh_argv* argv = (guac_ssh_argv*) stream->data; guac_ssh_argv* argv = (guac_ssh_argv*) stream->data;
argv->buffer[argv->length] = '\0'; argv->buffer[argv->length] = '\0';
/* Apply changes to chosen setting */
switch (argv->setting) {
/* Update color scheme */ /* Update color scheme */
case GUAC_SSH_ARGV_SETTING_COLOR_SCHEME:
guac_terminal_apply_color_scheme(terminal, argv->buffer); 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); free(argv);
return 0; return 0;
@ -99,10 +163,26 @@ static int guac_ssh_argv_end_handler(guac_user* user,
int guac_ssh_argv_handler(guac_user* user, guac_stream* stream, int guac_ssh_argv_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) { char* mimetype, char* name) {
/* Allow users to update the color scheme */ guac_ssh_argv_setting setting;
if (strcmp(name, "color-scheme") == 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 */
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)); guac_ssh_argv* argv = malloc(sizeof(guac_ssh_argv));
argv->setting = setting;
argv->length = 0; argv->length = 0;
/* Prepare stream to receive argument value */ /* Prepare stream to receive argument value */
@ -111,16 +191,8 @@ int guac_ssh_argv_handler(guac_user* user, guac_stream* stream,
stream->data = argv; stream->data = argv;
/* Signal stream is ready */ /* Signal stream is ready */
guac_protocol_send_ack(user->socket, stream, "Ready for color " guac_protocol_send_ack(user->socket, stream, "Ready for updated "
"scheme.", GUAC_PROTOCOL_STATUS_SUCCESS); "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
guac_socket_flush(user->socket);
return 0;
}
/* No other connection parameters may be updated */
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
guac_socket_flush(user->socket); guac_socket_flush(user->socket);
return 0; return 0;

View File

@ -29,12 +29,40 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
/**
* 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 * The value or current status of a connection parameter received over an
* "argv" stream. * "argv" stream.
*/ */
typedef struct guac_telnet_argv { typedef struct guac_telnet_argv {
/**
* The specific setting being updated.
*/
guac_telnet_argv_setting setting;
/** /**
* Buffer space for containing the received argument value. * 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, static int guac_telnet_argv_end_handler(guac_user* user,
guac_stream* stream) { guac_stream* stream) {
int size;
guac_client* client = user->client; guac_client* client = user->client;
guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; guac_telnet_client* telnet_client = (guac_telnet_client*) client->data;
guac_terminal* terminal = telnet_client->term; 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; guac_telnet_argv* argv = (guac_telnet_argv*) stream->data;
argv->buffer[argv->length] = '\0'; argv->buffer[argv->length] = '\0';
/* Apply changes to chosen setting */
switch (argv->setting) {
/* Update color scheme */ /* Update color scheme */
case GUAC_TELNET_ARGV_SETTING_COLOR_SCHEME:
guac_terminal_apply_color_scheme(terminal, argv->buffer); 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); free(argv);
return 0; return 0;
@ -99,10 +159,26 @@ static int guac_telnet_argv_end_handler(guac_user* user,
int guac_telnet_argv_handler(guac_user* user, guac_stream* stream, int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
char* mimetype, char* name) { char* mimetype, char* name) {
/* Allow users to update the color scheme */ guac_telnet_argv_setting setting;
if (strcmp(name, "color-scheme") == 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 */
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)); guac_telnet_argv* argv = malloc(sizeof(guac_telnet_argv));
argv->setting = setting;
argv->length = 0; argv->length = 0;
/* Prepare stream to receive argument value */ /* Prepare stream to receive argument value */
@ -111,16 +187,8 @@ int guac_telnet_argv_handler(guac_user* user, guac_stream* stream,
stream->data = argv; stream->data = argv;
/* Signal stream is ready */ /* Signal stream is ready */
guac_protocol_send_ack(user->socket, stream, "Ready for color " guac_protocol_send_ack(user->socket, stream, "Ready for updated "
"scheme.", GUAC_PROTOCOL_STATUS_SUCCESS); "parameter.", GUAC_PROTOCOL_STATUS_SUCCESS);
guac_socket_flush(user->socket);
return 0;
}
/* No other connection parameters may be updated */
guac_protocol_send_ack(user->socket, stream, "Not allowed.",
GUAC_PROTOCOL_STATUS_CLIENT_FORBIDDEN);
guac_socket_flush(user->socket); guac_socket_flush(user->socket);
return 0; return 0;