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
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
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
}
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
msg = new(windowAdjustMsg)
case msgChannelData:
msg = new(channelData)
+ case msgChannelExtendedData:
+ msg = new(channelExtendedData)
case msgChannelEOF:
msg = new(channelEOFMsg)
case msgChannelClose:
// 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
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")
}
// 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
"crypto/aes"
"crypto/cipher"
"crypto/hmac"
- "crypto/rand"
"crypto/subtle"
"hash"
"io"
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.
seqNum uint32
mac hash.Hash
cipher cipher.Stream
+
+ cipherAlgo string
+ macAlgo string
+ compressionAlgo string
}
// Read and decrypt a single packet from the remote peer.
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,
}
}