diff --git a/src/protocols/telnet/client.c b/src/protocols/telnet/client.c index 0be0243c..6d4b5e3c 100644 --- a/src/protocols/telnet/client.c +++ b/src/protocols/telnet/client.c @@ -45,6 +45,7 @@ const char* GUAC_CLIENT_ARGS[] = { "hostname", "port", + "username", "font-name", "font-size", NULL @@ -62,6 +63,11 @@ enum __TELNET_ARGS_IDX { */ IDX_PORT, + /** + * The name of the user to login as. Optional. + */ + IDX_USERNAME, + /** * The name of the font to use within the terminal. */ @@ -100,6 +106,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Read parameters */ strcpy(client_data->hostname, argv[IDX_HOSTNAME]); + strcpy(client_data->username, argv[IDX_USERNAME]); /* Read port */ if (argv[IDX_PORT][0] != 0) diff --git a/src/protocols/telnet/client.h b/src/protocols/telnet/client.h index 227d0e56..e850dce2 100644 --- a/src/protocols/telnet/client.h +++ b/src/protocols/telnet/client.h @@ -44,6 +44,11 @@ typedef struct guac_telnet_client_data { */ char port[64]; + /** + * The name of the user to login as. + */ + char username[1024]; + /** * The name of the font to use for display rendering. */ diff --git a/src/protocols/telnet/telnet_client.c b/src/protocols/telnet/telnet_client.c index d61141eb..a636d731 100644 --- a/src/protocols/telnet/telnet_client.c +++ b/src/protocols/telnet/telnet_client.c @@ -44,11 +44,12 @@ * negotiation by telnet_init(), part of libtelnet. */ static const telnet_telopt_t __telnet_options[] = { - { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, - { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, - { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, + { TELNET_TELOPT_ECHO, TELNET_WONT, TELNET_DO }, + { TELNET_TELOPT_TTYPE, TELNET_WILL, TELNET_DONT }, + { TELNET_TELOPT_COMPRESS2, TELNET_WONT, TELNET_DO }, + { TELNET_TELOPT_MSSP, TELNET_WONT, TELNET_DO }, + { TELNET_TELOPT_NAWS, TELNET_WILL, TELNET_DONT }, + { TELNET_TELOPT_NEW_ENVIRON, TELNET_WILL, TELNET_DONT }, { -1, 0, 0 } }; @@ -132,6 +133,15 @@ static void __guac_telnet_event_handler(telnet_t* telnet, telnet_event_t* event, telnet_ttype_is(client_data->telnet, "linux"); break; + /* Environment request */ + case TELNET_EV_ENVIRON: + + /* Only send USER if entire environment was requested */ + if (event->environ.size == 0) + guac_telnet_send_user(telnet, client_data->username); + + break; + /* Connection warnings */ case TELNET_EV_WARNING: guac_client_log_info(client, "%s", event->error.msg); @@ -293,6 +303,16 @@ static void __guac_telnet_send_uint16(telnet_t* telnet, uint16_t value) { } +/** + * Sends an 8-bit value over the given telnet connection. + * + * @param telnet The telnet connection to use. + * @param value The value to send. + */ +static void __guac_telnet_send_uint8(telnet_t* telnet, uint8_t value) { + telnet_send(telnet, (char*) (&value), 1); +} + void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { telnet_begin_sb(telnet, TELNET_TELOPT_NAWS); __guac_telnet_send_uint16(telnet, width); @@ -300,6 +320,25 @@ void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height) { telnet_finish_sb(telnet); } +void guac_telnet_send_user(telnet_t* telnet, const char* username) { + + /* IAC SB NEW-ENVIRON IS */ + telnet_begin_sb(telnet, TELNET_TELOPT_NEW_ENVIRON); + __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_IS); + + /* VAR "USER" */ + __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VAR); + telnet_send(telnet, "USER", 4); + + /* VALUE username */ + __guac_telnet_send_uint8(telnet, TELNET_ENVIRON_VALUE); + telnet_send(telnet, username, strlen(username)); + + /* IAC SE */ + telnet_finish_sb(telnet); + +} + /** * Waits for data on the given file descriptor for up to one second. The * return value is identical to that of select(): 0 on timeout, < 0 on diff --git a/src/protocols/telnet/telnet_client.h b/src/protocols/telnet/telnet_client.h index 403d5a77..6c72bde5 100644 --- a/src/protocols/telnet/telnet_client.h +++ b/src/protocols/telnet/telnet_client.h @@ -40,5 +40,11 @@ void* guac_telnet_client_thread(void* data); */ void guac_telnet_send_naws(telnet_t* telnet, uint16_t width, uint16_t height); +/** + * Sends the given username by setting the remote USER environment variable + * using the telnet NEW-ENVIRON option. + */ +void guac_telnet_send_user(telnet_t* telnet, const char* username); + #endif