ssh: handle bad servers better.

This change prevents bad servers from crashing a client by sending an
invalid channel ID. It also makes the client disconnect in more cases
of invalid messages from a server and cleans up the client channels
in the event of a disconnect.

R=dave
CC=golang-dev
https://golang.org/cl/6099050
diff --git a/ssh/session_test.go b/ssh/session_test.go
index df66e1d..df97fcf 100644
--- a/ssh/session_test.go
+++ b/ssh/session_test.go
@@ -275,6 +275,20 @@
 	}
 }
 
+func TestInvalidServerMessage(t *testing.T) {
+	conn := dial(sendInvalidRecord, t)
+	defer conn.Close()
+	session, err := conn.NewSession()
+	if err != nil {
+		t.Fatalf("Unable to request new session: %s", err)
+	}
+	// Make sure that we closed all the clientChans when the connection
+	// failed.
+	session.wait()
+
+	defer session.Close()
+}
+
 type exitStatusMsg struct {
 	PeersId   uint32
 	Request   string
@@ -373,3 +387,14 @@
 	}
 	ch.serverConn.writePacket(marshal(msgChannelRequest, sig))
 }
+
+func sendInvalidRecord(ch *channel) {
+	defer ch.Close()
+	packet := make([]byte, 1+4+4+1)
+	packet[0] = msgChannelData
+	marshalUint32(packet[1:], 29348723 /* invalid channel id */)
+	marshalUint32(packet[5:], 1)
+	packet[9] = 42
+
+	ch.serverConn.writePacket(packet)
+}