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.
---