summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/crypto/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/crypto/ssh')
-rw-r--r--vendor/golang.org/x/crypto/ssh/certs.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/cipher.go11
-rw-r--r--vendor/golang.org/x/crypto/ssh/common.go19
-rw-r--r--vendor/golang.org/x/crypto/ssh/connection.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/handshake.go69
-rw-r--r--vendor/golang.org/x/crypto/ssh/keys.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/messages.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/server.go27
-rw-r--r--vendor/golang.org/x/crypto/ssh/session.go7
9 files changed, 94 insertions, 47 deletions
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 4600c2077..fc04d03e1 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -251,7 +251,7 @@ type algorithmOpenSSHCertSigner struct {
// private key is held by signer. It returns an error if the public key in cert
// doesn't match the key used by signer.
func NewCertSigner(cert *Certificate, signer Signer) (Signer, error) {
- if bytes.Compare(cert.Key.Marshal(), signer.PublicKey().Marshal()) != 0 {
+ if !bytes.Equal(cert.Key.Marshal(), signer.PublicKey().Marshal()) {
return nil, errors.New("ssh: signer and cert have different public key")
}
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 770e8a663..87f48552c 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -15,7 +15,6 @@ import (
"fmt"
"hash"
"io"
- "io/ioutil"
"golang.org/x/crypto/chacha20"
"golang.org/x/crypto/internal/poly1305"
@@ -97,13 +96,13 @@ func streamCipherMode(skip int, createFunc func(key, iv []byte) (cipher.Stream,
// are not supported and will not be negotiated, even if explicitly requested in
// ClientConfig.Crypto.Ciphers.
var cipherModes = map[string]*cipherMode{
- // Ciphers from RFC4344, which introduced many CTR-based ciphers. Algorithms
+ // Ciphers from RFC 4344, which introduced many CTR-based ciphers. Algorithms
// are defined in the order specified in the RFC.
"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.
+ // Ciphers from RFC 4345, which introduces security-improved arcfour ciphers.
// They are defined in the order specified in the RFC.
"arcfour128": {16, 0, streamCipherMode(1536, newRC4)},
"arcfour256": {32, 0, streamCipherMode(1536, newRC4)},
@@ -111,7 +110,7 @@ var cipherModes = map[string]*cipherMode{
// 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.
+ // RFC 4345 introduces improved versions of Arcfour.
"arcfour": {16, 0, streamCipherMode(0, newRC4)},
// AEAD ciphers
@@ -497,7 +496,7 @@ func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error)
// data, to make distinguishing between
// failing MAC and failing length check more
// difficult.
- io.CopyN(ioutil.Discard, r, int64(c.oracleCamouflage))
+ io.CopyN(io.Discard, r, int64(c.oracleCamouflage))
}
}
return p, err
@@ -642,7 +641,7 @@ const chacha20Poly1305ID = "chacha20-poly1305@openssh.com"
//
// https://tools.ietf.org/html/draft-josefsson-ssh-chacha20-poly1305-openssh-00
//
-// the methods here also implement padding, which RFC4253 Section 6
+// the methods here also implement padding, which RFC 4253 Section 6
// also requires of stream ciphers.
type chacha20Poly1305Cipher struct {
lengthKey [32]byte
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go
index 2a47a61de..c7964275d 100644
--- a/vendor/golang.org/x/crypto/ssh/common.go
+++ b/vendor/golang.org/x/crypto/ssh/common.go
@@ -10,6 +10,7 @@ import (
"fmt"
"io"
"math"
+ "strings"
"sync"
_ "crypto/sha1"
@@ -118,6 +119,20 @@ func algorithmsForKeyFormat(keyFormat string) []string {
}
}
+// supportedPubKeyAuthAlgos specifies the supported client public key
+// authentication algorithms. Note that this doesn't include certificate types
+// since those use the underlying algorithm. This list is sent to the client if
+// it supports the server-sig-algs extension. Order is irrelevant.
+var supportedPubKeyAuthAlgos = []string{
+ KeyAlgoED25519,
+ KeyAlgoSKED25519, KeyAlgoSKECDSA256,
+ KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
+ KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA,
+ KeyAlgoDSA,
+}
+
+var supportedPubKeyAuthAlgosList = strings.Join(supportedPubKeyAuthAlgos, ",")
+
// unexpectedMessageError results when the SSH message that we received didn't
// match what we wanted.
func unexpectedMessageError(expected, got uint8) error {
@@ -149,7 +164,7 @@ type directionAlgorithms struct {
// rekeyBytes returns a rekeying intervals in bytes.
func (a *directionAlgorithms) rekeyBytes() int64 {
- // According to RFC4344 block ciphers should rekey after
+ // According to RFC 4344 block ciphers should rekey after
// 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is
// 128.
switch a.Cipher {
@@ -158,7 +173,7 @@ func (a *directionAlgorithms) rekeyBytes() int64 {
}
- // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data.
+ // For others, stick with RFC 4253 recommendation to rekey after 1 Gb of data.
return 1 << 30
}
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
index fd6b0681b..35661a52b 100644
--- a/vendor/golang.org/x/crypto/ssh/connection.go
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -52,7 +52,7 @@ type Conn interface {
// SendRequest sends a global request, and returns the
// reply. If wantReply is true, it returns the response status
- // and payload. See also RFC4254, section 4.
+ // and payload. See also RFC 4254, section 4.
SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
// OpenChannel tries to open an channel. If the request is
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index 653dc4d2c..07a1843e0 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -58,11 +58,13 @@ type handshakeTransport struct {
incoming chan []byte
readError error
- mu sync.Mutex
- writeError error
- sentInitPacket []byte
- sentInitMsg *kexInitMsg
- pendingPackets [][]byte // Used when a key exchange is in progress.
+ mu sync.Mutex
+ writeError error
+ sentInitPacket []byte
+ sentInitMsg *kexInitMsg
+ pendingPackets [][]byte // Used when a key exchange is in progress.
+ writePacketsLeft uint32
+ writeBytesLeft int64
// If the read loop wants to schedule a kex, it pings this
// channel, and the write loop will send out a kex
@@ -71,7 +73,8 @@ type handshakeTransport struct {
// If the other side requests or confirms a kex, its kexInit
// packet is sent here for the write loop to find it.
- startKex chan *pendingKex
+ startKex chan *pendingKex
+ kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits
// data for host key checking
hostKeyCallback HostKeyCallback
@@ -86,12 +89,10 @@ type handshakeTransport struct {
// Algorithms agreed in the last key exchange.
algorithms *algorithms
+ // Counters exclusively owned by readLoop.
readPacketsLeft uint32
readBytesLeft int64
- writePacketsLeft uint32
- writeBytesLeft int64
-
// The session ID or nil if first kex did not complete yet.
sessionID []byte
}
@@ -108,7 +109,8 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
clientVersion: clientVersion,
incoming: make(chan []byte, chanSize),
requestKex: make(chan struct{}, 1),
- startKex: make(chan *pendingKex, 1),
+ startKex: make(chan *pendingKex),
+ kexLoopDone: make(chan struct{}),
config: config,
}
@@ -340,16 +342,17 @@ write:
t.mu.Unlock()
}
+ // Unblock reader.
+ t.conn.Close()
+
// drain startKex channel. We don't service t.requestKex
// because nobody does blocking sends there.
- go func() {
- for init := range t.startKex {
- init.done <- t.writeError
- }
- }()
+ for request := range t.startKex {
+ request.done <- t.getWriteError()
+ }
- // Unblock reader.
- t.conn.Close()
+ // Mark that the loop is done so that Close can return.
+ close(t.kexLoopDone)
}
// The protocol uses uint32 for packet counters, so we can't let them
@@ -545,7 +548,16 @@ func (t *handshakeTransport) writePacket(p []byte) error {
}
func (t *handshakeTransport) Close() error {
- return t.conn.Close()
+ // Close the connection. This should cause the readLoop goroutine to wake up
+ // and close t.startKex, which will shut down kexLoop if running.
+ err := t.conn.Close()
+
+ // Wait for the kexLoop goroutine to complete.
+ // At that point we know that the readLoop goroutine is complete too,
+ // because kexLoop itself waits for readLoop to close the startKex channel.
+ <-t.kexLoopDone
+
+ return err
}
func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
@@ -615,7 +627,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
return err
}
- if t.sessionID == nil {
+ firstKeyExchange := t.sessionID == nil
+ if firstKeyExchange {
t.sessionID = result.H
}
result.SessionID = t.sessionID
@@ -626,6 +639,24 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
return err
}
+
+ // On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
+ // message with the server-sig-algs extension if the client supports it. See
+ // RFC 8308, Sections 2.4 and 3.1.
+ if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
+ extInfo := &extInfoMsg{
+ NumExtensions: 1,
+ Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)),
+ }
+ extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs"))
+ extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...)
+ extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList))
+ extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...)
+ if err := t.conn.writePacket(Marshal(extInfo)); err != nil {
+ return err
+ }
+ }
+
if packet, err := t.conn.readPacket(); err != nil {
return err
} else if packet[0] != msgNewKeys {
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index 1c7de1a6d..729698041 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -184,7 +184,7 @@ func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey
return "", nil, nil, "", nil, io.EOF
}
-// ParseAuthorizedKeys parses a public key from an authorized_keys
+// ParseAuthorizedKey parses a public key from an authorized_keys
// file used in OpenSSH according to the sshd(8) manual page.
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
for len(in) > 0 {
diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go
index 19bc67c46..922032d95 100644
--- a/vendor/golang.org/x/crypto/ssh/messages.go
+++ b/vendor/golang.org/x/crypto/ssh/messages.go
@@ -68,7 +68,7 @@ type kexInitMsg struct {
// See RFC 4253, section 8.
-// Diffie-Helman
+// Diffie-Hellman
const msgKexDHInit = 30
type kexDHInitMsg struct {
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 70045bdfd..9e3870292 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -68,8 +68,16 @@ type ServerConfig struct {
// NoClientAuth is true if clients are allowed to connect without
// authenticating.
+ // To determine NoClientAuth at runtime, set NoClientAuth to true
+ // and the optional NoClientAuthCallback to a non-nil value.
NoClientAuth bool
+ // NoClientAuthCallback, if non-nil, is called when a user
+ // attempts to authenticate with auth method "none".
+ // NoClientAuth must also be set to true for this be used, or
+ // this func is unused.
+ NoClientAuthCallback func(ConnMetadata) (*Permissions, error)
+
// MaxAuthTries specifies the maximum number of authentication attempts
// permitted per connection. If set to a negative number, the number of
// attempts are unlimited. If set to zero, the number of attempts are limited
@@ -283,15 +291,6 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
return perms, err
}
-func isAcceptableAlgo(algo string) bool {
- switch algo {
- case KeyAlgoRSA, KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, KeyAlgoSKECDSA256, KeyAlgoED25519, KeyAlgoSKED25519,
- CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
- return true
- }
- return false
-}
-
func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
if addr == nil {
return errors.New("ssh: no address known for client, but source-address match required")
@@ -455,7 +454,11 @@ userAuthLoop:
switch userAuthReq.Method {
case "none":
if config.NoClientAuth {
- authErr = nil
+ if config.NoClientAuthCallback != nil {
+ perms, authErr = config.NoClientAuthCallback(s)
+ } else {
+ authErr = nil
+ }
}
// allow initial attempt of 'none' without penalty
@@ -502,7 +505,7 @@ userAuthLoop:
return nil, parseError(msgUserAuthRequest)
}
algo := string(algoBytes)
- if !isAcceptableAlgo(algo) {
+ if !contains(supportedPubKeyAuthAlgos, underlyingAlgo(algo)) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
break
}
@@ -560,7 +563,7 @@ userAuthLoop:
// algorithm name that corresponds to algo with
// sig.Format. This is usually the same, but
// for certs, the names differ.
- if !isAcceptableAlgo(sig.Format) {
+ if !contains(supportedPubKeyAuthAlgos, sig.Format) {
authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
break
}
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
index eca31a22d..acef62259 100644
--- a/vendor/golang.org/x/crypto/ssh/session.go
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -13,7 +13,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"sync"
)
@@ -124,7 +123,7 @@ type Session struct {
// output and error.
//
// If either is nil, Run connects the corresponding file
- // descriptor to an instance of ioutil.Discard. There is a
+ // descriptor to an instance of io.Discard. There is a
// fixed amount of buffering that is shared for the two streams.
// If either blocks it may eventually cause the remote
// command to block.
@@ -506,7 +505,7 @@ func (s *Session) stdout() {
return
}
if s.Stdout == nil {
- s.Stdout = ioutil.Discard
+ s.Stdout = io.Discard
}
s.copyFuncs = append(s.copyFuncs, func() error {
_, err := io.Copy(s.Stdout, s.ch)
@@ -519,7 +518,7 @@ func (s *Session) stderr() {
return
}
if s.Stderr == nil {
- s.Stderr = ioutil.Discard
+ s.Stderr = io.Discard
}
s.copyFuncs = append(s.copyFuncs, func() error {
_, err := io.Copy(s.Stderr, s.ch.Stderr())