diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/ssh')
19 files changed, 536 insertions, 290 deletions
| diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go index dce7682..b1808dd 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/client.go +++ b/vendor/golang.org/x/crypto/ssh/agent/client.go @@ -8,7 +8,7 @@  // ssh-agent process using the sample server.  //  // References: -//  [PROTOCOL.agent]:    http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD +//  [PROTOCOL.agent]: https://tools.ietf.org/html/draft-miller-ssh-agent-00  package agent // import "golang.org/x/crypto/ssh/agent"  import ( @@ -98,7 +98,7 @@ const (  	agentAddIdentity         = 17  	agentRemoveIdentity      = 18  	agentRemoveAllIdentities = 19 -	agentAddIdConstrained    = 25 +	agentAddIDConstrained    = 25  	// 3.3 Key-type independent requests from client to agent  	agentAddSmartcardKey            = 20 @@ -515,7 +515,7 @@ func (c *client) insertKey(s interface{}, comment string, constraints []byte) er  	// if constraints are present then the message type needs to be changed.  	if len(constraints) != 0 { -		req[0] = agentAddIdConstrained +		req[0] = agentAddIDConstrained  	}  	resp, err := c.call(req) @@ -577,11 +577,11 @@ func (c *client) Add(key AddedKey) error {  		constraints = append(constraints, agentConstrainConfirm)  	} -	if cert := key.Certificate; cert == nil { +	cert := key.Certificate +	if cert == nil {  		return c.insertKey(key.PrivateKey, key.Comment, constraints) -	} else { -		return c.insertCert(key.PrivateKey, cert, key.Comment, constraints)  	} +	return c.insertCert(key.PrivateKey, cert, key.Comment, constraints)  }  func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string, constraints []byte) error { @@ -633,7 +633,7 @@ func (c *client) insertCert(s interface{}, cert *ssh.Certificate, comment string  	// if constraints are present then the message type needs to be changed.  	if len(constraints) != 0 { -		req[0] = agentAddIdConstrained +		req[0] = agentAddIDConstrained  	}  	signer, err := ssh.NewSignerFromKey(s) diff --git a/vendor/golang.org/x/crypto/ssh/agent/keyring.go b/vendor/golang.org/x/crypto/ssh/agent/keyring.go index a6ba06a..1a51632 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/keyring.go +++ b/vendor/golang.org/x/crypto/ssh/agent/keyring.go @@ -102,7 +102,7 @@ func (r *keyring) Unlock(passphrase []byte) error {  	if !r.locked {  		return errors.New("agent: not locked")  	} -	if len(passphrase) != len(r.passphrase) || 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) { +	if 1 != subtle.ConstantTimeCompare(passphrase, r.passphrase) {  		return fmt.Errorf("agent: incorrect passphrase")  	} diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go index 321e48a..2e4692c 100644 --- a/vendor/golang.org/x/crypto/ssh/agent/server.go +++ b/vendor/golang.org/x/crypto/ssh/agent/server.go @@ -148,7 +148,7 @@ func (s *server) processRequest(data []byte) (interface{}, error) {  		}  		return rep, nil -	case agentAddIdConstrained, agentAddIdentity: +	case agentAddIDConstrained, agentAddIdentity:  		return nil, s.insertIdentity(data)  	} diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go index b1f0220..42106f3 100644 --- a/vendor/golang.org/x/crypto/ssh/certs.go +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -44,7 +44,9 @@ type Signature struct {  const CertTimeInfinity = 1<<64 - 1  // An Certificate represents an OpenSSH certificate as defined in -// [PROTOCOL.certkeys]?rev=1.8. +// [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the +// PublicKey interface, so it can be unmarshaled using +// ParsePublicKey.  type Certificate struct {  	Nonce           []byte  	Key             PublicKey @@ -340,10 +342,10 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis  // the signature of the certificate.  func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {  	if c.IsRevoked != nil && c.IsRevoked(cert) { -		return fmt.Errorf("ssh: certicate serial %d revoked", cert.Serial) +		return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial)  	} -	for opt, _ := range cert.CriticalOptions { +	for opt := range cert.CriticalOptions {  		// sourceAddressCriticalOption will be enforced by  		// serverAuthenticate  		if opt == sourceAddressCriticalOption { diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go index 195530e..c0834c0 100644 --- a/vendor/golang.org/x/crypto/ssh/channel.go +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -205,32 +205,32 @@ type channel struct {  // writePacket sends a packet. If the packet is a channel close, it updates  // sentClose. This method takes the lock c.writeMu. -func (c *channel) writePacket(packet []byte) error { -	c.writeMu.Lock() -	if c.sentClose { -		c.writeMu.Unlock() +func (ch *channel) writePacket(packet []byte) error { +	ch.writeMu.Lock() +	if ch.sentClose { +		ch.writeMu.Unlock()  		return io.EOF  	} -	c.sentClose = (packet[0] == msgChannelClose) -	err := c.mux.conn.writePacket(packet) -	c.writeMu.Unlock() +	ch.sentClose = (packet[0] == msgChannelClose) +	err := ch.mux.conn.writePacket(packet) +	ch.writeMu.Unlock()  	return err  } -func (c *channel) sendMessage(msg interface{}) error { +func (ch *channel) sendMessage(msg interface{}) error {  	if debugMux { -		log.Printf("send(%d): %#v", c.mux.chanList.offset, msg) +		log.Printf("send(%d): %#v", ch.mux.chanList.offset, msg)  	}  	p := Marshal(msg) -	binary.BigEndian.PutUint32(p[1:], c.remoteId) -	return c.writePacket(p) +	binary.BigEndian.PutUint32(p[1:], ch.remoteId) +	return ch.writePacket(p)  }  // WriteExtended writes data to a specific extended stream. These streams are  // used, for example, for stderr. -func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { -	if c.sentEOF { +func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) { +	if ch.sentEOF {  		return 0, io.EOF  	}  	// 1 byte message type, 4 bytes remoteId, 4 bytes data length @@ -241,16 +241,16 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er  		opCode = msgChannelExtendedData  	} -	c.writeMu.Lock() -	packet := c.packetPool[extendedCode] +	ch.writeMu.Lock() +	packet := ch.packetPool[extendedCode]  	// We don't remove the buffer from packetPool, so  	// WriteExtended calls from different goroutines will be  	// flagged as errors by the race detector. -	c.writeMu.Unlock() +	ch.writeMu.Unlock()  	for len(data) > 0 { -		space := min(c.maxRemotePayload, len(data)) -		if space, err = c.remoteWin.reserve(space); err != nil { +		space := min(ch.maxRemotePayload, len(data)) +		if space, err = ch.remoteWin.reserve(space); err != nil {  			return n, err  		}  		if want := headerLength + space; uint32(cap(packet)) < want { @@ -262,13 +262,13 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er  		todo := data[:space]  		packet[0] = opCode -		binary.BigEndian.PutUint32(packet[1:], c.remoteId) +		binary.BigEndian.PutUint32(packet[1:], ch.remoteId)  		if extendedCode > 0 {  			binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))  		}  		binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))  		copy(packet[headerLength:], todo) -		if err = c.writePacket(packet); err != nil { +		if err = ch.writePacket(packet); err != nil {  			return n, err  		} @@ -276,14 +276,14 @@ func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err er  		data = data[len(todo):]  	} -	c.writeMu.Lock() -	c.packetPool[extendedCode] = packet -	c.writeMu.Unlock() +	ch.writeMu.Lock() +	ch.packetPool[extendedCode] = packet +	ch.writeMu.Unlock()  	return n, err  } -func (c *channel) handleData(packet []byte) error { +func (ch *channel) handleData(packet []byte) error {  	headerLen := 9  	isExtendedData := packet[0] == msgChannelExtendedData  	if isExtendedData { @@ -303,7 +303,7 @@ func (c *channel) handleData(packet []byte) error {  	if length == 0 {  		return nil  	} -	if length > c.maxIncomingPayload { +	if length > ch.maxIncomingPayload {  		// TODO(hanwen): should send Disconnect?  		return errors.New("ssh: incoming packet exceeds maximum payload size")  	} @@ -313,21 +313,21 @@ func (c *channel) handleData(packet []byte) error {  		return errors.New("ssh: wrong packet length")  	} -	c.windowMu.Lock() -	if c.myWindow < length { -		c.windowMu.Unlock() +	ch.windowMu.Lock() +	if ch.myWindow < length { +		ch.windowMu.Unlock()  		// TODO(hanwen): should send Disconnect with reason?  		return errors.New("ssh: remote side wrote too much")  	} -	c.myWindow -= length -	c.windowMu.Unlock() +	ch.myWindow -= length +	ch.windowMu.Unlock()  	if extended == 1 { -		c.extPending.write(data) +		ch.extPending.write(data)  	} else if extended > 0 {  		// discard other extended data.  	} else { -		c.pending.write(data) +		ch.pending.write(data)  	}  	return nil  } @@ -384,31 +384,31 @@ func (c *channel) close() {  // responseMessageReceived is called when a success or failure message is  // received on a channel to check that such a message is reasonable for the  // given channel. -func (c *channel) responseMessageReceived() error { -	if c.direction == channelInbound { +func (ch *channel) responseMessageReceived() error { +	if ch.direction == channelInbound {  		return errors.New("ssh: channel response message received on inbound channel")  	} -	if c.decided { +	if ch.decided {  		return errors.New("ssh: duplicate response received for channel")  	} -	c.decided = true +	ch.decided = true  	return nil  } -func (c *channel) handlePacket(packet []byte) error { +func (ch *channel) handlePacket(packet []byte) error {  	switch packet[0] {  	case msgChannelData, msgChannelExtendedData: -		return c.handleData(packet) +		return ch.handleData(packet)  	case msgChannelClose: -		c.sendMessage(channelCloseMsg{PeersId: c.remoteId}) -		c.mux.chanList.remove(c.localId) -		c.close() +		ch.sendMessage(channelCloseMsg{PeersID: ch.remoteId}) +		ch.mux.chanList.remove(ch.localId) +		ch.close()  		return nil  	case msgChannelEOF:  		// RFC 4254 is mute on how EOF affects dataExt messages but  		// it is logical to signal EOF at the same time. -		c.extPending.eof() -		c.pending.eof() +		ch.extPending.eof() +		ch.pending.eof()  		return nil  	} @@ -419,24 +419,24 @@ func (c *channel) handlePacket(packet []byte) error {  	switch msg := decoded.(type) {  	case *channelOpenFailureMsg: -		if err := c.responseMessageReceived(); err != nil { +		if err := ch.responseMessageReceived(); err != nil {  			return err  		} -		c.mux.chanList.remove(msg.PeersId) -		c.msg <- msg +		ch.mux.chanList.remove(msg.PeersID) +		ch.msg <- msg  	case *channelOpenConfirmMsg: -		if err := c.responseMessageReceived(); err != nil { +		if err := ch.responseMessageReceived(); err != nil {  			return err  		}  		if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {  			return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)  		} -		c.remoteId = msg.MyId -		c.maxRemotePayload = msg.MaxPacketSize -		c.remoteWin.add(msg.MyWindow) -		c.msg <- msg +		ch.remoteId = msg.MyID +		ch.maxRemotePayload = msg.MaxPacketSize +		ch.remoteWin.add(msg.MyWindow) +		ch.msg <- msg  	case *windowAdjustMsg: -		if !c.remoteWin.add(msg.AdditionalBytes) { +		if !ch.remoteWin.add(msg.AdditionalBytes) {  			return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)  		}  	case *channelRequestMsg: @@ -444,12 +444,12 @@ func (c *channel) handlePacket(packet []byte) error {  			Type:      msg.Request,  			WantReply: msg.WantReply,  			Payload:   msg.RequestSpecificData, -			ch:        c, +			ch:        ch,  		} -		c.incomingRequests <- &req +		ch.incomingRequests <- &req  	default: -		c.msg <- msg +		ch.msg <- msg  	}  	return nil  } @@ -488,23 +488,23 @@ func (e *extChannel) Read(data []byte) (n int, err error) {  	return e.ch.ReadExtended(data, e.code)  } -func (c *channel) Accept() (Channel, <-chan *Request, error) { -	if c.decided { +func (ch *channel) Accept() (Channel, <-chan *Request, error) { +	if ch.decided {  		return nil, nil, errDecidedAlready  	} -	c.maxIncomingPayload = channelMaxPacket +	ch.maxIncomingPayload = channelMaxPacket  	confirm := channelOpenConfirmMsg{ -		PeersId:       c.remoteId, -		MyId:          c.localId, -		MyWindow:      c.myWindow, -		MaxPacketSize: c.maxIncomingPayload, +		PeersID:       ch.remoteId, +		MyID:          ch.localId, +		MyWindow:      ch.myWindow, +		MaxPacketSize: ch.maxIncomingPayload,  	} -	c.decided = true -	if err := c.sendMessage(confirm); err != nil { +	ch.decided = true +	if err := ch.sendMessage(confirm); err != nil {  		return nil, nil, err  	} -	return c, c.incomingRequests, nil +	return ch, ch.incomingRequests, nil  }  func (ch *channel) Reject(reason RejectionReason, message string) error { @@ -512,7 +512,7 @@ func (ch *channel) Reject(reason RejectionReason, message string) error {  		return errDecidedAlready  	}  	reject := channelOpenFailureMsg{ -		PeersId:  ch.remoteId, +		PeersID:  ch.remoteId,  		Reason:   reason,  		Message:  message,  		Language: "en", @@ -541,7 +541,7 @@ func (ch *channel) CloseWrite() error {  	}  	ch.sentEOF = true  	return ch.sendMessage(channelEOFMsg{ -		PeersId: ch.remoteId}) +		PeersID: ch.remoteId})  }  func (ch *channel) Close() error { @@ -550,7 +550,7 @@ func (ch *channel) Close() error {  	}  	return ch.sendMessage(channelCloseMsg{ -		PeersId: ch.remoteId}) +		PeersID: ch.remoteId})  }  // Extended returns an io.ReadWriter that sends and receives data on the given, @@ -577,7 +577,7 @@ func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo  	}  	msg := channelRequestMsg{ -		PeersId:             ch.remoteId, +		PeersID:             ch.remoteId,  		Request:             name,  		WantReply:           wantReply,  		RequestSpecificData: payload, @@ -614,11 +614,11 @@ func (ch *channel) ackRequest(ok bool) error {  	var msg interface{}  	if !ok {  		msg = channelRequestFailureMsg{ -			PeersId: ch.remoteId, +			PeersID: ch.remoteId,  		}  	} else {  		msg = channelRequestSuccessMsg{ -			PeersId: ch.remoteId, +			PeersID: ch.remoteId,  		}  	}  	return ch.sendMessage(msg) diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go index 22bb30c..67b0126 100644 --- a/vendor/golang.org/x/crypto/ssh/cipher.go +++ b/vendor/golang.org/x/crypto/ssh/cipher.go @@ -16,6 +16,10 @@ import (  	"hash"  	"io"  	"io/ioutil" +	"math/bits" + +	"golang.org/x/crypto/internal/chacha20" +	"golang.org/x/crypto/poly1305"  )  const ( @@ -53,78 +57,78 @@ func newRC4(key, iv []byte) (cipher.Stream, error) {  	return rc4.NewCipher(key)  } -type streamCipherMode struct { -	keySize    int -	ivSize     int -	skip       int -	createFunc func(key, iv []byte) (cipher.Stream, error) +type cipherMode struct { +	keySize int +	ivSize  int +	create  func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error)  } -func (c *streamCipherMode) createStream(key, iv []byte) (cipher.Stream, error) { -	if len(key) < c.keySize { -		panic("ssh: key length too small for cipher") -	} -	if len(iv) < c.ivSize { -		panic("ssh: iv too small for cipher") -	} - -	stream, err := c.createFunc(key[:c.keySize], iv[:c.ivSize]) -	if err != nil { -		return nil, err -	} +func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream, error)) func(key, iv []byte, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +	return func(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +		stream, err := createFunc(key, iv) +		if err != nil { +			return nil, err +		} -	var streamDump []byte -	if c.skip > 0 { -		streamDump = make([]byte, 512) -	} +		var streamDump []byte +		if skip > 0 { +			streamDump = make([]byte, 512) +		} -	for remainingToDump := c.skip; remainingToDump > 0; { -		dumpThisTime := remainingToDump -		if dumpThisTime > len(streamDump) { -			dumpThisTime = len(streamDump) +		for remainingToDump := skip; remainingToDump > 0; { +			dumpThisTime := remainingToDump +			if dumpThisTime > len(streamDump) { +				dumpThisTime = len(streamDump) +			} +			stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) +			remainingToDump -= dumpThisTime  		} -		stream.XORKeyStream(streamDump[:dumpThisTime], streamDump[:dumpThisTime]) -		remainingToDump -= dumpThisTime -	} -	return stream, nil +		mac := macModes[algs.MAC].new(macKey) +		return &streamPacketCipher{ +			mac:       mac, +			etm:       macModes[algs.MAC].etm, +			macResult: make([]byte, mac.Size()), +			cipher:    stream, +		}, nil +	}  }  // cipherModes documents properties of supported ciphers. Ciphers not included  // are not supported and will not be negotiated, even if explicitly requested in  // ClientConfig.Crypto.Ciphers. -var cipherModes = map[string]*streamCipherMode{ +var cipherModes = map[string]*cipherMode{  	// Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms  	// are defined in the order specified in the RFC. -	"aes128-ctr": {16, aes.BlockSize, 0, newAESCTR}, -	"aes192-ctr": {24, aes.BlockSize, 0, newAESCTR}, -	"aes256-ctr": {32, aes.BlockSize, 0, newAESCTR}, +	"aes128-ctr": {16, aes.BlockSize, streamCipherMode(0, newAESCTR)}, +	"aes192-ctr": {24, aes.BlockSize, streamCipherMode(0, newAESCTR)}, +	"aes256-ctr": {32, aes.BlockSize, streamCipherMode(0, newAESCTR)},  	// Ciphers from RFC4345, which introduces security-improved arcfour ciphers.  	// They are defined in the order specified in the RFC. -	"arcfour128": {16, 0, 1536, newRC4}, -	"arcfour256": {32, 0, 1536, newRC4}, +	"arcfour128": {16, 0, streamCipherMode(1536, newRC4)}, +	"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},  	// Cipher defined in RFC 4253, which describes SSH Transport Layer Protocol.  	// Note that this cipher is not safe, as stated in RFC 4253: "Arcfour (and  	// RC4) has problems with weak keys, and should be used with caution."  	// RFC4345 introduces improved versions of Arcfour. -	"arcfour": {16, 0, 0, newRC4}, +	"arcfour": {16, 0, streamCipherMode(0, newRC4)}, -	// AES-GCM is not a stream cipher, so it is constructed with a -	// special case. If we add any more non-stream ciphers, we -	// should invest a cleaner way to do this. -	gcmCipherID: {16, 12, 0, nil}, +	// AEAD ciphers +	gcmCipherID:        {16, 12, newGCMCipher}, +	chacha20Poly1305ID: {64, 0, newChaCha20Cipher},  	// CBC mode is insecure and so is not included in the default config.  	// (See http://www.isg.rhul.ac.uk/~kp/SandPfinal.pdf). If absolutely  	// needed, it's possible to specify a custom Config to enable it.  	// You should expect that an active attacker can recover plaintext if  	// you do. -	aes128cbcID: {16, aes.BlockSize, 0, nil}, +	aes128cbcID: {16, aes.BlockSize, newAESCBCCipher}, -	// 3des-cbc is insecure and is disabled by default. -	tripledescbcID: {24, des.BlockSize, 0, nil}, +	// 3des-cbc is insecure and is not included in the default +	// config. +	tripledescbcID: {24, des.BlockSize, newTripleDESCBCCipher},  }  // prefixLen is the length of the packet prefix that contains the packet length @@ -304,7 +308,7 @@ type gcmCipher struct {  	buf    []byte  } -func newGCMCipher(iv, key, macKey []byte) (packetCipher, error) { +func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) {  	c, err := aes.NewCipher(key)  	if err != nil {  		return nil, err @@ -372,7 +376,7 @@ func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {  	}  	length := binary.BigEndian.Uint32(c.prefix[:])  	if length > maxPacket { -		return nil, errors.New("ssh: max packet length exceeded.") +		return nil, errors.New("ssh: max packet length exceeded")  	}  	if cap(c.buf) < int(length+gcmTagSize) { @@ -422,7 +426,7 @@ type cbcCipher struct {  	oracleCamouflage uint32  } -func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newCBCCipher(c cipher.Block, key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {  	cbc := &cbcCipher{  		mac:        macModes[algs.MAC].new(macKey),  		decrypter:  cipher.NewCBCDecrypter(c, iv), @@ -436,13 +440,13 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith  	return cbc, nil  } -func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newAESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {  	c, err := aes.NewCipher(key)  	if err != nil {  		return nil, err  	} -	cbc, err := newCBCCipher(c, iv, key, macKey, algs) +	cbc, err := newCBCCipher(c, key, iv, macKey, algs)  	if err != nil {  		return nil, err  	} @@ -450,13 +454,13 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi  	return cbc, nil  } -func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newTripleDESCBCCipher(key, iv, macKey []byte, algs directionAlgorithms) (packetCipher, error) {  	c, err := des.NewTripleDESCipher(key)  	if err != nil {  		return nil, err  	} -	cbc, err := newCBCCipher(c, iv, key, macKey, algs) +	cbc, err := newCBCCipher(c, key, iv, macKey, algs)  	if err != nil {  		return nil, err  	} @@ -548,11 +552,11 @@ func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error)  		c.packetData = c.packetData[:entirePacketSize]  	} -	if n, err := io.ReadFull(r, c.packetData[firstBlockLength:]); err != nil { +	n, err := io.ReadFull(r, c.packetData[firstBlockLength:]) +	if err != nil {  		return nil, err -	} else { -		c.oracleCamouflage -= uint32(n)  	} +	c.oracleCamouflage -= uint32(n)  	remainingCrypted := c.packetData[firstBlockLength:macStart]  	c.decrypter.CryptBlocks(remainingCrypted, remainingCrypted) @@ -627,3 +631,140 @@ func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, pack  	return nil  } + +const chacha20Poly1305ID = "chacha20-poly1305@openssh.com" + +// chacha20Poly1305Cipher implements the chacha20-poly1305@openssh.com +// AEAD, which is described here: +// +//   https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00 +// +// the methods here also implement padding, which RFC4253 Section 6 +// also requires of stream ciphers. +type chacha20Poly1305Cipher struct { +	lengthKey  [8]uint32 +	contentKey [8]uint32 +	buf        []byte +} + +func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionAlgorithms) (packetCipher, error) { +	if len(key) != 64 { +		panic(len(key)) +	} + +	c := &chacha20Poly1305Cipher{ +		buf: make([]byte, 256), +	} + +	for i := range c.contentKey { +		c.contentKey[i] = binary.LittleEndian.Uint32(key[i*4 : (i+1)*4]) +	} +	for i := range c.lengthKey { +		c.lengthKey[i] = binary.LittleEndian.Uint32(key[(i+8)*4 : (i+9)*4]) +	} +	return c, nil +} + +func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { +	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} +	s := chacha20.New(c.contentKey, nonce) +	var polyKey [32]byte +	s.XORKeyStream(polyKey[:], polyKey[:]) +	s.Advance() // skip next 32 bytes + +	encryptedLength := c.buf[:4] +	if _, err := io.ReadFull(r, encryptedLength); err != nil { +		return nil, err +	} + +	var lenBytes [4]byte +	chacha20.New(c.lengthKey, nonce).XORKeyStream(lenBytes[:], encryptedLength) + +	length := binary.BigEndian.Uint32(lenBytes[:]) +	if length > maxPacket { +		return nil, errors.New("ssh: invalid packet length, packet too large") +	} + +	contentEnd := 4 + length +	packetEnd := contentEnd + poly1305.TagSize +	if uint32(cap(c.buf)) < packetEnd { +		c.buf = make([]byte, packetEnd) +		copy(c.buf[:], encryptedLength) +	} else { +		c.buf = c.buf[:packetEnd] +	} + +	if _, err := io.ReadFull(r, c.buf[4:packetEnd]); err != nil { +		return nil, err +	} + +	var mac [poly1305.TagSize]byte +	copy(mac[:], c.buf[contentEnd:packetEnd]) +	if !poly1305.Verify(&mac, c.buf[:contentEnd], &polyKey) { +		return nil, errors.New("ssh: MAC failure") +	} + +	plain := c.buf[4:contentEnd] +	s.XORKeyStream(plain, plain) + +	padding := plain[0] +	if padding < 4 { +		// padding is a byte, so it automatically satisfies +		// the maximum size, which is 255. +		return nil, fmt.Errorf("ssh: illegal padding %d", padding) +	} + +	if int(padding)+1 >= len(plain) { +		return nil, fmt.Errorf("ssh: padding %d too large", padding) +	} + +	plain = plain[1 : len(plain)-int(padding)] + +	return plain, nil +} + +func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { +	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} +	s := chacha20.New(c.contentKey, nonce) +	var polyKey [32]byte +	s.XORKeyStream(polyKey[:], polyKey[:]) +	s.Advance() // skip next 32 bytes + +	// There is no blocksize, so fall back to multiple of 8 byte +	// padding, as described in RFC 4253, Sec 6. +	const packetSizeMultiple = 8 + +	padding := packetSizeMultiple - (1+len(payload))%packetSizeMultiple +	if padding < 4 { +		padding += packetSizeMultiple +	} + +	// size (4 bytes), padding (1), payload, padding, tag. +	totalLength := 4 + 1 + len(payload) + padding + poly1305.TagSize +	if cap(c.buf) < totalLength { +		c.buf = make([]byte, totalLength) +	} else { +		c.buf = c.buf[:totalLength] +	} + +	binary.BigEndian.PutUint32(c.buf, uint32(1+len(payload)+padding)) +	chacha20.New(c.lengthKey, nonce).XORKeyStream(c.buf, c.buf[:4]) +	c.buf[4] = byte(padding) +	copy(c.buf[5:], payload) +	packetEnd := 5 + len(payload) + padding +	if _, err := io.ReadFull(rand, c.buf[5+len(payload):packetEnd]); err != nil { +		return err +	} + +	s.XORKeyStream(c.buf[4:], c.buf[4:packetEnd]) + +	var mac [poly1305.TagSize]byte +	poly1305.Sum(&mac, c.buf[:packetEnd], &polyKey) + +	copy(c.buf[packetEnd:], mac[:]) + +	if _, err := w.Write(c.buf); err != nil { +		return err +	} +	return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/client.go b/vendor/golang.org/x/crypto/ssh/client.go index a7e3263..ae6ca77 100644 --- a/vendor/golang.org/x/crypto/ssh/client.go +++ b/vendor/golang.org/x/crypto/ssh/client.go @@ -9,6 +9,7 @@ import (  	"errors"  	"fmt"  	"net" +	"os"  	"sync"  	"time"  ) @@ -18,6 +19,8 @@ import (  type Client struct {  	Conn +	handleForwardsOnce sync.Once // guards calling (*Client).handleForwards +  	forwards        forwardList // forwarded tcpip connections from the remote side  	mu              sync.Mutex  	channelHandlers map[string]chan NewChannel @@ -59,8 +62,6 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {  		conn.Wait()  		conn.forwards.closeAll()  	}() -	go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip")) -	go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))  	return conn  } @@ -187,6 +188,10 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {  // net.Conn underlying the the SSH connection.  type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error +// BannerCallback is the function type used for treat the banner sent by +// the server. A BannerCallback receives the message sent by the remote server. +type BannerCallback func(message string) error +  // A ClientConfig structure is used to configure a Client. It must not be  // modified after having been passed to an SSH function.  type ClientConfig struct { @@ -209,6 +214,12 @@ type ClientConfig struct {  	// FixedHostKey can be used for simplistic host key checks.  	HostKeyCallback HostKeyCallback +	// BannerCallback is called during the SSH dance to display a custom +	// server's message. The client configuration can supply this callback to +	// handle it as wished. The function BannerDisplayStderr can be used for +	// simplistic display on Stderr. +	BannerCallback BannerCallback +  	// ClientVersion contains the version identification string that will  	// be used for the connection. If empty, a reasonable default is used.  	ClientVersion string @@ -255,3 +266,13 @@ func FixedHostKey(key PublicKey) HostKeyCallback {  	hk := &fixedHostKey{key}  	return hk.check  } + +// BannerDisplayStderr returns a function that can be used for +// ClientConfig.BannerCallback to display banners on os.Stderr. +func BannerDisplayStderr() BannerCallback { +	return func(banner string) error { +		_, err := os.Stderr.WriteString(banner) + +		return err +	} +} diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go index 3acd8d4..5f44b77 100644 --- a/vendor/golang.org/x/crypto/ssh/client_auth.go +++ b/vendor/golang.org/x/crypto/ssh/client_auth.go @@ -11,6 +11,14 @@ import (  	"io"  ) +type authResult int + +const ( +	authFailure authResult = iota +	authPartialSuccess +	authSuccess +) +  // clientAuthenticate authenticates with the remote server. See RFC 4252.  func (c *connection) clientAuthenticate(config *ClientConfig) error {  	// initiate user auth session @@ -37,11 +45,12 @@ func (c *connection) clientAuthenticate(config *ClientConfig) error {  		if err != nil {  			return err  		} -		if ok { +		if ok == authSuccess {  			// success  			return nil +		} else if ok == authFailure { +			tried[auth.method()] = true  		} -		tried[auth.method()] = true  		if methods == nil {  			methods = lastMethods  		} @@ -82,7 +91,7 @@ type AuthMethod interface {  	// If authentication is not successful, a []string of alternative  	// method names is returned. If the slice is nil, it will be ignored  	// and the previous set of possible methods will be reused. -	auth(session []byte, user string, p packetConn, rand io.Reader) (bool, []string, error) +	auth(session []byte, user string, p packetConn, rand io.Reader) (authResult, []string, error)  	// method returns the RFC 4252 method name.  	method() string @@ -91,13 +100,13 @@ type AuthMethod interface {  // "none" authentication, RFC 4252 section 5.2.  type noneAuth int -func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {  	if err := c.writePacket(Marshal(&userAuthRequestMsg{  		User:    user,  		Service: serviceSSH,  		Method:  "none",  	})); err != nil { -		return false, nil, err +		return authFailure, nil, err  	}  	return handleAuthResponse(c) @@ -111,7 +120,7 @@ func (n *noneAuth) method() string {  // a function call, e.g. by prompting the user.  type passwordCallback func() (password string, err error) -func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {  	type passwordAuthMsg struct {  		User     string `sshtype:"50"`  		Service  string @@ -125,7 +134,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand  	// The program may only find out that the user doesn't have a password  	// when prompting.  	if err != nil { -		return false, nil, err +		return authFailure, nil, err  	}  	if err := c.writePacket(Marshal(&passwordAuthMsg{ @@ -135,7 +144,7 @@ func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand  		Reply:    false,  		Password: pw,  	})); err != nil { -		return false, nil, err +		return authFailure, nil, err  	}  	return handleAuthResponse(c) @@ -178,7 +187,7 @@ func (cb publicKeyCallback) method() string {  	return "publickey"  } -func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {  	// Authentication is performed by sending an enquiry to test if a key is  	// acceptable to the remote. If the key is acceptable, the client will  	// attempt to authenticate with the valid key.  If not the client will repeat @@ -186,13 +195,13 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand  	signers, err := cb()  	if err != nil { -		return false, nil, err +		return authFailure, nil, err  	}  	var methods []string  	for _, signer := range signers {  		ok, err := validateKey(signer.PublicKey(), user, c)  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		if !ok {  			continue @@ -206,7 +215,7 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand  			Method:  cb.method(),  		}, []byte(pub.Type()), pubKey))  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		// manually wrap the serialized signature in a string @@ -224,24 +233,24 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand  		}  		p := Marshal(&msg)  		if err := c.writePacket(p); err != nil { -			return false, nil, err +			return authFailure, nil, err  		} -		var success bool +		var success authResult  		success, methods, err = handleAuthResponse(c)  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		// If authentication succeeds or the list of available methods does not  		// contain the "publickey" method, do not attempt to authenticate with any  		// other keys.  According to RFC 4252 Section 7, the latter can occur when  		// additional authentication methods are required. -		if success || !containsMethod(methods, cb.method()) { +		if success == authSuccess || !containsMethod(methods, cb.method()) {  			return success, methods, err  		}  	} -	return false, methods, nil +	return authFailure, methods, nil  }  func containsMethod(methods []string, method string) bool { @@ -283,7 +292,9 @@ func confirmKeyAck(key PublicKey, c packetConn) (bool, error) {  		}  		switch packet[0] {  		case msgUserAuthBanner: -			// TODO(gpaul): add callback to present the banner to the user +			if err := handleBannerResponse(c, packet); err != nil { +				return false, err +			}  		case msgUserAuthPubKeyOk:  			var msg userAuthPubKeyOkMsg  			if err := Unmarshal(packet, &msg); err != nil { @@ -316,30 +327,53 @@ func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMet  // handleAuthResponse returns whether the preceding authentication request succeeded  // along with a list of remaining authentication methods to try next and  // an error if an unexpected response was received. -func handleAuthResponse(c packetConn) (bool, []string, error) { +func handleAuthResponse(c packetConn) (authResult, []string, error) {  	for {  		packet, err := c.readPacket()  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		switch packet[0] {  		case msgUserAuthBanner: -			// TODO: add callback to present the banner to the user +			if err := handleBannerResponse(c, packet); err != nil { +				return authFailure, nil, err +			}  		case msgUserAuthFailure:  			var msg userAuthFailureMsg  			if err := Unmarshal(packet, &msg); err != nil { -				return false, nil, err +				return authFailure, nil, err +			} +			if msg.PartialSuccess { +				return authPartialSuccess, msg.Methods, nil  			} -			return false, msg.Methods, nil +			return authFailure, msg.Methods, nil  		case msgUserAuthSuccess: -			return true, nil, nil +			return authSuccess, nil, nil  		default: -			return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0]) +			return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])  		}  	}  } +func handleBannerResponse(c packetConn, packet []byte) error { +	var msg userAuthBannerMsg +	if err := Unmarshal(packet, &msg); err != nil { +		return err +	} + +	transport, ok := c.(*handshakeTransport) +	if !ok { +		return nil +	} + +	if transport.bannerCallback != nil { +		return transport.bannerCallback(msg.Message) +	} + +	return nil +} +  // KeyboardInteractiveChallenge should print questions, optionally  // disabling echoing (e.g. for passwords), and return all the answers.  // Challenge may be called multiple times in a single session. After @@ -359,7 +393,7 @@ func (cb KeyboardInteractiveChallenge) method() string {  	return "keyboard-interactive"  } -func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (bool, []string, error) { +func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) {  	type initiateMsg struct {  		User       string `sshtype:"50"`  		Service    string @@ -373,37 +407,42 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe  		Service: serviceSSH,  		Method:  "keyboard-interactive",  	})); err != nil { -		return false, nil, err +		return authFailure, nil, err  	}  	for {  		packet, err := c.readPacket()  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		// like handleAuthResponse, but with less options.  		switch packet[0] {  		case msgUserAuthBanner: -			// TODO: Print banners during userauth. +			if err := handleBannerResponse(c, packet); err != nil { +				return authFailure, nil, err +			}  			continue  		case msgUserAuthInfoRequest:  			// OK  		case msgUserAuthFailure:  			var msg userAuthFailureMsg  			if err := Unmarshal(packet, &msg); err != nil { -				return false, nil, err +				return authFailure, nil, err +			} +			if msg.PartialSuccess { +				return authPartialSuccess, msg.Methods, nil  			} -			return false, msg.Methods, nil +			return authFailure, msg.Methods, nil  		case msgUserAuthSuccess: -			return true, nil, nil +			return authSuccess, nil, nil  		default: -			return false, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0]) +			return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])  		}  		var msg userAuthInfoRequestMsg  		if err := Unmarshal(packet, &msg); err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		// Manually unpack the prompt/echo pairs. @@ -413,7 +452,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe  		for i := 0; i < int(msg.NumPrompts); i++ {  			prompt, r, ok := parseString(rest)  			if !ok || len(r) == 0 { -				return false, nil, errors.New("ssh: prompt format error") +				return authFailure, nil, errors.New("ssh: prompt format error")  			}  			prompts = append(prompts, string(prompt))  			echos = append(echos, r[0] != 0) @@ -421,16 +460,16 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe  		}  		if len(rest) != 0 { -			return false, nil, errors.New("ssh: extra data following keyboard-interactive pairs") +			return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")  		}  		answers, err := cb(msg.User, msg.Instruction, prompts, echos)  		if err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  		if len(answers) != len(prompts) { -			return false, nil, errors.New("ssh: not enough answers from keyboard-interactive callback") +			return authFailure, nil, errors.New("ssh: not enough answers from keyboard-interactive callback")  		}  		responseLength := 1 + 4  		for _, a := range answers { @@ -446,7 +485,7 @@ func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packe  		}  		if err := c.writePacket(serialized); err != nil { -			return false, nil, err +			return authFailure, nil, err  		}  	}  } @@ -456,10 +495,10 @@ type retryableAuthMethod struct {  	maxTries   int  } -func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) { +func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok authResult, methods []string, err error) {  	for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {  		ok, methods, err = r.authMethod.auth(session, user, c, rand) -		if ok || err != nil { // either success or error terminate +		if ok != authFailure || err != nil { // either success, partial success or error terminate  			return ok, methods, err  		}  	} diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go index dc39e4d..04f3620 100644 --- a/vendor/golang.org/x/crypto/ssh/common.go +++ b/vendor/golang.org/x/crypto/ssh/common.go @@ -24,11 +24,21 @@ const (  	serviceSSH      = "ssh-connection"  ) -// supportedCiphers specifies the supported ciphers in preference order. +// supportedCiphers lists ciphers we support but might not recommend.  var supportedCiphers = []string{  	"aes128-ctr", "aes192-ctr", "aes256-ctr",  	"aes128-gcm@openssh.com", -	"arcfour256", "arcfour128", +	chacha20Poly1305ID, +	"arcfour256", "arcfour128", "arcfour", +	aes128cbcID, +	tripledescbcID, +} + +// preferredCiphers specifies the default preference for ciphers. +var preferredCiphers = []string{ +	"aes128-gcm@openssh.com", +	chacha20Poly1305ID, +	"aes128-ctr", "aes192-ctr", "aes256-ctr",  }  // supportedKexAlgos specifies the supported key-exchange algorithms in @@ -211,7 +221,7 @@ func (c *Config) SetDefaults() {  		c.Rand = rand.Reader  	}  	if c.Ciphers == nil { -		c.Ciphers = supportedCiphers +		c.Ciphers = preferredCiphers  	}  	var ciphers []string  	for _, c := range c.Ciphers { @@ -242,7 +252,7 @@ func (c *Config) SetDefaults() {  // buildDataSignedForAuth returns the data that is signed in order to prove  // possession of a private key. See RFC 4252, section 7. -func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { +func buildDataSignedForAuth(sessionID []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {  	data := struct {  		Session []byte  		Type    byte @@ -253,7 +263,7 @@ func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubK  		Algo    []byte  		PubKey  []byte  	}{ -		sessionId, +		sessionID,  		msgUserAuthRequest,  		req.User,  		req.Service, diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go index 932ce83..4f7912e 100644 --- a/vendor/golang.org/x/crypto/ssh/handshake.go +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -78,6 +78,11 @@ type handshakeTransport struct {  	dialAddress     string  	remoteAddr      net.Addr +	// bannerCallback is non-empty if we are the client and it has been set in +	// ClientConfig. In that case it is called during the user authentication +	// dance to handle a custom server's message. +	bannerCallback BannerCallback +  	// Algorithms agreed in the last key exchange.  	algorithms *algorithms @@ -120,6 +125,7 @@ func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byt  	t.dialAddress = dialAddr  	t.remoteAddr = addr  	t.hostKeyCallback = config.HostKeyCallback +	t.bannerCallback = config.BannerCallback  	if config.HostKeyAlgorithms != nil {  		t.hostKeyAlgorithms = config.HostKeyAlgorithms  	} else { diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go index f91c277..f34bcc0 100644 --- a/vendor/golang.org/x/crypto/ssh/kex.go +++ b/vendor/golang.org/x/crypto/ssh/kex.go @@ -119,7 +119,7 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha  		return nil, err  	} -	kInt, err := group.diffieHellman(kexDHReply.Y, x) +	ki, err := group.diffieHellman(kexDHReply.Y, x)  	if err != nil {  		return nil, err  	} @@ -129,8 +129,8 @@ func (group *dhGroup) Client(c packetConn, randSource io.Reader, magics *handsha  	writeString(h, kexDHReply.HostKey)  	writeInt(h, X)  	writeInt(h, kexDHReply.Y) -	K := make([]byte, intLength(kInt)) -	marshalInt(K, kInt) +	K := make([]byte, intLength(ki)) +	marshalInt(K, ki)  	h.Write(K)  	return &kexResult{ @@ -164,7 +164,7 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha  	}  	Y := new(big.Int).Exp(group.g, y, group.p) -	kInt, err := group.diffieHellman(kexDHInit.X, y) +	ki, err := group.diffieHellman(kexDHInit.X, y)  	if err != nil {  		return nil, err  	} @@ -177,8 +177,8 @@ func (group *dhGroup) Server(c packetConn, randSource io.Reader, magics *handsha  	writeInt(h, kexDHInit.X)  	writeInt(h, Y) -	K := make([]byte, intLength(kInt)) -	marshalInt(K, kInt) +	K := make([]byte, intLength(ki)) +	marshalInt(K, ki)  	h.Write(K)  	H := h.Sum(nil) @@ -462,9 +462,9 @@ func (kex *curve25519sha256) Client(c packetConn, rand io.Reader, magics *handsh  	writeString(h, kp.pub[:])  	writeString(h, reply.EphemeralPubKey) -	kInt := new(big.Int).SetBytes(secret[:]) -	K := make([]byte, intLength(kInt)) -	marshalInt(K, kInt) +	ki := new(big.Int).SetBytes(secret[:]) +	K := make([]byte, intLength(ki)) +	marshalInt(K, ki)  	h.Write(K)  	return &kexResult{ @@ -510,9 +510,9 @@ func (kex *curve25519sha256) Server(c packetConn, rand io.Reader, magics *handsh  	writeString(h, kexInit.ClientPubKey)  	writeString(h, kp.pub[:]) -	kInt := new(big.Int).SetBytes(secret[:]) -	K := make([]byte, intLength(kInt)) -	marshalInt(K, kInt) +	ki := new(big.Int).SetBytes(secret[:]) +	K := make([]byte, intLength(ki)) +	marshalInt(K, ki)  	h.Write(K)  	H := h.Sum(nil) diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index b682c17..73697de 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -276,7 +276,8 @@ type PublicKey interface {  	Type() string  	// Marshal returns the serialized key data in SSH wire format, -	// with the name prefix. +	// with the name prefix. To unmarshal the returned data, use +	// the ParsePublicKey function.  	Marshal() []byte  	// Verify that sig is a signature on the given data using this @@ -363,7 +364,7 @@ func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {  type dsaPublicKey dsa.PublicKey -func (r *dsaPublicKey) Type() string { +func (k *dsaPublicKey) Type() string {  	return "ssh-dss"  } @@ -481,12 +482,12 @@ func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {  type ecdsaPublicKey ecdsa.PublicKey -func (key *ecdsaPublicKey) Type() string { -	return "ecdsa-sha2-" + key.nistID() +func (k *ecdsaPublicKey) Type() string { +	return "ecdsa-sha2-" + k.nistID()  } -func (key *ecdsaPublicKey) nistID() string { -	switch key.Params().BitSize { +func (k *ecdsaPublicKey) nistID() string { +	switch k.Params().BitSize {  	case 256:  		return "nistp256"  	case 384: @@ -499,7 +500,7 @@ func (key *ecdsaPublicKey) nistID() string {  type ed25519PublicKey ed25519.PublicKey -func (key ed25519PublicKey) Type() string { +func (k ed25519PublicKey) Type() string {  	return KeyAlgoED25519  } @@ -518,23 +519,23 @@ func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {  	return (ed25519PublicKey)(key), w.Rest, nil  } -func (key ed25519PublicKey) Marshal() []byte { +func (k ed25519PublicKey) Marshal() []byte {  	w := struct {  		Name     string  		KeyBytes []byte  	}{  		KeyAlgoED25519, -		[]byte(key), +		[]byte(k),  	}  	return Marshal(&w)  } -func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error { -	if sig.Format != key.Type() { -		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) +func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error { +	if sig.Format != k.Type() { +		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())  	} -	edKey := (ed25519.PublicKey)(key) +	edKey := (ed25519.PublicKey)(k)  	if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {  		return errors.New("ssh: signature did not verify")  	} @@ -595,9 +596,9 @@ func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {  	return (*ecdsaPublicKey)(key), w.Rest, nil  } -func (key *ecdsaPublicKey) Marshal() []byte { +func (k *ecdsaPublicKey) Marshal() []byte {  	// See RFC 5656, section 3.1. -	keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) +	keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)  	// ECDSA publickey struct layout should match the struct used by  	// parseECDSACert in the x/crypto/ssh/agent package.  	w := struct { @@ -605,20 +606,20 @@ func (key *ecdsaPublicKey) Marshal() []byte {  		ID   string  		Key  []byte  	}{ -		key.Type(), -		key.nistID(), +		k.Type(), +		k.nistID(),  		keyBytes,  	}  	return Marshal(&w)  } -func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { -	if sig.Format != key.Type() { -		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) +func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { +	if sig.Format != k.Type() { +		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())  	} -	h := ecHash(key.Curve).New() +	h := ecHash(k.Curve).New()  	h.Write(data)  	digest := h.Sum(nil) @@ -635,7 +636,7 @@ func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {  		return err  	} -	if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) { +	if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {  		return nil  	}  	return errors.New("ssh: signature did not verify") @@ -758,7 +759,7 @@ func NewPublicKey(key interface{}) (PublicKey, error) {  		return (*rsaPublicKey)(key), nil  	case *ecdsa.PublicKey:  		if !supportedEllipticCurve(key.Curve) { -			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.") +			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")  		}  		return (*ecdsaPublicKey)(key), nil  	case *dsa.PublicKey: diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go index e6ecd3a..08d2811 100644 --- a/vendor/golang.org/x/crypto/ssh/messages.go +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -23,10 +23,6 @@ const (  	msgUnimplemented = 3  	msgDebug         = 4  	msgNewKeys       = 21 - -	// Standard authentication messages -	msgUserAuthSuccess = 52 -	msgUserAuthBanner  = 53  )  // SSH messages: @@ -137,6 +133,18 @@ type userAuthFailureMsg struct {  	PartialSuccess bool  } +// See RFC 4252, section 5.1 +const msgUserAuthSuccess = 52 + +// See RFC 4252, section 5.4 +const msgUserAuthBanner = 53 + +type userAuthBannerMsg struct { +	Message string `sshtype:"53"` +	// unused, but required to allow message parsing +	Language string +} +  // See RFC 4256, section 3.2  const msgUserAuthInfoRequest = 60  const msgUserAuthInfoResponse = 61 @@ -154,7 +162,7 @@ const msgChannelOpen = 90  type channelOpenMsg struct {  	ChanType         string `sshtype:"90"` -	PeersId          uint32 +	PeersID          uint32  	PeersWindow      uint32  	MaxPacketSize    uint32  	TypeSpecificData []byte `ssh:"rest"` @@ -165,7 +173,7 @@ const msgChannelData = 94  // Used for debug print outs of packets.  type channelDataMsg struct { -	PeersId uint32 `sshtype:"94"` +	PeersID uint32 `sshtype:"94"`  	Length  uint32  	Rest    []byte `ssh:"rest"`  } @@ -174,8 +182,8 @@ type channelDataMsg struct {  const msgChannelOpenConfirm = 91  type channelOpenConfirmMsg struct { -	PeersId          uint32 `sshtype:"91"` -	MyId             uint32 +	PeersID          uint32 `sshtype:"91"` +	MyID             uint32  	MyWindow         uint32  	MaxPacketSize    uint32  	TypeSpecificData []byte `ssh:"rest"` @@ -185,7 +193,7 @@ type channelOpenConfirmMsg struct {  const msgChannelOpenFailure = 92  type channelOpenFailureMsg struct { -	PeersId  uint32 `sshtype:"92"` +	PeersID  uint32 `sshtype:"92"`  	Reason   RejectionReason  	Message  string  	Language string @@ -194,7 +202,7 @@ type channelOpenFailureMsg struct {  const msgChannelRequest = 98  type channelRequestMsg struct { -	PeersId             uint32 `sshtype:"98"` +	PeersID             uint32 `sshtype:"98"`  	Request             string  	WantReply           bool  	RequestSpecificData []byte `ssh:"rest"` @@ -204,28 +212,28 @@ type channelRequestMsg struct {  const msgChannelSuccess = 99  type channelRequestSuccessMsg struct { -	PeersId uint32 `sshtype:"99"` +	PeersID uint32 `sshtype:"99"`  }  // See RFC 4254, section 5.4.  const msgChannelFailure = 100  type channelRequestFailureMsg struct { -	PeersId uint32 `sshtype:"100"` +	PeersID uint32 `sshtype:"100"`  }  // See RFC 4254, section 5.3  const msgChannelClose = 97  type channelCloseMsg struct { -	PeersId uint32 `sshtype:"97"` +	PeersID uint32 `sshtype:"97"`  }  // See RFC 4254, section 5.3  const msgChannelEOF = 96  type channelEOFMsg struct { -	PeersId uint32 `sshtype:"96"` +	PeersID uint32 `sshtype:"96"`  }  // See RFC 4254, section 4 @@ -255,7 +263,7 @@ type globalRequestFailureMsg struct {  const msgChannelWindowAdjust = 93  type windowAdjustMsg struct { -	PeersId         uint32 `sshtype:"93"` +	PeersID         uint32 `sshtype:"93"`  	AdditionalBytes uint32  } diff --git a/vendor/golang.org/x/crypto/ssh/mux.go b/vendor/golang.org/x/crypto/ssh/mux.go index 27a527c..f190162 100644 --- a/vendor/golang.org/x/crypto/ssh/mux.go +++ b/vendor/golang.org/x/crypto/ssh/mux.go @@ -278,7 +278,7 @@ func (m *mux) handleChannelOpen(packet []byte) error {  	if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {  		failMsg := channelOpenFailureMsg{ -			PeersId:  msg.PeersId, +			PeersID:  msg.PeersID,  			Reason:   ConnectionFailed,  			Message:  "invalid request",  			Language: "en_US.UTF-8", @@ -287,7 +287,7 @@ func (m *mux) handleChannelOpen(packet []byte) error {  	}  	c := m.newChannel(msg.ChanType, channelInbound, msg.TypeSpecificData) -	c.remoteId = msg.PeersId +	c.remoteId = msg.PeersID  	c.maxRemotePayload = msg.MaxPacketSize  	c.remoteWin.add(msg.PeersWindow)  	m.incomingChannels <- c @@ -313,7 +313,7 @@ func (m *mux) openChannel(chanType string, extra []byte) (*channel, error) {  		PeersWindow:      ch.myWindow,  		MaxPacketSize:    ch.maxIncomingPayload,  		TypeSpecificData: extra, -		PeersId:          ch.localId, +		PeersID:          ch.localId,  	}  	if err := m.sendMessage(open); err != nil {  		return nil, err diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go index 8a78b7c..d0f4825 100644 --- a/vendor/golang.org/x/crypto/ssh/server.go +++ b/vendor/golang.org/x/crypto/ssh/server.go @@ -95,6 +95,10 @@ type ServerConfig struct {  	// Note that RFC 4253 section 4.2 requires that this string start with  	// "SSH-2.0-".  	ServerVersion string + +	// BannerCallback, if present, is called and the return string is sent to +	// the client after key exchange completed but before authentication. +	BannerCallback func(conn ConnMetadata) string  }  // AddHostKey adds a private key as a host key. If an existing host @@ -162,6 +166,9 @@ type ServerConn struct {  // unsuccessful, it closes the connection and returns an error.  The  // Request and NewChannel channels must be serviced, or the connection  // will hang. +// +// The returned error may be of type *ServerAuthError for +// authentication errors.  func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {  	fullConf := *config  	fullConf.SetDefaults() @@ -252,7 +259,7 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)  func isAcceptableAlgo(algo string) bool {  	switch algo {  	case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoED25519, -		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01: +		CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:  		return true  	}  	return false @@ -288,12 +295,13 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {  	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)  } -// ServerAuthError implements the error interface. It appends any authentication -// errors that may occur, and is returned if all of the authentication methods -// provided by the user failed to authenticate. +// ServerAuthError represents server authentication errors and is +// sometimes returned by NewServerConn. It appends any authentication +// errors that may occur, and is returned if all of the authentication +// methods provided by the user failed to authenticate.  type ServerAuthError struct {  	// Errors contains authentication errors returned by the authentication -	// callback methods. +	// callback methods. The first entry is typically ErrNoAuth.  	Errors []error  } @@ -305,6 +313,13 @@ func (l ServerAuthError) Error() string {  	return "[" + strings.Join(errs, ", ") + "]"  } +// ErrNoAuth is the error value returned if no +// authentication method has been passed yet. This happens as a normal +// part of the authentication loop, since the client first tries +// 'none' authentication to discover available methods. +// It is returned in ServerAuthError.Errors from NewServerConn. +var ErrNoAuth = errors.New("ssh: no auth passed yet") +  func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {  	sessionID := s.transport.getSessionID()  	var cache pubKeyCache @@ -312,6 +327,7 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err  	authFailures := 0  	var authErrs []error +	var displayedBanner bool  userAuthLoop:  	for { @@ -343,8 +359,22 @@ userAuthLoop:  		}  		s.user = userAuthReq.User + +		if !displayedBanner && config.BannerCallback != nil { +			displayedBanner = true +			msg := config.BannerCallback(s) +			if msg != "" { +				bannerMsg := &userAuthBannerMsg{ +					Message: msg, +				} +				if err := s.transport.writePacket(Marshal(bannerMsg)); err != nil { +					return nil, err +				} +			} +		} +  		perms = nil -		authErr := errors.New("no auth passed yet") +		authErr := ErrNoAuth  		switch userAuthReq.Method {  		case "none": diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go index cc06e03..d3321f6 100644 --- a/vendor/golang.org/x/crypto/ssh/session.go +++ b/vendor/golang.org/x/crypto/ssh/session.go @@ -406,7 +406,7 @@ func (s *Session) Wait() error {  		s.stdinPipeWriter.Close()  	}  	var copyError error -	for _ = range s.copyFuncs { +	for range s.copyFuncs {  		if err := <-s.errors; err != nil && copyError == nil {  			copyError = err  		} diff --git a/vendor/golang.org/x/crypto/ssh/streamlocal.go b/vendor/golang.org/x/crypto/ssh/streamlocal.go index a2dccc6..b171b33 100644 --- a/vendor/golang.org/x/crypto/ssh/streamlocal.go +++ b/vendor/golang.org/x/crypto/ssh/streamlocal.go @@ -32,6 +32,7 @@ type streamLocalChannelForwardMsg struct {  // ListenUnix is similar to ListenTCP but uses a Unix domain socket.  func (c *Client) ListenUnix(socketPath string) (net.Listener, error) { +	c.handleForwardsOnce.Do(c.handleForwards)  	m := streamLocalChannelForwardMsg{  		socketPath,  	} diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index acf1717..80d35f5 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -90,10 +90,19 @@ type channelForwardMsg struct {  	rport uint32  } +// handleForwards starts goroutines handling forwarded connections. +// It's called on first use by (*Client).ListenTCP to not launch +// goroutines until needed. +func (c *Client) handleForwards() { +	go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-tcpip")) +	go c.forwards.handleChannels(c.HandleChannelOpen("forwarded-streamlocal@openssh.com")) +} +  // ListenTCP requests the remote peer open a listening socket  // on laddr. Incoming connections will be available by calling  // Accept on the returned net.Listener.  func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) { +	c.handleForwardsOnce.Do(c.handleForwards)  	if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {  		return c.autoPortListenWorkaround(laddr)  	} diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go index f9780e0..f6fae1d 100644 --- a/vendor/golang.org/x/crypto/ssh/transport.go +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -6,6 +6,7 @@ package ssh  import (  	"bufio" +	"bytes"  	"errors"  	"io"  	"log" @@ -76,17 +77,17 @@ type connectionState struct {  // both directions are triggered by reading and writing a msgNewKey packet  // respectively.  func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { -	if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { +	ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult) +	if err != nil {  		return err -	} else { -		t.reader.pendingKeyChange <- ciph  	} +	t.reader.pendingKeyChange <- ciph -	if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil { +	ciph, err = newPacketCipher(t.writer.dir, algs.w, kexResult) +	if err != nil {  		return err -	} else { -		t.writer.pendingKeyChange <- ciph  	} +	t.writer.pendingKeyChange <- ciph  	return nil  } @@ -139,7 +140,7 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {  			case cipher := <-s.pendingKeyChange:  				s.packetCipher = cipher  			default: -				return nil, errors.New("ssh: got bogus newkeys message.") +				return nil, errors.New("ssh: got bogus newkeys message")  			}  		case msgDisconnect: @@ -232,52 +233,22 @@ var (  	clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}  ) -// generateKeys generates key material for IV, MAC and encryption. -func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { +// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as +// described in RFC 4253, section 6.4. direction should either be serverKeys +// (to setup server->client keys) or clientKeys (for client->server keys). +func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) {  	cipherMode := cipherModes[algs.Cipher]  	macMode := macModes[algs.MAC] -	iv = make([]byte, cipherMode.ivSize) -	key = make([]byte, cipherMode.keySize) -	macKey = make([]byte, macMode.keySize) +	iv := make([]byte, cipherMode.ivSize) +	key := make([]byte, cipherMode.keySize) +	macKey := make([]byte, macMode.keySize)  	generateKeyMaterial(iv, d.ivTag, kex)  	generateKeyMaterial(key, d.keyTag, kex)  	generateKeyMaterial(macKey, d.macKeyTag, kex) -	return -} - -// setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as -// described in RFC 4253, section 6.4. direction should either be serverKeys -// (to setup server->client keys) or clientKeys (for client->server keys). -func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { -	iv, key, macKey := generateKeys(d, algs, kex) - -	if algs.Cipher == gcmCipherID { -		return newGCMCipher(iv, key, macKey) -	} - -	if algs.Cipher == aes128cbcID { -		return newAESCBCCipher(iv, key, macKey, algs) -	} - -	if algs.Cipher == tripledescbcID { -		return newTripleDESCBCCipher(iv, key, macKey, algs) -	} -	c := &streamPacketCipher{ -		mac: macModes[algs.MAC].new(macKey), -		etm: macModes[algs.MAC].etm, -	} -	c.macResult = make([]byte, c.mac.Size()) - -	var err error -	c.cipher, err = cipherModes[algs.Cipher].createStream(key, iv) -	if err != nil { -		return nil, err -	} - -	return c, nil +	return cipherModes[algs.Cipher].create(key, iv, macKey, algs)  }  // generateKeyMaterial fills out with key material generated from tag, K, H @@ -342,7 +313,7 @@ func readVersion(r io.Reader) ([]byte, error) {  	var ok bool  	var buf [1]byte -	for len(versionString) < maxVersionStringBytes { +	for length := 0; length < maxVersionStringBytes; length++ {  		_, err := io.ReadFull(r, buf[:])  		if err != nil {  			return nil, err @@ -350,6 +321,13 @@ func readVersion(r io.Reader) ([]byte, error) {  		// The RFC says that the version should be terminated with \r\n  		// but several SSH servers actually only send a \n.  		if buf[0] == '\n' { +			if !bytes.HasPrefix(versionString, []byte("SSH-")) { +				// RFC 4253 says we need to ignore all version string lines +				// except the one containing the SSH version (provided that +				// all the lines do not exceed 255 bytes in total). +				versionString = versionString[:0] +				continue +			}  			ok = true  			break  		} | 
