mirror of
https://github.com/golang/go
synced 2024-11-21 21:54:40 -07:00
exp/ssh: general cleanups for client support
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
This commit is contained in:
parent
1db31f8933
commit
ec158f77bd
@ -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
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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")
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user