Alex Dowad
2015-Oct-12 18:51 UTC
[PATCH] ANSI terminal escape sequences do not affect processing of SSH escapes
Even when the user has not pressed a key, ANSI-compatible terminal emulators can send escape sequences to ssh's stdin at any time. For example, any time that the server sends an "<ESC>[6n" (query cursor position) sequence, an ANSI-compatible terminal will send back "<ESC>[<ROW>;<COLUMN>R". ssh sees these escape sequences just as if they were characters typed in by the user. This causes problems if the user is attempting to type an SSH escape sequence, starting with "<ENTER>~". Therefore, when scanning user input for SSH escape sequences, skip over any ANSI terminal control sequences which appear in the input. --- Dear OpenSSH-Portable Devs, Please CC replies as I am not (yet) a subscriber! I should probably send this upstream, but I've been searching for the right mailing list and haven't found anything. Your feedback will be appreciated. I've read your style guidelines and attempted to follow them. This patch was prompted by the observation that SSH escapes (using ~) don't work at all when the remote shell is BusyBox ash (used by Alpine Linux and some other minimalist and/or embedded Linux distributions). This is because the BusyBox shell *always* sends a "query cursor position" terminal control escape sequence each time you press the <ENTER> key. Quick as a flash, as your pinky finger is descending towards the tilda key, the terminal sends back a "report cursor position" sequence. The result is that the SSH client *never* sees your tilda as immediately following the newline. Those ANSI terminal control sequences always begin with "<ESC>[" and end with an alphabetic character. Hence the call to isalpha() in my code. Can someone confirm that isalpha() *always* treats a-z and A-Z as alphabetic, no matter what the locale is? Thank you, Alex Dowad clientloop.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/clientloop.c b/clientloop.c index 87ceb3d..b15e470 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1096,7 +1096,17 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, /* Get one character at a time. */ ch = buf[i]; - if (*escape_pendingp) { + /* ANSI terminal escape sequences may appear anywhere in input stream. */ + /* They do not affect our processing of our own escapes. */ + if (ch == 0x1B && buf[i+1] == '[') { + for (; i < (u_int)len; i++) { + ch = buf[i]; + buffer_put_char(bin, ch); + if (isalpha(ch)) + break; + } + continue; + } else if (*escape_pendingp) { /* We have previously seen an escape character. */ /* Clear the flag now. */ *escape_pendingp = 0; -- 2.0.0.GIT
Damien Miller
2015-Oct-12 19:28 UTC
[PATCH] ANSI terminal escape sequences do not affect processing of SSH escapes
Hi, Thanks for this - could I ask you to create a bug at https://bugzilla.mindrot.org for this and attach your patch? This will make sure it doesn't get lost. Thanks, Damien On Mon, 12 Oct 2015, Alex Dowad wrote:> Even when the user has not pressed a key, ANSI-compatible terminal emulators > can send escape sequences to ssh's stdin at any time. For example, any time that > the server sends an "<ESC>[6n" (query cursor position) sequence, an > ANSI-compatible terminal will send back "<ESC>[<ROW>;<COLUMN>R". ssh sees these > escape sequences just as if they were characters typed in by the user. This > causes problems if the user is attempting to type an SSH escape sequence, > starting with "<ENTER>~". > > Therefore, when scanning user input for SSH escape sequences, skip over any > ANSI terminal control sequences which appear in the input. > --- > > Dear OpenSSH-Portable Devs, > > Please CC replies as I am not (yet) a subscriber! > > I should probably send this upstream, but I've been searching for the right > mailing list and haven't found anything. Your feedback will be appreciated. > I've read your style guidelines and attempted to follow them. > > This patch was prompted by the observation that SSH escapes (using ~) don't work > at all when the remote shell is BusyBox ash (used by Alpine Linux and some > other minimalist and/or embedded Linux distributions). > > This is because the BusyBox shell *always* sends a "query cursor position" > terminal control escape sequence each time you press the <ENTER> key. > Quick as a flash, as your pinky finger is descending towards the tilda key, > the terminal sends back a "report cursor position" sequence. The result is > that the SSH client *never* sees your tilda as immediately following the > newline. > > Those ANSI terminal control sequences always begin with "<ESC>[" and end > with an alphabetic character. Hence the call to isalpha() in my code. > Can someone confirm that isalpha() *always* treats a-z and A-Z as alphabetic, > no matter what the locale is? > > Thank you, > Alex Dowad > > clientloop.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/clientloop.c b/clientloop.c > index 87ceb3d..b15e470 100644 > --- a/clientloop.c > +++ b/clientloop.c > @@ -1096,7 +1096,17 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, > /* Get one character at a time. */ > ch = buf[i]; > > - if (*escape_pendingp) { > + /* ANSI terminal escape sequences may appear anywhere in input stream. */ > + /* They do not affect our processing of our own escapes. */ > + if (ch == 0x1B && buf[i+1] == '[') { > + for (; i < (u_int)len; i++) { > + ch = buf[i]; > + buffer_put_char(bin, ch); > + if (isalpha(ch)) > + break; > + } > + continue; > + } else if (*escape_pendingp) { > /* We have previously seen an escape character. */ > /* Clear the flag now. */ > *escape_pendingp = 0; > -- > 2.0.0.GIT > > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev >