Github user mike-jumper commented on a diff in the pull request: https://github.com/apache/guacamole-server/pull/187#discussion_r219631546 --- Diff: src/protocols/telnet/telnet.c --- @@ -82,57 +83,178 @@ static int __guac_telnet_write_all(int fd, const char* buffer, int size) { } /** - * Searches for a line matching the stored password regex, appending the given - * buffer to the internal pattern matching buffer. The internal pattern match - * buffer is cleared whenever a newline is read. Returns TRUE if a match is found and the - * value is sent. + * Matches the given line against the given regex, returning true and sending + * the given value if a match is found. An enter keypress is automatically + * sent after the value is sent. + * + * @param client + * The guac_client associated with the telnet session. + * + * @param regex + * The regex to search for within the given line buffer. + * + * @param value + * The string value to send through STDIN of the telnet session if a + * match is found, or NULL if no value should be sent. + * + * @param line_buffer + * The line of character data to test. + * + * @return + * true if a match is found, false otherwise. */ -static bool __guac_telnet_regex_search(guac_client* client, regex_t* regex, char* value, const char* buffer, int size) { +static bool guac_telnet_regex_exec(guac_client* client, regex_t* regex, + const char* value, const char* line_buffer) { - static char line_buffer[1024] = {0}; - static int length = 0; + guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; + + /* Send value upon match */ + if (regexec(regex, line_buffer, 0, NULL, 0) == 0) { + + /* Send value */ + if (value != NULL) { + guac_terminal_send_string(telnet_client->term, value); + guac_terminal_send_string(telnet_client->term, "\x0D"); + } + + /* Stop searching for prompt */ + return true; + + } + + return false; + +} + +/** + * Matches the given line against the various stored regexes, automatically + * sending the configured username, password, or reporting login + * success/failure depending on context. If no search is in progress, either + * because no regexes have been defined or because all applicable searches have + * completed, this function has no effect. + * + * @param client + * The guac_client associated with the telnet session. + * + * @param line_buffer + * The line of character data to test. + */ +static void guac_telnet_search_line(guac_client* client, const char* line_buffer) { guac_telnet_client* telnet_client = (guac_telnet_client*) client->data; + guac_telnet_settings* settings = telnet_client->settings; + + /* Continue search for username prompt */ + if (settings->username_regex != NULL) { + if (guac_telnet_regex_exec(client, settings->username_regex, + settings->username, line_buffer)) { + guac_client_log(client, GUAC_LOG_DEBUG, "Username sent"); + guac_telnet_regex_free(&settings->username_regex); + } + } + + /* Continue search for password prompt */ + if (settings->password_regex != NULL) { + if (guac_telnet_regex_exec(client, settings->password_regex, + settings->password, line_buffer)) { - int i; - const char* current; + guac_client_log(client, GUAC_LOG_DEBUG, "Password sent"); - /* Ensure line buffer contains only the most recent line */ - current = buffer; - for (i = 0; i < size; i++) { + /* Do not continue searching for username/password once password is sent */ + guac_telnet_regex_free(&settings->username_regex); --- End diff -- Yep. There is a situation where `username_regex` will still not be NULL, yet the password regex will match. While no telnet server has support for sending the password as a dedicated authentication phase, some telnet servers have support for sending the username directly. This is accomplished through sending an environment variable called `USER`: https://github.com/apache/guacamole-server/blob/332e187813595fc2e769f3e29c0582b7ec726ea1/src/protocols/telnet/telnet.c#L222-L229 As this isn't guaranteed, the heuristics for recognizing username/password prompts have to be somewhat forgiving. It's possible that there will be a username prompt followed by a password prompt, and it's possible that there will be only a password prompt.
---