go.crypto/ssh: support OpenSSH keepalives

Fixes golang/go#4552.

R=minux.ma, agl
CC=golang-dev
https://golang.org/cl/6948059
This commit is contained in:
Eric Milliken
2012-12-18 11:33:58 -05:00
committed by Adam Langley
parent d95b28330d
commit 61ab4d36df
3 changed files with 46 additions and 1 deletions
+6
View File
@@ -309,6 +309,12 @@ func (c *ClientConn) mainLoop() {
// invalid window update
return
}
case *globalRequestMsg:
// This handles keepalive messages and matches
// the behaviour of OpenSSH.
if msg.WantReply {
c.writePacket(marshal(msgRequestFailure, globalRequestFailureMsg{}))
}
case *globalRequestSuccessMsg, *globalRequestFailureMsg:
c.globalRequest.response <- msg
case *disconnectMsg:
+7 -1
View File
@@ -404,7 +404,13 @@ func (s *Session) wait() error {
}
wm.lang = safeString(string(lang))
default:
return fmt.Errorf("wait: unexpected channel request: %v", msg)
// This handles keepalives and matches
// OpenSSH's behaviour.
if msg.WantReply {
s.writePacket(marshal(msgChannelFailure, channelRequestFailureMsg{
PeersId: s.remoteId,
}))
}
}
default:
return fmt.Errorf("wait: unexpected packet %T received: %v", msg, msg)
+33
View File
@@ -498,6 +498,24 @@ func TestServerWindow(t *testing.T) {
}
}
// Verify the client can handle a keepalive packet from the server.
func TestClientHandlesKeepalives(t *testing.T) {
conn := dial(channelKeepaliveSender, t)
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
t.Fatal(err)
}
defer session.Close()
if err := session.Shell(); err != nil {
t.Fatalf("Unable to execute command: %v", err)
}
err = session.Wait()
if err != nil {
t.Fatalf("expected nil but got: %v", err)
}
}
type exitStatusMsg struct {
PeersId uint32
Request string
@@ -687,3 +705,18 @@ func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, erro
}
return written, nil
}
func channelKeepaliveSender(ch *serverChan, t *testing.T) {
defer ch.Close()
shell := newServerShell(ch, "> ")
readLine(shell, t)
msg := channelRequestMsg{
PeersId: ch.remoteId,
Request: "keepalive@openssh.com",
WantReply: true,
}
if err := ch.writePacket(marshal(msgChannelRequest, msg)); err != nil {
t.Errorf("unable to send channel keepalive request: %v", err)
}
sendStatus(0, ch, t)
}