aboutsummaryrefslogtreecommitdiff
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/agent/client.go38
-rw-r--r--vendor/golang.org/x/crypto/ssh/agent/server.go90
-rw-r--r--vendor/golang.org/x/crypto/ssh/buffer.go5
-rw-r--r--vendor/golang.org/x/crypto/ssh/certs.go34
-rw-r--r--vendor/golang.org/x/crypto/ssh/cipher.go4
-rw-r--r--vendor/golang.org/x/crypto/ssh/client_auth.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/connection.go2
-rw-r--r--vendor/golang.org/x/crypto/ssh/handshake.go39
-rw-r--r--vendor/golang.org/x/crypto/ssh/kex.go8
-rw-r--r--vendor/golang.org/x/crypto/ssh/keys.go92
-rw-r--r--vendor/golang.org/x/crypto/ssh/server.go79
-rw-r--r--vendor/golang.org/x/crypto/ssh/session.go20
12 files changed, 337 insertions, 76 deletions
diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go
index ecfd7c5..dce7682 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/client.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/client.go
@@ -57,6 +57,17 @@ type Agent interface {
Signers() ([]ssh.Signer, error)
}
+// ConstraintExtension describes an optional constraint defined by users.
+type ConstraintExtension struct {
+ // ExtensionName consist of a UTF-8 string suffixed by the
+ // implementation domain following the naming scheme defined
+ // in Section 4.2 of [RFC4251], e.g. "foo@example.com".
+ ExtensionName string
+ // ExtensionDetails contains the actual content of the extended
+ // constraint.
+ ExtensionDetails []byte
+}
+
// AddedKey describes an SSH key to be added to an Agent.
type AddedKey struct {
// PrivateKey must be a *rsa.PrivateKey, *dsa.PrivateKey or
@@ -73,6 +84,9 @@ type AddedKey struct {
// ConfirmBeforeUse, if true, requests that the agent confirm with the
// user before each use of this key.
ConfirmBeforeUse bool
+ // ConstraintExtensions are the experimental or private-use constraints
+ // defined by users.
+ ConstraintExtensions []ConstraintExtension
}
// See [PROTOCOL.agent], section 3.
@@ -94,8 +108,9 @@ const (
agentAddSmartcardKeyConstrained = 26
// 3.7 Key constraint identifiers
- agentConstrainLifetime = 1
- agentConstrainConfirm = 2
+ agentConstrainLifetime = 1
+ agentConstrainConfirm = 2
+ agentConstrainExtension = 3
)
// maxAgentResponseBytes is the maximum agent reply size that is accepted. This
@@ -151,6 +166,19 @@ type publicKey struct {
Rest []byte `ssh:"rest"`
}
+// 3.7 Key constraint identifiers
+type constrainLifetimeAgentMsg struct {
+ LifetimeSecs uint32 `sshtype:"1"`
+}
+
+type constrainExtensionAgentMsg struct {
+ ExtensionName string `sshtype:"3"`
+ ExtensionDetails []byte
+
+ // Rest is a field used for parsing, not part of message
+ Rest []byte `ssh:"rest"`
+}
+
// Key represents a protocol 2 public key as defined in
// [PROTOCOL.agent], section 2.5.2.
type Key struct {
@@ -542,11 +570,7 @@ func (c *client) Add(key AddedKey) error {
var constraints []byte
if secs := key.LifetimeSecs; secs != 0 {
- constraints = append(constraints, agentConstrainLifetime)
-
- var secsBytes [4]byte
- binary.BigEndian.PutUint32(secsBytes[:], secs)
- constraints = append(constraints, secsBytes[:]...)
+ constraints = append(constraints, ssh.Marshal(constrainLifetimeAgentMsg{secs})...)
}
if key.ConfirmBeforeUse {
diff --git a/vendor/golang.org/x/crypto/ssh/agent/server.go b/vendor/golang.org/x/crypto/ssh/agent/server.go
index 68a333f..321e48a 100644
--- a/vendor/golang.org/x/crypto/ssh/agent/server.go
+++ b/vendor/golang.org/x/crypto/ssh/agent/server.go
@@ -106,7 +106,7 @@ func (s *server) processRequest(data []byte) (interface{}, error) {
return nil, s.agent.Lock(req.Passphrase)
case agentUnlock:
- var req agentLockMsg
+ var req agentUnlockMsg
if err := ssh.Unmarshal(data, &req); err != nil {
return nil, err
}
@@ -155,6 +155,44 @@ func (s *server) processRequest(data []byte) (interface{}, error) {
return nil, fmt.Errorf("unknown opcode %d", data[0])
}
+func parseConstraints(constraints []byte) (lifetimeSecs uint32, confirmBeforeUse bool, extensions []ConstraintExtension, err error) {
+ for len(constraints) != 0 {
+ switch constraints[0] {
+ case agentConstrainLifetime:
+ lifetimeSecs = binary.BigEndian.Uint32(constraints[1:5])
+ constraints = constraints[5:]
+ case agentConstrainConfirm:
+ confirmBeforeUse = true
+ constraints = constraints[1:]
+ case agentConstrainExtension:
+ var msg constrainExtensionAgentMsg
+ if err = ssh.Unmarshal(constraints, &msg); err != nil {
+ return 0, false, nil, err
+ }
+ extensions = append(extensions, ConstraintExtension{
+ ExtensionName: msg.ExtensionName,
+ ExtensionDetails: msg.ExtensionDetails,
+ })
+ constraints = msg.Rest
+ default:
+ return 0, false, nil, fmt.Errorf("unknown constraint type: %d", constraints[0])
+ }
+ }
+ return
+}
+
+func setConstraints(key *AddedKey, constraintBytes []byte) error {
+ lifetimeSecs, confirmBeforeUse, constraintExtensions, err := parseConstraints(constraintBytes)
+ if err != nil {
+ return err
+ }
+
+ key.LifetimeSecs = lifetimeSecs
+ key.ConfirmBeforeUse = confirmBeforeUse
+ key.ConstraintExtensions = constraintExtensions
+ return nil
+}
+
func parseRSAKey(req []byte) (*AddedKey, error) {
var k rsaKeyMsg
if err := ssh.Unmarshal(req, &k); err != nil {
@@ -173,7 +211,11 @@ func parseRSAKey(req []byte) (*AddedKey, error) {
}
priv.Precompute()
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseEd25519Key(req []byte) (*AddedKey, error) {
@@ -182,7 +224,12 @@ func parseEd25519Key(req []byte) (*AddedKey, error) {
return nil, err
}
priv := ed25519.PrivateKey(k.Priv)
- return &AddedKey{PrivateKey: &priv, Comment: k.Comments}, nil
+
+ addedKey := &AddedKey{PrivateKey: &priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseDSAKey(req []byte) (*AddedKey, error) {
@@ -202,7 +249,11 @@ func parseDSAKey(req []byte) (*AddedKey, error) {
X: k.X,
}
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func unmarshalECDSA(curveName string, keyBytes []byte, privScalar *big.Int) (priv *ecdsa.PrivateKey, err error) {
@@ -243,7 +294,12 @@ func parseEd25519Cert(req []byte) (*AddedKey, error) {
if !ok {
return nil, errors.New("agent: bad ED25519 certificate")
}
- return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
+
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseECDSAKey(req []byte) (*AddedKey, error) {
@@ -257,7 +313,11 @@ func parseECDSAKey(req []byte) (*AddedKey, error) {
return nil, err
}
- return &AddedKey{PrivateKey: priv, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseRSACert(req []byte) (*AddedKey, error) {
@@ -300,7 +360,11 @@ func parseRSACert(req []byte) (*AddedKey, error) {
}
priv.Precompute()
- return &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: &priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseDSACert(req []byte) (*AddedKey, error) {
@@ -338,7 +402,11 @@ func parseDSACert(req []byte) (*AddedKey, error) {
X: k.X,
}
- return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func parseECDSACert(req []byte) (*AddedKey, error) {
@@ -371,7 +439,11 @@ func parseECDSACert(req []byte) (*AddedKey, error) {
return nil, err
}
- return &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}, nil
+ addedKey := &AddedKey{PrivateKey: priv, Certificate: cert, Comment: k.Comments}
+ if err := setConstraints(addedKey, k.Constraints); err != nil {
+ return nil, err
+ }
+ return addedKey, nil
}
func (s *server) insertIdentity(req []byte) error {
diff --git a/vendor/golang.org/x/crypto/ssh/buffer.go b/vendor/golang.org/x/crypto/ssh/buffer.go
index 6931b51..1ab07d0 100644
--- a/vendor/golang.org/x/crypto/ssh/buffer.go
+++ b/vendor/golang.org/x/crypto/ssh/buffer.go
@@ -51,13 +51,12 @@ func (b *buffer) write(buf []byte) {
}
// eof closes the buffer. Reads from the buffer once all
-// the data has been consumed will receive os.EOF.
-func (b *buffer) eof() error {
+// the data has been consumed will receive io.EOF.
+func (b *buffer) eof() {
b.Cond.L.Lock()
b.closed = true
b.Cond.Signal()
b.Cond.L.Unlock()
- return nil
}
// Read reads data from the internal buffer in buf. Reads will block
diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go
index 67600e2..b1f0220 100644
--- a/vendor/golang.org/x/crypto/ssh/certs.go
+++ b/vendor/golang.org/x/crypto/ssh/certs.go
@@ -251,10 +251,18 @@ type CertChecker struct {
// for user certificates.
SupportedCriticalOptions []string
- // IsAuthority should return true if the key is recognized as
- // an authority. This allows for certificates to be signed by other
- // certificates.
- IsAuthority func(auth PublicKey) bool
+ // IsUserAuthority should return true if the key is recognized as an
+ // authority for the given user certificate. This allows for
+ // certificates to be signed by other certificates. This must be set
+ // if this CertChecker will be checking user certificates.
+ IsUserAuthority func(auth PublicKey) bool
+
+ // IsHostAuthority should report whether the key is recognized as
+ // an authority for this host. This allows for certificates to be
+ // signed by other keys, and for those other keys to only be valid
+ // signers for particular hostnames. This must be set if this
+ // CertChecker will be checking host certificates.
+ IsHostAuthority func(auth PublicKey, address string) bool
// Clock is used for verifying time stamps. If nil, time.Now
// is used.
@@ -290,8 +298,17 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey)
if cert.CertType != HostCert {
return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType)
}
+ if !c.IsHostAuthority(cert.SignatureKey, addr) {
+ return fmt.Errorf("ssh: no authorities for hostname: %v", addr)
+ }
+
+ hostname, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return err
+ }
- return c.CheckCert(addr, cert)
+ // Pass hostname only as principal for host certificates (consistent with OpenSSH)
+ return c.CheckCert(hostname, cert)
}
// Authenticate checks a user certificate. Authenticate can be used as
@@ -308,6 +325,9 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis
if cert.CertType != UserCert {
return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType)
}
+ if !c.IsUserAuthority(cert.SignatureKey) {
+ return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority")
+ }
if err := c.CheckCert(conn.User(), cert); err != nil {
return nil, err
@@ -356,10 +376,6 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error {
}
}
- if !c.IsAuthority(cert.SignatureKey) {
- return fmt.Errorf("ssh: certificate signed by unrecognized authority")
- }
-
clock := c.Clock
if clock == nil {
clock = time.Now
diff --git a/vendor/golang.org/x/crypto/ssh/cipher.go b/vendor/golang.org/x/crypto/ssh/cipher.go
index 13484ab..22bb30c 100644
--- a/vendor/golang.org/x/crypto/ssh/cipher.go
+++ b/vendor/golang.org/x/crypto/ssh/cipher.go
@@ -392,7 +392,9 @@ func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
c.incIV()
padding := plain[0]
- if padding < 4 || padding >= 20 {
+ 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)
}
diff --git a/vendor/golang.org/x/crypto/ssh/client_auth.go b/vendor/golang.org/x/crypto/ssh/client_auth.go
index b882da0..3acd8d4 100644
--- a/vendor/golang.org/x/crypto/ssh/client_auth.go
+++ b/vendor/golang.org/x/crypto/ssh/client_auth.go
@@ -349,7 +349,7 @@ func handleAuthResponse(c packetConn) (bool, []string, error) {
// both CLI and GUI environments.
type KeyboardInteractiveChallenge func(user, instruction string, questions []string, echos []bool) (answers []string, err error)
-// KeyboardInteractive returns a AuthMethod using a prompt/response
+// KeyboardInteractive returns an AuthMethod using a prompt/response
// sequence controlled by the server.
func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
return challenge
diff --git a/vendor/golang.org/x/crypto/ssh/connection.go b/vendor/golang.org/x/crypto/ssh/connection.go
index e786f2f..fd6b068 100644
--- a/vendor/golang.org/x/crypto/ssh/connection.go
+++ b/vendor/golang.org/x/crypto/ssh/connection.go
@@ -25,7 +25,7 @@ type ConnMetadata interface {
// User returns the user ID for this connection.
User() string
- // SessionID returns the sesson hash, also denoted by H.
+ // SessionID returns the session hash, also denoted by H.
SessionID() []byte
// ClientVersion returns the client's version string as hashed
diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go
index b9a2071..932ce83 100644
--- a/vendor/golang.org/x/crypto/ssh/handshake.go
+++ b/vendor/golang.org/x/crypto/ssh/handshake.go
@@ -107,6 +107,8 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
config: config,
}
+ t.resetReadThresholds()
+ t.resetWriteThresholds()
// We always start with a mandatory key exchange.
t.requestKex <- struct{}{}
@@ -237,6 +239,17 @@ func (t *handshakeTransport) requestKeyExchange() {
}
}
+func (t *handshakeTransport) resetWriteThresholds() {
+ t.writePacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.writeBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+ } else {
+ t.writeBytesLeft = 1 << 30
+ }
+}
+
func (t *handshakeTransport) kexLoop() {
write:
@@ -285,12 +298,8 @@ write:
t.writeError = err
t.sentInitPacket = nil
t.sentInitMsg = nil
- t.writePacketsLeft = packetRekeyThreshold
- if t.config.RekeyThreshold > 0 {
- t.writeBytesLeft = int64(t.config.RekeyThreshold)
- } else if t.algorithms != nil {
- t.writeBytesLeft = t.algorithms.w.rekeyBytes()
- }
+
+ t.resetWriteThresholds()
// we have completed the key exchange. Since the
// reader is still blocked, it is safe to clear out
@@ -344,6 +353,17 @@ write:
// key exchange itself.
const packetRekeyThreshold = (1 << 31)
+func (t *handshakeTransport) resetReadThresholds() {
+ t.readPacketsLeft = packetRekeyThreshold
+ if t.config.RekeyThreshold > 0 {
+ t.readBytesLeft = int64(t.config.RekeyThreshold)
+ } else if t.algorithms != nil {
+ t.readBytesLeft = t.algorithms.r.rekeyBytes()
+ } else {
+ t.readBytesLeft = 1 << 30
+ }
+}
+
func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
p, err := t.conn.readPacket()
if err != nil {
@@ -391,12 +411,7 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
return nil, err
}
- t.readPacketsLeft = packetRekeyThreshold
- if t.config.RekeyThreshold > 0 {
- t.readBytesLeft = int64(t.config.RekeyThreshold)
- } else {
- t.readBytesLeft = t.algorithms.r.rekeyBytes()
- }
+ t.resetReadThresholds()
// By default, a key exchange is hidden from higher layers by
// translating it into msgIgnore.
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index c87fbeb..f91c277 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -383,8 +383,8 @@ func init() {
// 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
@@ -393,8 +393,8 @@ func init() {
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go
index cf68532..b682c17 100644
--- a/vendor/golang.org/x/crypto/ssh/keys.go
+++ b/vendor/golang.org/x/crypto/ssh/keys.go
@@ -367,6 +367,17 @@ func (r *dsaPublicKey) Type() string {
return "ssh-dss"
}
+func checkDSAParams(param *dsa.Parameters) error {
+ // SSH specifies FIPS 186-2, which only provided a single size
+ // (1024 bits) DSA key. FIPS 186-3 allows for larger key
+ // sizes, which would confuse SSH.
+ if l := param.P.BitLen(); l != 1024 {
+ return fmt.Errorf("ssh: unsupported DSA key size %d", l)
+ }
+
+ return nil
+}
+
// parseDSA parses an DSA key according to RFC 4253, section 6.6.
func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
var w struct {
@@ -377,13 +388,18 @@ func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
return nil, nil, err
}
+ param := dsa.Parameters{
+ P: w.P,
+ Q: w.Q,
+ G: w.G,
+ }
+ if err := checkDSAParams(&param); err != nil {
+ return nil, nil, err
+ }
+
key := &dsaPublicKey{
- Parameters: dsa.Parameters{
- P: w.P,
- Q: w.Q,
- G: w.G,
- },
- Y: w.Y,
+ Parameters: param,
+ Y: w.Y,
}
return key, w.Rest, nil
}
@@ -630,19 +646,28 @@ func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
}
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
-// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
-// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
+// *ecdsa.PrivateKey or any other crypto.Signer and returns a
+// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
+// P-521. DSA keys must use parameter size L1024N160.
func NewSignerFromKey(key interface{}) (Signer, error) {
switch key := key.(type) {
case crypto.Signer:
return NewSignerFromSigner(key)
case *dsa.PrivateKey:
- return &dsaPrivateKey{key}, nil
+ return newDSAPrivateKey(key)
default:
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
}
}
+func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
+ if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
+ return nil, err
+ }
+
+ return &dsaPrivateKey{key}, nil
+}
+
type wrappedSigner struct {
signer crypto.Signer
pubKey PublicKey
@@ -756,6 +781,18 @@ func ParsePrivateKey(pemBytes []byte) (Signer, error) {
return NewSignerFromKey(key)
}
+// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
+// key and passphrase. It supports the same keys as
+// ParseRawPrivateKeyWithPassphrase.
+func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
+ key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
+ if err != nil {
+ return nil, err
+ }
+
+ return NewSignerFromKey(key)
+}
+
// encryptedBlock tells whether a private key is
// encrypted by examining its Proc-Type header
// for a mention of ENCRYPTED
@@ -790,6 +827,43 @@ func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
}
}
+// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
+// passphrase from a PEM encoded private key. If wrong passphrase, return
+// x509.IncorrectPasswordError.
+func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return nil, errors.New("ssh: no key found")
+ }
+ buf := block.Bytes
+
+ if encryptedBlock(block) {
+ if x509.IsEncryptedPEMBlock(block) {
+ var err error
+ buf, err = x509.DecryptPEMBlock(block, passPhrase)
+ if err != nil {
+ if err == x509.IncorrectPasswordError {
+ return nil, err
+ }
+ return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
+ }
+ }
+ }
+
+ switch block.Type {
+ case "RSA PRIVATE KEY":
+ return x509.ParsePKCS1PrivateKey(buf)
+ case "EC PRIVATE KEY":
+ return x509.ParseECPrivateKey(buf)
+ case "DSA PRIVATE KEY":
+ return ParseDSAPrivateKey(buf)
+ case "OPENSSH PRIVATE KEY":
+ return parseOpenSSHPrivateKey(buf)
+ default:
+ return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
+ }
+}
+
// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
// specified by the OpenSSL DSA man page.
func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
diff --git a/vendor/golang.org/x/crypto/ssh/server.go b/vendor/golang.org/x/crypto/ssh/server.go
index 8e95acc..8a78b7c 100644
--- a/vendor/golang.org/x/crypto/ssh/server.go
+++ b/vendor/golang.org/x/crypto/ssh/server.go
@@ -14,23 +14,34 @@ import (
)
// The Permissions type holds fine-grained permissions that are
-// specific to a user or a specific authentication method for a
-// user. Permissions, except for "source-address", must be enforced in
-// the server application layer, after successful authentication. The
-// Permissions are passed on in ServerConn so a server implementation
-// can honor them.
+// specific to a user or a specific authentication method for a user.
+// The Permissions value for a successful authentication attempt is
+// available in ServerConn, so it can be used to pass information from
+// the user-authentication phase to the application layer.
type Permissions struct {
- // Critical options restrict default permissions. Common
- // restrictions are "source-address" and "force-command". If
- // the server cannot enforce the restriction, or does not
- // recognize it, the user should not authenticate.
+ // CriticalOptions indicate restrictions to the default
+ // permissions, and are typically used in conjunction with
+ // user certificates. The standard for SSH certificates
+ // defines "force-command" (only allow the given command to
+ // execute) and "source-address" (only allow connections from
+ // the given address). The SSH package currently only enforces
+ // the "source-address" critical option. It is up to server
+ // implementations to enforce other critical options, such as
+ // "force-command", by checking them after the SSH handshake
+ // is successful. In general, SSH servers should reject
+ // connections that specify critical options that are unknown
+ // or not supported.
CriticalOptions map[string]string
// Extensions are extra functionality that the server may
- // offer on authenticated connections. Common extensions are
- // "permit-agent-forwarding", "permit-X11-forwarding". Lack of
- // support for an extension does not preclude authenticating a
- // user.
+ // offer on authenticated connections. Lack of support for an
+ // extension does not preclude authenticating a user. Common
+ // extensions are "permit-agent-forwarding",
+ // "permit-X11-forwarding". The Go SSH library currently does
+ // not act on any extension, and it is up to server
+ // implementations to honor them. Extensions can be used to
+ // pass data from the authentication callbacks to the server
+ // application layer.
Extensions map[string]string
}
@@ -55,9 +66,14 @@ type ServerConfig struct {
// attempts to authenticate using a password.
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
- // PublicKeyCallback, if non-nil, is called when a client attempts public
- // key authentication. It must return true if the given public key is
- // valid for the given user. For example, see CertChecker.Authenticate.
+ // PublicKeyCallback, if non-nil, is called when a client
+ // offers a public key for authentication. It must return a nil error
+ // if the given public key can be used to authenticate the
+ // given user. For example, see CertChecker.Authenticate. A
+ // call to this function does not guarantee that the key
+ // offered is in fact used to authenticate. To record any data
+ // depending on the public key, store it inside a
+ // Permissions.Extensions entry.
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
// KeyboardInteractiveCallback, if non-nil, is called when
@@ -147,12 +163,12 @@ type ServerConn struct {
// Request and NewChannel channels must be serviced, or the connection
// will hang.
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
- if config.MaxAuthTries == 0 {
- config.MaxAuthTries = 6
- }
-
fullConf := *config
fullConf.SetDefaults()
+ if fullConf.MaxAuthTries == 0 {
+ fullConf.MaxAuthTries = 6
+ }
+
s := &connection{
sshConn: sshConn{conn: c},
}
@@ -272,12 +288,30 @@ 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.
+type ServerAuthError struct {
+ // Errors contains authentication errors returned by the authentication
+ // callback methods.
+ Errors []error
+}
+
+func (l ServerAuthError) Error() string {
+ var errs []string
+ for _, err := range l.Errors {
+ errs = append(errs, err.Error())
+ }
+ return "[" + strings.Join(errs, ", ") + "]"
+}
+
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
sessionID := s.transport.getSessionID()
var cache pubKeyCache
var perms *Permissions
authFailures := 0
+ var authErrs []error
userAuthLoop:
for {
@@ -296,6 +330,9 @@ userAuthLoop:
var userAuthReq userAuthRequestMsg
if packet, err := s.transport.readPacket(); err != nil {
+ if err == io.EOF {
+ return nil, &ServerAuthError{Errors: authErrs}
+ }
return nil, err
} else if err = Unmarshal(packet, &userAuthReq); err != nil {
return nil, err
@@ -432,6 +469,8 @@ userAuthLoop:
authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
}
+ authErrs = append(authErrs, authErr)
+
if config.AuthLogCallback != nil {
config.AuthLogCallback(s, userAuthReq.Method, authErr)
}
diff --git a/vendor/golang.org/x/crypto/ssh/session.go b/vendor/golang.org/x/crypto/ssh/session.go
index 17e2aa8..cc06e03 100644
--- a/vendor/golang.org/x/crypto/ssh/session.go
+++ b/vendor/golang.org/x/crypto/ssh/session.go
@@ -231,6 +231,26 @@ func (s *Session) RequestSubsystem(subsystem string) error {
return err
}
+// RFC 4254 Section 6.7.
+type ptyWindowChangeMsg struct {
+ Columns uint32
+ Rows uint32
+ Width uint32
+ Height uint32
+}
+
+// WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.
+func (s *Session) WindowChange(h, w int) error {
+ req := ptyWindowChangeMsg{
+ Columns: uint32(w),
+ Rows: uint32(h),
+ Width: uint32(w * 8),
+ Height: uint32(h * 8),
+ }
+ _, err := s.ch.SendRequest("window-change", false, Marshal(&req))
+ return err
+}
+
// RFC 4254 Section 6.9.
type signalMsg struct {
Signal string