go.crypto/ssh: allow zero sized window adjustments

The RFC doesn't prohibit zero sized window adjustments and
there is evidence of well known clients using them in the
wild.

R=agl, kardianos, gustav.paul
CC=golang-dev
https://golang.org/cl/6209082
This commit is contained in:
Dave Cheney
2012-05-22 12:04:51 +10:00
parent 36d74d6fed
commit 55aa08130e
2 changed files with 55 additions and 1 deletions
+2 -1
View File
@@ -300,8 +300,9 @@ type window struct {
// add adds win to the amount of window available
// for consumers.
func (w *window) add(win uint32) bool {
// a zero sized window adjust is a noop.
if win == 0 {
return false
return true
}
w.L.Lock()
if w.win+win < win {
+53
View File
@@ -294,6 +294,50 @@ func TestInvalidServerMessage(t *testing.T) {
defer session.Close()
}
// In the wild some clients (and servers) send zero sized window updates.
// Test that the client can continue after receiving a zero sized update.
func TestClientZeroWindowAdjust(t *testing.T) {
conn := dial(sendZeroWindowAdjust, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
err = session.Wait()
if err != nil {
t.Fatalf("expected nil but got %s", err)
}
}
// In the wild some clients (and servers) send zero sized window updates.
// Test that the server can continue after receiving a zero size update.
func TestServerZeroWindowAdjust(t *testing.T) {
conn := dial(exitStatusZeroHandler, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatalf("Unable to request new session: %s", err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %s", err)
}
// send a bogus zero sized window update
session.clientChan.sendWindowAdj(0)
err = session.Wait()
if err != nil {
t.Fatalf("expected nil but got %s", err)
}
}
type exitStatusMsg struct {
PeersId uint32
Request string
@@ -403,3 +447,12 @@ func sendInvalidRecord(ch *serverChan) {
ch.serverConn.writePacket(packet)
}
func sendZeroWindowAdjust(ch *serverChan) {
defer ch.Close()
// send a bogus zero sized window update
ch.sendWindowAdj(0)
shell := newServerShell(ch, "> ")
shell.ReadLine()
sendStatus(0, ch)
}