From ecb85df213405b7d32e4d73cb5bbaace2ec88881 Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Sun, 19 Jan 2020 09:47:15 +1100 Subject: [PATCH] ssh/terminal: adjust ReadConsole rules on windows CL 212377 changed end of input character on windows - from \n to \r. But CL 212377 did not adjust ReadConsole accordingly. For example, after CL 212377 \n was still used to end of password processing, and \r was ignored. This CL swaps these rules - \r is now used to end password processing, and \n are ignored. The change only affects windows, all non windows code should work as before. This CL also adjusts TestReadPasswordLineEnd to fit new rules. Fixes golang/go#36609 Change-Id: I027bf80d10e7d4d4b17ff0264935d14b8bea9097 Reviewed-on: https://go-review.googlesource.com/c/crypto/+/215417 Run-TryBot: Alex Brainman TryBot-Result: Gobot Gobot Reviewed-by: Filippo Valsorda --- ssh/terminal/terminal.go | 13 +++++++++++-- ssh/terminal/terminal_test.go | 20 +++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/ssh/terminal/terminal.go b/ssh/terminal/terminal.go index dd7378c8a3..d1b4fca3a9 100644 --- a/ssh/terminal/terminal.go +++ b/ssh/terminal/terminal.go @@ -7,6 +7,7 @@ package terminal import ( "bytes" "io" + "runtime" "strconv" "sync" "unicode/utf8" @@ -939,6 +940,8 @@ func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { // readPasswordLine reads from reader until it finds \n or io.EOF. // The slice returned does not include the \n. // readPasswordLine also ignores any \r it finds. +// Windows uses \r as end of line. So, on Windows, readPasswordLine +// reads until it finds \r and ignores any \n it finds during processing. func readPasswordLine(reader io.Reader) ([]byte, error) { var buf [1]byte var ret []byte @@ -952,9 +955,15 @@ func readPasswordLine(reader io.Reader) ([]byte, error) { ret = ret[:len(ret)-1] } case '\n': - return ret, nil + if runtime.GOOS != "windows" { + return ret, nil + } + // otherwise ignore \n case '\r': - // remove \r from passwords on Windows + if runtime.GOOS == "windows" { + return ret, nil + } + // otherwise ignore \r default: ret = append(ret, buf[0]) } diff --git a/ssh/terminal/terminal_test.go b/ssh/terminal/terminal_test.go index 4e7a0c658f..2a2faccd03 100644 --- a/ssh/terminal/terminal_test.go +++ b/ssh/terminal/terminal_test.go @@ -323,18 +323,32 @@ func TestTerminalSetSize(t *testing.T) { } func TestReadPasswordLineEnd(t *testing.T) { - var tests = []struct { + type testType struct { input string want string - }{ - {"\n", ""}, + } + var tests = []testType{ {"\r\n", ""}, {"test\r\n", "test"}, + {"test\r", "test"}, + {"test\n", "test"}, {"testtesttesttes\n", "testtesttesttes"}, {"testtesttesttes\r\n", "testtesttesttes"}, {"testtesttesttesttest\n", "testtesttesttesttest"}, {"testtesttesttesttest\r\n", "testtesttesttesttest"}, + {"\btest", "test"}, + {"t\best", "est"}, + {"te\bst", "tst"}, + {"test\b", "tes"}, + {"test\b\r\n", "tes"}, + {"test\b\n", "tes"}, + {"test\b\r", "tes"}, + } + eol := "\n" + if runtime.GOOS == "windows" { + eol = "\r" } + tests = append(tests, testType{eol, ""}) for _, test := range tests { buf := new(bytes.Buffer) if _, err := buf.WriteString(test.input); err != nil {