From 1a268e53058a4f7946358fdfb6dc439a67c7a772 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 --- terminal.go | 13 +++++++++++-- terminal_test.go | 20 +++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/terminal.go b/terminal.go index dd7378c..d1b4fca 100644 --- a/terminal.go +++ b/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/terminal_test.go b/terminal_test.go index 4e7a0c6..2a2facc 100644 --- a/terminal_test.go +++ b/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 {