]> Cypherpunks repositories - gostls13.git/commitdiff
exp/ssh: general cleanups for client support
authorDave Cheney <dave@cheney.net>
Tue, 18 Oct 2011 16:54:48 +0000 (12:54 -0400)
committerAdam Langley <agl@golang.org>
Tue, 18 Oct 2011 16:54:48 +0000 (12:54 -0400)
common.go:
* simplify findAgreedAlgorithms.
* add channelExtendedData support.

messages.go:
* add clientExtendedData.

server.go:
*  use simplified findAgreedAlgorithms.

server_shell.go:
* fix shadowed err return value.

transport.go:
* introduce separate cipher, mac and compression for each direction.
* added filteredConn and packetWriter interfaces.
* newTransport requires a source of randomness.

R=golang-dev, agl, rsc
CC=golang-dev
https://golang.org/cl/5285044

src/pkg/exp/ssh/common.go
src/pkg/exp/ssh/messages.go
src/pkg/exp/ssh/server.go
src/pkg/exp/ssh/server_shell.go
src/pkg/exp/ssh/transport.go

index 441c5b17d381ef287c73b1e7cd507748759d43d5..739bd2f9c5f36c6f556a3450eee6905e3d0c80c2 100644 (file)
@@ -83,7 +83,7 @@ func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo
        return
 }
 
-func findAgreedAlgorithms(clientToServer, serverToClient *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
+func findAgreedAlgorithms(transport *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
        kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
        if !ok {
                return
@@ -94,32 +94,32 @@ func findAgreedAlgorithms(clientToServer, serverToClient *transport, clientKexIn
                return
        }
 
-       clientToServer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+       transport.writer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
        if !ok {
                return
        }
 
-       serverToClient.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+       transport.reader.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
        if !ok {
                return
        }
 
-       clientToServer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+       transport.writer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
        if !ok {
                return
        }
 
-       serverToClient.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+       transport.reader.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
        if !ok {
                return
        }
 
-       clientToServer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+       transport.writer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
        if !ok {
                return
        }
 
-       serverToClient.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+       transport.reader.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
        if !ok {
                return
        }
index 851c89747dd4fe2dd363678c47db9e3bcb498c71..1d0bc5774265350f008a2a0d9c87b333af7489c4 100644 (file)
@@ -150,6 +150,13 @@ type channelData struct {
        Payload []byte `ssh:"rest"`
 }
 
+// See RFC 4254, section 5.2.
+type channelExtendedData struct {
+       PeersId  uint32
+       Datatype uint32
+       Data     string
+}
+
 type channelRequestMsg struct {
        PeersId             uint32
        Request             string
@@ -607,6 +614,8 @@ func decode(packet []byte) interface{} {
                msg = new(windowAdjustMsg)
        case msgChannelData:
                msg = new(channelData)
+       case msgChannelExtendedData:
+               msg = new(channelExtendedData)
        case msgChannelEOF:
                msg = new(channelEOFMsg)
        case msgChannelClose:
index 9e7a255ae3eb31a8c5c3cb701ea8719413771b1c..410cafc44c29ef95a3f7825e98aacb35f5b7d613 100644 (file)
@@ -260,7 +260,7 @@ func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubK
 // Handshake performs an SSH transport and client authentication on the given ServerConnection.
 func (s *ServerConnection) Handshake(conn net.Conn) os.Error {
        var magics handshakeMagics
-       s.transport = newTransport(conn)
+       s.transport = newTransport(conn, rand.Reader)
 
        if _, err := conn.Write(serverVersion); err != nil {
                return err
@@ -302,7 +302,7 @@ func (s *ServerConnection) Handshake(conn net.Conn) os.Error {
                return err
        }
 
-       kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, s.transport, &clientKexInit, &serverKexInit)
+       kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, &clientKexInit, &serverKexInit)
        if !ok {
                return os.NewError("ssh: no common algorithms")
        }
index 53a3241f5e04eefa2bb511d70ab23cf178c55531..0e9967a90911c13255488239d1e9e55e3790efa6 100644 (file)
@@ -340,7 +340,8 @@ func (ss *ServerShell) ReadLine() (line string, err os.Error) {
                // ss.remainder is a slice at the beginning of ss.inBuf
                // containing a partial key sequence
                readBuf := ss.inBuf[len(ss.remainder):]
-               n, err := ss.c.Read(readBuf)
+               var n int
+               n, err = ss.c.Read(readBuf)
                if err == nil {
                        ss.remainder = ss.inBuf[:n+len(ss.remainder)]
                        rest := ss.remainder
index 77660a26573873cb2eb27900691b6db8f9f14dd5..5994004d86656ba854a8e8c010bd36575751a983 100644 (file)
@@ -10,7 +10,6 @@ import (
        "crypto/aes"
        "crypto/cipher"
        "crypto/hmac"
-       "crypto/rand"
        "crypto/subtle"
        "hash"
        "io"
@@ -23,17 +22,33 @@ const (
        paddingMultiple = 16 // TODO(dfc) does this need to be configurable?
 )
 
+// filteredConn reduces the set of methods exposed when embeddeding
+// a net.Conn inside ssh.transport.
+// TODO(dfc) suggestions for a better name will be warmly received.
+type filteredConn interface {
+       // Close closes the connection.
+       Close() os.Error
+
+       // LocalAddr returns the local network address.
+       LocalAddr() net.Addr
+
+       // RemoteAddr returns the remote network address.
+       RemoteAddr() net.Addr
+}
+
+// Types implementing packetWriter provide the ability to send packets to
+// an SSH peer.
+type packetWriter interface {
+       // Encrypt and send a packet of data to the remote peer.
+       writePacket(packet []byte) os.Error
+}
+
 // transport represents the SSH connection to the remote peer.
 type transport struct {
        reader
        writer
 
-       cipherAlgo      string
-       macAlgo         string
-       compressionAlgo string
-
-       Close      func() os.Error
-       RemoteAddr func() net.Addr
+       filteredConn
 }
 
 // reader represents the incoming connection state.
@@ -57,6 +72,10 @@ type common struct {
        seqNum uint32
        mac    hash.Hash
        cipher cipher.Stream
+
+       cipherAlgo      string
+       macAlgo         string
+       compressionAlgo string
 }
 
 // Read and decrypt a single packet from the remote peer.
@@ -204,22 +223,17 @@ func (t *transport) sendMessage(typ uint8, msg interface{}) os.Error {
        return t.writePacket(packet)
 }
 
-func newTransport(conn net.Conn) *transport {
+func newTransport(conn net.Conn, rand io.Reader) *transport {
        return &transport{
                reader: reader{
                        Reader: bufio.NewReader(conn),
                },
                writer: writer{
                        Writer: bufio.NewWriter(conn),
-                       rand:   rand.Reader,
+                       rand:   rand,
                        Mutex:  new(sync.Mutex),
                },
-               Close: func() os.Error {
-                       return conn.Close()
-               },
-               RemoteAddr: func() net.Addr {
-                       return conn.RemoteAddr()
-               },
+               filteredConn: conn,
        }
 }