mirror of
https://github.com/appleboy/drone-ssh.git
synced 2025-07-02 21:52:51 +08:00
refactor: HostKeyCallback is the function type used for verifying server (#68)
This commit is contained in:
parent
6c2d8f278d
commit
c73e22e279
26
vendor/github.com/appleboy/easyssh-proxy/Makefile
generated
vendored
26
vendor/github.com/appleboy/easyssh-proxy/Makefile
generated
vendored
@ -1,11 +1,29 @@
|
|||||||
.PHONY: test drone-ssh build fmt vet errcheck lint install update release-dirs release-build release-copy release-check release coverage embedmd
|
.PHONY: test drone-ssh fmt vet errcheck lint install update coverage embedmd
|
||||||
|
|
||||||
|
GOFMT ?= gofmt "-s"
|
||||||
|
|
||||||
|
GOFILES := find . -name "*.go" -type f -not -path "./vendor/*"
|
||||||
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
|
||||||
|
|
||||||
all: build
|
all: install lint
|
||||||
|
|
||||||
|
install:
|
||||||
|
@hash govendor > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||||
|
go get -u github.com/kardianos/govendor; \
|
||||||
|
fi
|
||||||
|
govendor sync
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
find . -name "*.go" -type f -not -path "./vendor/*" | xargs gofmt -s -w
|
$(GOFILES) | xargs $(GOFMT) -w
|
||||||
|
|
||||||
|
.PHONY: fmt-check
|
||||||
|
fmt-check:
|
||||||
|
# get all go files and run go fmt on them
|
||||||
|
@files=$$($(GOFILES) | xargs $(GOFMT) -l); if [ -n "$$files" ]; then \
|
||||||
|
echo "Please run 'make fmt' and commit the result:"; \
|
||||||
|
echo "$${files}"; \
|
||||||
|
exit 1; \
|
||||||
|
fi;
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
go vet $(PACKAGES)
|
go vet $(PACKAGES)
|
||||||
@ -34,7 +52,7 @@ embedmd:
|
|||||||
fi
|
fi
|
||||||
embedmd -d *.md
|
embedmd -d *.md
|
||||||
|
|
||||||
test:
|
test: fmt-check
|
||||||
for PKG in $(PACKAGES); do go test -v -cover -coverprofile $$GOPATH/src/$$PKG/coverage.txt $$PKG || exit 1; done;
|
for PKG in $(PACKAGES); do go test -v -cover -coverprofile $$GOPATH/src/$$PKG/coverage.txt $$PKG || exit 1; done;
|
||||||
|
|
||||||
html:
|
html:
|
||||||
|
3
vendor/github.com/appleboy/easyssh-proxy/README.md
generated
vendored
3
vendor/github.com/appleboy/easyssh-proxy/README.md
generated
vendored
@ -40,6 +40,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/appleboy/easyssh-proxy"
|
"github.com/appleboy/easyssh-proxy"
|
||||||
)
|
)
|
||||||
@ -53,7 +54,7 @@ func main() {
|
|||||||
//Password: "password",
|
//Password: "password",
|
||||||
Key: "/.ssh/id_rsa",
|
Key: "/.ssh/id_rsa",
|
||||||
Port: "22",
|
Port: "22",
|
||||||
Timeout: 60,
|
Timeout: 60 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call Run method with command you want to run on remote server.
|
// Call Run method with command you want to run on remote server.
|
||||||
|
1
vendor/github.com/appleboy/easyssh-proxy/easyssh.go
generated
vendored
1
vendor/github.com/appleboy/easyssh-proxy/easyssh.go
generated
vendored
@ -94,6 +94,7 @@ func getSSHConfig(config DefaultConfig) *ssh.ClientConfig {
|
|||||||
Timeout: config.Timeout,
|
Timeout: config.Timeout,
|
||||||
User: config.User,
|
User: config.User,
|
||||||
Auth: auths,
|
Auth: auths,
|
||||||
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
2
vendor/golang.org/x/crypto/ssh/certs.go
generated
vendored
@ -268,7 +268,7 @@ type CertChecker struct {
|
|||||||
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
|
// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
|
||||||
// public key that is not a certificate. It must implement host key
|
// public key that is not a certificate. It must implement host key
|
||||||
// validation or else, if nil, all such keys are rejected.
|
// validation or else, if nil, all such keys are rejected.
|
||||||
HostKeyFallback func(addr string, remote net.Addr, key PublicKey) error
|
HostKeyFallback HostKeyCallback
|
||||||
|
|
||||||
// IsRevoked is called for each certificate so that revocation checking
|
// IsRevoked is called for each certificate so that revocation checking
|
||||||
// can be implemented. It should return true if the given certificate
|
// can be implemented. It should return true if the given certificate
|
||||||
|
56
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
56
vendor/golang.org/x/crypto/ssh/client.go
generated
vendored
@ -5,6 +5,7 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
@ -13,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Client implements a traditional SSH client that supports shells,
|
// Client implements a traditional SSH client that supports shells,
|
||||||
// subprocesses, port forwarding and tunneled dialing.
|
// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Conn
|
Conn
|
||||||
|
|
||||||
@ -59,6 +60,7 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
|||||||
conn.forwards.closeAll()
|
conn.forwards.closeAll()
|
||||||
}()
|
}()
|
||||||
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-tcpip"))
|
||||||
|
go conn.forwards.handleChannels(conn.HandleChannelOpen("forwarded-streamlocal@openssh.com"))
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +70,11 @@ func NewClient(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client {
|
|||||||
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
|
func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error) {
|
||||||
fullConf := *config
|
fullConf := *config
|
||||||
fullConf.SetDefaults()
|
fullConf.SetDefaults()
|
||||||
|
if fullConf.HostKeyCallback == nil {
|
||||||
|
c.Close()
|
||||||
|
return nil, nil, nil, errors.New("ssh: must specify HostKeyCallback")
|
||||||
|
}
|
||||||
|
|
||||||
conn := &connection{
|
conn := &connection{
|
||||||
sshConn: sshConn{conn: c},
|
sshConn: sshConn{conn: c},
|
||||||
}
|
}
|
||||||
@ -173,6 +180,13 @@ func Dial(network, addr string, config *ClientConfig) (*Client, error) {
|
|||||||
return NewClient(c, chans, reqs), nil
|
return NewClient(c, chans, reqs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostKeyCallback is the function type used for verifying server
|
||||||
|
// keys. A HostKeyCallback must return nil if the host key is OK, or
|
||||||
|
// an error to reject it. It receives the hostname as passed to Dial
|
||||||
|
// or NewClientConn. The remote address is the RemoteAddr of the
|
||||||
|
// net.Conn underlying the the SSH connection.
|
||||||
|
type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
||||||
|
|
||||||
// A ClientConfig structure is used to configure a Client. It must not be
|
// A ClientConfig structure is used to configure a Client. It must not be
|
||||||
// modified after having been passed to an SSH function.
|
// modified after having been passed to an SSH function.
|
||||||
type ClientConfig struct {
|
type ClientConfig struct {
|
||||||
@ -188,10 +202,12 @@ type ClientConfig struct {
|
|||||||
// be used during authentication.
|
// be used during authentication.
|
||||||
Auth []AuthMethod
|
Auth []AuthMethod
|
||||||
|
|
||||||
// HostKeyCallback, if not nil, is called during the cryptographic
|
// HostKeyCallback is called during the cryptographic
|
||||||
// handshake to validate the server's host key. A nil HostKeyCallback
|
// handshake to validate the server's host key. The client
|
||||||
// implies that all host keys are accepted.
|
// configuration must supply this callback for the connection
|
||||||
HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
// to succeed. The functions InsecureIgnoreHostKey or
|
||||||
|
// FixedHostKey can be used for simplistic host key checks.
|
||||||
|
HostKeyCallback HostKeyCallback
|
||||||
|
|
||||||
// ClientVersion contains the version identification string that will
|
// ClientVersion contains the version identification string that will
|
||||||
// be used for the connection. If empty, a reasonable default is used.
|
// be used for the connection. If empty, a reasonable default is used.
|
||||||
@ -209,3 +225,33 @@ type ClientConfig struct {
|
|||||||
// A Timeout of zero means no timeout.
|
// A Timeout of zero means no timeout.
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InsecureIgnoreHostKey returns a function that can be used for
|
||||||
|
// ClientConfig.HostKeyCallback to accept any host key. It should
|
||||||
|
// not be used for production code.
|
||||||
|
func InsecureIgnoreHostKey() HostKeyCallback {
|
||||||
|
return func(hostname string, remote net.Addr, key PublicKey) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fixedHostKey struct {
|
||||||
|
key PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fixedHostKey) check(hostname string, remote net.Addr, key PublicKey) error {
|
||||||
|
if f.key == nil {
|
||||||
|
return fmt.Errorf("ssh: required host key was nil")
|
||||||
|
}
|
||||||
|
if !bytes.Equal(key.Marshal(), f.key.Marshal()) {
|
||||||
|
return fmt.Errorf("ssh: host key mismatch")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FixedHostKey returns a function for use in
|
||||||
|
// ClientConfig.HostKeyCallback to accept only a specific host key.
|
||||||
|
func FixedHostKey(key PublicKey) HostKeyCallback {
|
||||||
|
hk := &fixedHostKey{key}
|
||||||
|
return hk.check
|
||||||
|
}
|
||||||
|
39
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
39
vendor/golang.org/x/crypto/ssh/client_auth.go
generated
vendored
@ -179,31 +179,26 @@ func (cb publicKeyCallback) method() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) (bool, []string, error) {
|
||||||
// Authentication is performed in two stages. The first stage sends an
|
// Authentication is performed by sending an enquiry to test if a key is
|
||||||
// enquiry to test if each key is acceptable to the remote. The second
|
// acceptable to the remote. If the key is acceptable, the client will
|
||||||
// stage attempts to authenticate with the valid keys obtained in the
|
// attempt to authenticate with the valid key. If not the client will repeat
|
||||||
// first stage.
|
// the process with the remaining keys.
|
||||||
|
|
||||||
signers, err := cb()
|
signers, err := cb()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
var validKeys []Signer
|
var methods []string
|
||||||
for _, signer := range signers {
|
for _, signer := range signers {
|
||||||
if ok, err := validateKey(signer.PublicKey(), user, c); ok {
|
ok, err := validateKey(signer.PublicKey(), user, c)
|
||||||
validKeys = append(validKeys, signer)
|
|
||||||
} else {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
}
|
if !ok {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// methods that may continue if this auth is not successful.
|
|
||||||
var methods []string
|
|
||||||
for _, signer := range validKeys {
|
|
||||||
pub := signer.PublicKey()
|
pub := signer.PublicKey()
|
||||||
|
|
||||||
pubKey := pub.Marshal()
|
pubKey := pub.Marshal()
|
||||||
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
sign, err := signer.Sign(rand, buildDataSignedForAuth(session, userAuthRequestMsg{
|
||||||
User: user,
|
User: user,
|
||||||
@ -236,13 +231,29 @@ func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
if success {
|
|
||||||
|
// 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()) {
|
||||||
return success, methods, err
|
return success, methods, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, methods, nil
|
return false, methods, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func containsMethod(methods []string, method string) bool {
|
||||||
|
for _, m := range methods {
|
||||||
|
if m == method {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// validateKey validates the key provided is acceptable to the server.
|
// validateKey validates the key provided is acceptable to the server.
|
||||||
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
func validateKey(key PublicKey, user string, c packetConn) (bool, error) {
|
||||||
pubKey := key.Marshal()
|
pubKey := key.Marshal()
|
||||||
|
14
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
14
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
_ "crypto/sha1"
|
_ "crypto/sha1"
|
||||||
@ -40,7 +41,7 @@ var supportedKexAlgos = []string{
|
|||||||
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
||||||
}
|
}
|
||||||
|
|
||||||
// supportedKexAlgos specifies the supported host-key algorithms (i.e. methods
|
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||||
// of authenticating servers) in preference order.
|
// of authenticating servers) in preference order.
|
||||||
var supportedHostKeyAlgos = []string{
|
var supportedHostKeyAlgos = []string{
|
||||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||||
@ -186,7 +187,7 @@ type Config struct {
|
|||||||
|
|
||||||
// The maximum number of bytes sent or received after which a
|
// The maximum number of bytes sent or received after which a
|
||||||
// new key is negotiated. It must be at least 256. If
|
// new key is negotiated. It must be at least 256. If
|
||||||
// unspecified, 1 gigabyte is used.
|
// unspecified, a size suitable for the chosen cipher is used.
|
||||||
RekeyThreshold uint64
|
RekeyThreshold uint64
|
||||||
|
|
||||||
// The allowed key exchanges algorithms. If unspecified then a
|
// The allowed key exchanges algorithms. If unspecified then a
|
||||||
@ -230,11 +231,12 @@ func (c *Config) SetDefaults() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.RekeyThreshold == 0 {
|
if c.RekeyThreshold == 0 {
|
||||||
// RFC 4253, section 9 suggests rekeying after 1G.
|
// cipher specific default
|
||||||
c.RekeyThreshold = 1 << 30
|
} else if c.RekeyThreshold < minRekeyThreshold {
|
||||||
}
|
|
||||||
if c.RekeyThreshold < minRekeyThreshold {
|
|
||||||
c.RekeyThreshold = minRekeyThreshold
|
c.RekeyThreshold = minRekeyThreshold
|
||||||
|
} else if c.RekeyThreshold >= math.MaxInt64 {
|
||||||
|
// Avoid weirdness if somebody uses -1 as a threshold.
|
||||||
|
c.RekeyThreshold = math.MaxInt64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
3
vendor/golang.org/x/crypto/ssh/doc.go
generated
vendored
@ -14,5 +14,8 @@ others.
|
|||||||
References:
|
References:
|
||||||
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
|
||||||
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
|
||||||
|
|
||||||
|
This package does not fall under the stability promise of the Go language itself,
|
||||||
|
so its API may be changed when pressing needs arise.
|
||||||
*/
|
*/
|
||||||
package ssh // import "golang.org/x/crypto/ssh"
|
package ssh // import "golang.org/x/crypto/ssh"
|
||||||
|
47
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
47
vendor/golang.org/x/crypto/ssh/handshake.go
generated
vendored
@ -74,7 +74,7 @@ type handshakeTransport struct {
|
|||||||
startKex chan *pendingKex
|
startKex chan *pendingKex
|
||||||
|
|
||||||
// data for host key checking
|
// data for host key checking
|
||||||
hostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error
|
hostKeyCallback HostKeyCallback
|
||||||
dialAddress string
|
dialAddress string
|
||||||
remoteAddr net.Addr
|
remoteAddr net.Addr
|
||||||
|
|
||||||
@ -107,6 +107,8 @@ func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion,
|
|||||||
|
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
|
t.resetReadThresholds()
|
||||||
|
t.resetWriteThresholds()
|
||||||
|
|
||||||
// We always start with a mandatory key exchange.
|
// We always start with a mandatory key exchange.
|
||||||
t.requestKex <- struct{}{}
|
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() {
|
func (t *handshakeTransport) kexLoop() {
|
||||||
|
|
||||||
write:
|
write:
|
||||||
@ -285,12 +298,8 @@ write:
|
|||||||
t.writeError = err
|
t.writeError = err
|
||||||
t.sentInitPacket = nil
|
t.sentInitPacket = nil
|
||||||
t.sentInitMsg = nil
|
t.sentInitMsg = nil
|
||||||
t.writePacketsLeft = packetRekeyThreshold
|
|
||||||
if t.config.RekeyThreshold > 0 {
|
t.resetWriteThresholds()
|
||||||
t.writeBytesLeft = int64(t.config.RekeyThreshold)
|
|
||||||
} else if t.algorithms != nil {
|
|
||||||
t.writeBytesLeft = t.algorithms.w.rekeyBytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have completed the key exchange. Since the
|
// we have completed the key exchange. Since the
|
||||||
// reader is still blocked, it is safe to clear out
|
// reader is still blocked, it is safe to clear out
|
||||||
@ -344,6 +353,17 @@ write:
|
|||||||
// key exchange itself.
|
// key exchange itself.
|
||||||
const packetRekeyThreshold = (1 << 31)
|
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) {
|
func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||||
p, err := t.conn.readPacket()
|
p, err := t.conn.readPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -391,12 +411,7 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
t.readPacketsLeft = packetRekeyThreshold
|
t.resetReadThresholds()
|
||||||
if t.config.RekeyThreshold > 0 {
|
|
||||||
t.readBytesLeft = int64(t.config.RekeyThreshold)
|
|
||||||
} else {
|
|
||||||
t.readBytesLeft = t.algorithms.r.rekeyBytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, a key exchange is hidden from higher layers by
|
// By default, a key exchange is hidden from higher layers by
|
||||||
// translating it into msgIgnore.
|
// translating it into msgIgnore.
|
||||||
@ -574,7 +589,9 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||||||
}
|
}
|
||||||
result.SessionID = t.sessionID
|
result.SessionID = t.sessionID
|
||||||
|
|
||||||
t.conn.prepareKeyChange(t.algorithms, result)
|
if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -614,12 +631,10 @@ func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.hostKeyCallback != nil {
|
|
||||||
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
74
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
74
vendor/golang.org/x/crypto/ssh/keys.go
generated
vendored
@ -824,7 +824,7 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
|
|||||||
|
|
||||||
// Implemented based on the documentation at
|
// Implemented based on the documentation at
|
||||||
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
|
||||||
func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
|
||||||
magic := append([]byte("openssh-key-v1"), 0)
|
magic := append([]byte("openssh-key-v1"), 0)
|
||||||
if !bytes.Equal(magic, key[0:len(magic)]) {
|
if !bytes.Equal(magic, key[0:len(magic)]) {
|
||||||
return nil, errors.New("ssh: invalid openssh private key format")
|
return nil, errors.New("ssh: invalid openssh private key format")
|
||||||
@ -844,14 +844,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if w.KdfName != "none" || w.CipherName != "none" {
|
||||||
|
return nil, errors.New("ssh: cannot decode encrypted private keys")
|
||||||
|
}
|
||||||
|
|
||||||
pk1 := struct {
|
pk1 := struct {
|
||||||
Check1 uint32
|
Check1 uint32
|
||||||
Check2 uint32
|
Check2 uint32
|
||||||
Keytype string
|
Keytype string
|
||||||
Pub []byte
|
Rest []byte `ssh:"rest"`
|
||||||
Priv []byte
|
|
||||||
Comment string
|
|
||||||
Pad []byte `ssh:"rest"`
|
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
|
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
|
||||||
@ -862,24 +863,75 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
|
|||||||
return nil, errors.New("ssh: checkint mismatch")
|
return nil, errors.New("ssh: checkint mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
// we only handle ed25519 keys currently
|
// we only handle ed25519 and rsa keys currently
|
||||||
if pk1.Keytype != KeyAlgoED25519 {
|
switch pk1.Keytype {
|
||||||
return nil, errors.New("ssh: unhandled key type")
|
case KeyAlgoRSA:
|
||||||
|
// https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
|
||||||
|
key := struct {
|
||||||
|
N *big.Int
|
||||||
|
E *big.Int
|
||||||
|
D *big.Int
|
||||||
|
Iqmp *big.Int
|
||||||
|
P *big.Int
|
||||||
|
Q *big.Int
|
||||||
|
Comment string
|
||||||
|
Pad []byte `ssh:"rest"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
if err := Unmarshal(pk1.Rest, &key); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, b := range pk1.Pad {
|
for i, b := range key.Pad {
|
||||||
if int(b) != i+1 {
|
if int(b) != i+1 {
|
||||||
return nil, errors.New("ssh: padding not as expected")
|
return nil, errors.New("ssh: padding not as expected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pk1.Priv) != ed25519.PrivateKeySize {
|
pk := &rsa.PrivateKey{
|
||||||
|
PublicKey: rsa.PublicKey{
|
||||||
|
N: key.N,
|
||||||
|
E: int(key.E.Int64()),
|
||||||
|
},
|
||||||
|
D: key.D,
|
||||||
|
Primes: []*big.Int{key.P, key.Q},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := pk.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pk.Precompute()
|
||||||
|
|
||||||
|
return pk, nil
|
||||||
|
case KeyAlgoED25519:
|
||||||
|
key := struct {
|
||||||
|
Pub []byte
|
||||||
|
Priv []byte
|
||||||
|
Comment string
|
||||||
|
Pad []byte `ssh:"rest"`
|
||||||
|
}{}
|
||||||
|
|
||||||
|
if err := Unmarshal(pk1.Rest, &key); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(key.Priv) != ed25519.PrivateKeySize {
|
||||||
return nil, errors.New("ssh: private key unexpected length")
|
return nil, errors.New("ssh: private key unexpected length")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i, b := range key.Pad {
|
||||||
|
if int(b) != i+1 {
|
||||||
|
return nil, errors.New("ssh: padding not as expected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
|
||||||
copy(pk, pk1.Priv)
|
copy(pk, key.Priv)
|
||||||
return &pk, nil
|
return &pk, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New("ssh: unhandled key type")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FingerprintLegacyMD5 returns the user presentation of the key's
|
// FingerprintLegacyMD5 returns the user presentation of the key's
|
||||||
|
33
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
33
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
@ -45,6 +45,12 @@ type ServerConfig struct {
|
|||||||
// authenticating.
|
// authenticating.
|
||||||
NoClientAuth bool
|
NoClientAuth bool
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// to 6.
|
||||||
|
MaxAuthTries int
|
||||||
|
|
||||||
// PasswordCallback, if non-nil, is called when a user
|
// PasswordCallback, if non-nil, is called when a user
|
||||||
// attempts to authenticate using a password.
|
// attempts to authenticate using a password.
|
||||||
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
|
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
|
||||||
@ -141,6 +147,10 @@ type ServerConn struct {
|
|||||||
// Request and NewChannel channels must be serviced, or the connection
|
// Request and NewChannel channels must be serviced, or the connection
|
||||||
// will hang.
|
// will hang.
|
||||||
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
|
func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
|
||||||
|
if config.MaxAuthTries == 0 {
|
||||||
|
config.MaxAuthTries = 6
|
||||||
|
}
|
||||||
|
|
||||||
fullConf := *config
|
fullConf := *config
|
||||||
fullConf.SetDefaults()
|
fullConf.SetDefaults()
|
||||||
s := &connection{
|
s := &connection{
|
||||||
@ -267,8 +277,23 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err
|
|||||||
var cache pubKeyCache
|
var cache pubKeyCache
|
||||||
var perms *Permissions
|
var perms *Permissions
|
||||||
|
|
||||||
|
authFailures := 0
|
||||||
|
|
||||||
userAuthLoop:
|
userAuthLoop:
|
||||||
for {
|
for {
|
||||||
|
if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
|
||||||
|
discMsg := &disconnectMsg{
|
||||||
|
Reason: 2,
|
||||||
|
Message: "too many authentication failures",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, discMsg
|
||||||
|
}
|
||||||
|
|
||||||
var userAuthReq userAuthRequestMsg
|
var userAuthReq userAuthRequestMsg
|
||||||
if packet, err := s.transport.readPacket(); err != nil {
|
if packet, err := s.transport.readPacket(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -289,6 +314,11 @@ userAuthLoop:
|
|||||||
if config.NoClientAuth {
|
if config.NoClientAuth {
|
||||||
authErr = nil
|
authErr = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow initial attempt of 'none' without penalty
|
||||||
|
if authFailures == 0 {
|
||||||
|
authFailures--
|
||||||
|
}
|
||||||
case "password":
|
case "password":
|
||||||
if config.PasswordCallback == nil {
|
if config.PasswordCallback == nil {
|
||||||
authErr = errors.New("ssh: password auth not configured")
|
authErr = errors.New("ssh: password auth not configured")
|
||||||
@ -360,6 +390,7 @@ userAuthLoop:
|
|||||||
if isQuery {
|
if isQuery {
|
||||||
// The client can query if the given public key
|
// The client can query if the given public key
|
||||||
// would be okay.
|
// would be okay.
|
||||||
|
|
||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
@ -409,6 +440,8 @@ userAuthLoop:
|
|||||||
break userAuthLoop
|
break userAuthLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authFailures++
|
||||||
|
|
||||||
var failureMsg userAuthFailureMsg
|
var failureMsg userAuthFailureMsg
|
||||||
if config.PasswordCallback != nil {
|
if config.PasswordCallback != nil {
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "password")
|
failureMsg.Methods = append(failureMsg.Methods, "password")
|
||||||
|
115
vendor/golang.org/x/crypto/ssh/streamlocal.go
generated
vendored
Normal file
115
vendor/golang.org/x/crypto/ssh/streamlocal.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// streamLocalChannelOpenDirectMsg is a struct used for SSH_MSG_CHANNEL_OPEN message
|
||||||
|
// with "direct-streamlocal@openssh.com" string.
|
||||||
|
//
|
||||||
|
// See openssh-portable/PROTOCOL, section 2.4. connection: Unix domain socket forwarding
|
||||||
|
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL#L235
|
||||||
|
type streamLocalChannelOpenDirectMsg struct {
|
||||||
|
socketPath string
|
||||||
|
reserved0 string
|
||||||
|
reserved1 uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// forwardedStreamLocalPayload is a struct used for SSH_MSG_CHANNEL_OPEN message
|
||||||
|
// with "forwarded-streamlocal@openssh.com" string.
|
||||||
|
type forwardedStreamLocalPayload struct {
|
||||||
|
SocketPath string
|
||||||
|
Reserved0 string
|
||||||
|
}
|
||||||
|
|
||||||
|
// streamLocalChannelForwardMsg is a struct used for SSH2_MSG_GLOBAL_REQUEST message
|
||||||
|
// with "streamlocal-forward@openssh.com"/"cancel-streamlocal-forward@openssh.com" string.
|
||||||
|
type streamLocalChannelForwardMsg struct {
|
||||||
|
socketPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenUnix is similar to ListenTCP but uses a Unix domain socket.
|
||||||
|
func (c *Client) ListenUnix(socketPath string) (net.Listener, error) {
|
||||||
|
m := streamLocalChannelForwardMsg{
|
||||||
|
socketPath,
|
||||||
|
}
|
||||||
|
// send message
|
||||||
|
ok, _, err := c.SendRequest("streamlocal-forward@openssh.com", true, Marshal(&m))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("ssh: streamlocal-forward@openssh.com request denied by peer")
|
||||||
|
}
|
||||||
|
ch := c.forwards.add(&net.UnixAddr{Name: socketPath, Net: "unix"})
|
||||||
|
|
||||||
|
return &unixListener{socketPath, c, ch}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) dialStreamLocal(socketPath string) (Channel, error) {
|
||||||
|
msg := streamLocalChannelOpenDirectMsg{
|
||||||
|
socketPath: socketPath,
|
||||||
|
}
|
||||||
|
ch, in, err := c.OpenChannel("direct-streamlocal@openssh.com", Marshal(&msg))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go DiscardRequests(in)
|
||||||
|
return ch, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type unixListener struct {
|
||||||
|
socketPath string
|
||||||
|
|
||||||
|
conn *Client
|
||||||
|
in <-chan forward
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept waits for and returns the next connection to the listener.
|
||||||
|
func (l *unixListener) Accept() (net.Conn, error) {
|
||||||
|
s, ok := <-l.in
|
||||||
|
if !ok {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
ch, incoming, err := s.newCh.Accept()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
go DiscardRequests(incoming)
|
||||||
|
|
||||||
|
return &chanConn{
|
||||||
|
Channel: ch,
|
||||||
|
laddr: &net.UnixAddr{
|
||||||
|
Name: l.socketPath,
|
||||||
|
Net: "unix",
|
||||||
|
},
|
||||||
|
raddr: &net.UnixAddr{
|
||||||
|
Name: "@",
|
||||||
|
Net: "unix",
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the listener.
|
||||||
|
func (l *unixListener) Close() error {
|
||||||
|
// this also closes the listener.
|
||||||
|
l.conn.forwards.remove(&net.UnixAddr{Name: l.socketPath, Net: "unix"})
|
||||||
|
m := streamLocalChannelForwardMsg{
|
||||||
|
l.socketPath,
|
||||||
|
}
|
||||||
|
ok, _, err := l.conn.SendRequest("cancel-streamlocal-forward@openssh.com", true, Marshal(&m))
|
||||||
|
if err == nil && !ok {
|
||||||
|
err = errors.New("ssh: cancel-streamlocal-forward@openssh.com failed")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr returns the listener's network address.
|
||||||
|
func (l *unixListener) Addr() net.Addr {
|
||||||
|
return &net.UnixAddr{
|
||||||
|
Name: l.socketPath,
|
||||||
|
Net: "unix",
|
||||||
|
}
|
||||||
|
}
|
118
vendor/golang.org/x/crypto/ssh/tcpip.go
generated
vendored
118
vendor/golang.org/x/crypto/ssh/tcpip.go
generated
vendored
@ -20,12 +20,20 @@ import (
|
|||||||
// addr. Incoming connections will be available by calling Accept on
|
// addr. Incoming connections will be available by calling Accept on
|
||||||
// the returned net.Listener. The listener must be serviced, or the
|
// the returned net.Listener. The listener must be serviced, or the
|
||||||
// SSH connection may hang.
|
// SSH connection may hang.
|
||||||
|
// N must be "tcp", "tcp4", "tcp6", or "unix".
|
||||||
func (c *Client) Listen(n, addr string) (net.Listener, error) {
|
func (c *Client) Listen(n, addr string) (net.Listener, error) {
|
||||||
|
switch n {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
laddr, err := net.ResolveTCPAddr(n, addr)
|
laddr, err := net.ResolveTCPAddr(n, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return c.ListenTCP(laddr)
|
return c.ListenTCP(laddr)
|
||||||
|
case "unix":
|
||||||
|
return c.ListenUnix(addr)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatic port allocation is broken with OpenSSH before 6.0. See
|
// Automatic port allocation is broken with OpenSSH before 6.0. See
|
||||||
@ -116,7 +124,7 @@ func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register this forward, using the port number we obtained.
|
// Register this forward, using the port number we obtained.
|
||||||
ch := c.forwards.add(*laddr)
|
ch := c.forwards.add(laddr)
|
||||||
|
|
||||||
return &tcpListener{laddr, c, ch}, nil
|
return &tcpListener{laddr, c, ch}, nil
|
||||||
}
|
}
|
||||||
@ -131,7 +139,7 @@ type forwardList struct {
|
|||||||
// forwardEntry represents an established mapping of a laddr on a
|
// forwardEntry represents an established mapping of a laddr on a
|
||||||
// remote ssh server to a channel connected to a tcpListener.
|
// remote ssh server to a channel connected to a tcpListener.
|
||||||
type forwardEntry struct {
|
type forwardEntry struct {
|
||||||
laddr net.TCPAddr
|
laddr net.Addr
|
||||||
c chan forward
|
c chan forward
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,15 +148,15 @@ type forwardEntry struct {
|
|||||||
// the original forward-request.
|
// the original forward-request.
|
||||||
type forward struct {
|
type forward struct {
|
||||||
newCh NewChannel // the ssh client channel underlying this forward
|
newCh NewChannel // the ssh client channel underlying this forward
|
||||||
raddr *net.TCPAddr // the raddr of the incoming connection
|
raddr net.Addr // the raddr of the incoming connection
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *forwardList) add(addr net.TCPAddr) chan forward {
|
func (l *forwardList) add(addr net.Addr) chan forward {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
f := forwardEntry{
|
f := forwardEntry{
|
||||||
addr,
|
laddr: addr,
|
||||||
make(chan forward, 1),
|
c: make(chan forward, 1),
|
||||||
}
|
}
|
||||||
l.entries = append(l.entries, f)
|
l.entries = append(l.entries, f)
|
||||||
return f.c
|
return f.c
|
||||||
@ -176,8 +184,15 @@ func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
|
|||||||
|
|
||||||
func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
||||||
for ch := range in {
|
for ch := range in {
|
||||||
|
var (
|
||||||
|
laddr net.Addr
|
||||||
|
raddr net.Addr
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch channelType := ch.ChannelType(); channelType {
|
||||||
|
case "forwarded-tcpip":
|
||||||
var payload forwardedTCPPayload
|
var payload forwardedTCPPayload
|
||||||
if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
|
if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||||
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -187,33 +202,51 @@ func (l *forwardList) handleChannels(in <-chan NewChannel) {
|
|||||||
// format. It is implied that this should be an IP
|
// format. It is implied that this should be an IP
|
||||||
// address, as it would be impossible to connect to it
|
// address, as it would be impossible to connect to it
|
||||||
// otherwise.
|
// otherwise.
|
||||||
laddr, err := parseTCPAddr(payload.Addr, payload.Port)
|
laddr, err = parseTCPAddr(payload.Addr, payload.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch.Reject(ConnectionFailed, err.Error())
|
ch.Reject(ConnectionFailed, err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
raddr, err = parseTCPAddr(payload.OriginAddr, payload.OriginPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch.Reject(ConnectionFailed, err.Error())
|
ch.Reject(ConnectionFailed, err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok := l.forward(*laddr, *raddr, ch); !ok {
|
case "forwarded-streamlocal@openssh.com":
|
||||||
|
var payload forwardedStreamLocalPayload
|
||||||
|
if err = Unmarshal(ch.ExtraData(), &payload); err != nil {
|
||||||
|
ch.Reject(ConnectionFailed, "could not parse forwarded-streamlocal@openssh.com payload: "+err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
laddr = &net.UnixAddr{
|
||||||
|
Name: payload.SocketPath,
|
||||||
|
Net: "unix",
|
||||||
|
}
|
||||||
|
raddr = &net.UnixAddr{
|
||||||
|
Name: "@",
|
||||||
|
Net: "unix",
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("ssh: unknown channel type %s", channelType))
|
||||||
|
}
|
||||||
|
if ok := l.forward(laddr, raddr, ch); !ok {
|
||||||
// Section 7.2, implementations MUST reject spurious incoming
|
// Section 7.2, implementations MUST reject spurious incoming
|
||||||
// connections.
|
// connections.
|
||||||
ch.Reject(Prohibited, "no forward for address")
|
ch.Reject(Prohibited, "no forward for address")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove removes the forward entry, and the channel feeding its
|
// remove removes the forward entry, and the channel feeding its
|
||||||
// listener.
|
// listener.
|
||||||
func (l *forwardList) remove(addr net.TCPAddr) {
|
func (l *forwardList) remove(addr net.Addr) {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
for i, f := range l.entries {
|
for i, f := range l.entries {
|
||||||
if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
|
if addr.Network() == f.laddr.Network() && addr.String() == f.laddr.String() {
|
||||||
l.entries = append(l.entries[:i], l.entries[i+1:]...)
|
l.entries = append(l.entries[:i], l.entries[i+1:]...)
|
||||||
close(f.c)
|
close(f.c)
|
||||||
return
|
return
|
||||||
@ -231,12 +264,12 @@ func (l *forwardList) closeAll() {
|
|||||||
l.entries = nil
|
l.entries = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
|
func (l *forwardList) forward(laddr, raddr net.Addr, ch NewChannel) bool {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
for _, f := range l.entries {
|
for _, f := range l.entries {
|
||||||
if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
|
if laddr.Network() == f.laddr.Network() && laddr.String() == f.laddr.String() {
|
||||||
f.c <- forward{ch, &raddr}
|
f.c <- forward{newCh: ch, raddr: raddr}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,7 +295,7 @@ func (l *tcpListener) Accept() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
go DiscardRequests(incoming)
|
go DiscardRequests(incoming)
|
||||||
|
|
||||||
return &tcpChanConn{
|
return &chanConn{
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: l.laddr,
|
laddr: l.laddr,
|
||||||
raddr: s.raddr,
|
raddr: s.raddr,
|
||||||
@ -277,7 +310,7 @@ func (l *tcpListener) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this also closes the listener.
|
// this also closes the listener.
|
||||||
l.conn.forwards.remove(*l.laddr)
|
l.conn.forwards.remove(l.laddr)
|
||||||
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
|
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
|
||||||
if err == nil && !ok {
|
if err == nil && !ok {
|
||||||
err = errors.New("ssh: cancel-tcpip-forward failed")
|
err = errors.New("ssh: cancel-tcpip-forward failed")
|
||||||
@ -293,6 +326,9 @@ func (l *tcpListener) Addr() net.Addr {
|
|||||||
// Dial initiates a connection to the addr from the remote host.
|
// Dial initiates a connection to the addr from the remote host.
|
||||||
// The resulting connection has a zero LocalAddr() and RemoteAddr().
|
// The resulting connection has a zero LocalAddr() and RemoteAddr().
|
||||||
func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
||||||
|
var ch Channel
|
||||||
|
switch n {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
// Parse the address into host and numeric port.
|
// Parse the address into host and numeric port.
|
||||||
host, portString, err := net.SplitHostPort(addr)
|
host, portString, err := net.SplitHostPort(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -302,20 +338,40 @@ func (c *Client) Dial(n, addr string) (net.Conn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
ch, err = c.dial(net.IPv4zero.String(), 0, host, int(port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
// Use a zero address for local and remote address.
|
// Use a zero address for local and remote address.
|
||||||
zeroAddr := &net.TCPAddr{
|
zeroAddr := &net.TCPAddr{
|
||||||
IP: net.IPv4zero,
|
IP: net.IPv4zero,
|
||||||
Port: 0,
|
Port: 0,
|
||||||
}
|
}
|
||||||
ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
|
return &chanConn{
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &tcpChanConn{
|
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: zeroAddr,
|
laddr: zeroAddr,
|
||||||
raddr: zeroAddr,
|
raddr: zeroAddr,
|
||||||
}, nil
|
}, nil
|
||||||
|
case "unix":
|
||||||
|
var err error
|
||||||
|
ch, err = c.dialStreamLocal(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &chanConn{
|
||||||
|
Channel: ch,
|
||||||
|
laddr: &net.UnixAddr{
|
||||||
|
Name: "@",
|
||||||
|
Net: "unix",
|
||||||
|
},
|
||||||
|
raddr: &net.UnixAddr{
|
||||||
|
Name: addr,
|
||||||
|
Net: "unix",
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("ssh: unsupported protocol: %s", n)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DialTCP connects to the remote address raddr on the network net,
|
// DialTCP connects to the remote address raddr on the network net,
|
||||||
@ -332,7 +388,7 @@ func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &tcpChanConn{
|
return &chanConn{
|
||||||
Channel: ch,
|
Channel: ch,
|
||||||
laddr: laddr,
|
laddr: laddr,
|
||||||
raddr: raddr,
|
raddr: raddr,
|
||||||
@ -366,26 +422,26 @@ type tcpChan struct {
|
|||||||
Channel // the backing channel
|
Channel // the backing channel
|
||||||
}
|
}
|
||||||
|
|
||||||
// tcpChanConn fulfills the net.Conn interface without
|
// chanConn fulfills the net.Conn interface without
|
||||||
// the tcpChan having to hold laddr or raddr directly.
|
// the tcpChan having to hold laddr or raddr directly.
|
||||||
type tcpChanConn struct {
|
type chanConn struct {
|
||||||
Channel
|
Channel
|
||||||
laddr, raddr net.Addr
|
laddr, raddr net.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocalAddr returns the local network address.
|
// LocalAddr returns the local network address.
|
||||||
func (t *tcpChanConn) LocalAddr() net.Addr {
|
func (t *chanConn) LocalAddr() net.Addr {
|
||||||
return t.laddr
|
return t.laddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteAddr returns the remote network address.
|
// RemoteAddr returns the remote network address.
|
||||||
func (t *tcpChanConn) RemoteAddr() net.Addr {
|
func (t *chanConn) RemoteAddr() net.Addr {
|
||||||
return t.raddr
|
return t.raddr
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDeadline sets the read and write deadlines associated
|
// SetDeadline sets the read and write deadlines associated
|
||||||
// with the connection.
|
// with the connection.
|
||||||
func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
|
func (t *chanConn) SetDeadline(deadline time.Time) error {
|
||||||
if err := t.SetReadDeadline(deadline); err != nil {
|
if err := t.SetReadDeadline(deadline); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -396,12 +452,14 @@ func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
|
|||||||
// A zero value for t means Read will not time out.
|
// A zero value for t means Read will not time out.
|
||||||
// After the deadline, the error from Read will implement net.Error
|
// After the deadline, the error from Read will implement net.Error
|
||||||
// with Timeout() == true.
|
// with Timeout() == true.
|
||||||
func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
|
func (t *chanConn) SetReadDeadline(deadline time.Time) error {
|
||||||
|
// for compatibility with previous version,
|
||||||
|
// the error message contains "tcpChan"
|
||||||
return errors.New("ssh: tcpChan: deadline not supported")
|
return errors.New("ssh: tcpChan: deadline not supported")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetWriteDeadline exists to satisfy the net.Conn interface
|
// SetWriteDeadline exists to satisfy the net.Conn interface
|
||||||
// but is not implemented by this type. It always returns an error.
|
// but is not implemented by this type. It always returns an error.
|
||||||
func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
|
func (t *chanConn) SetWriteDeadline(deadline time.Time) error {
|
||||||
return errors.New("ssh: tcpChan: deadline not supported")
|
return errors.New("ssh: tcpChan: deadline not supported")
|
||||||
}
|
}
|
||||||
|
16
vendor/vendor.json
vendored
16
vendor/vendor.json
vendored
@ -3,12 +3,12 @@
|
|||||||
"ignore": "test",
|
"ignore": "test",
|
||||||
"package": [
|
"package": [
|
||||||
{
|
{
|
||||||
"checksumSHA1": "KzIglkvAb68+jcmwajNkQLwa1R0=",
|
"checksumSHA1": "L3PugNJJOEpRmRbD+27LgTZC2E4=",
|
||||||
"path": "github.com/appleboy/easyssh-proxy",
|
"path": "github.com/appleboy/easyssh-proxy",
|
||||||
"revision": "b5f58761a17ac54f2b0008fb8dcc883c73bf289d",
|
"revision": "a13ed86767b8e8a24d8147a4909a702e7cf6b465",
|
||||||
"revisionTime": "2017-03-14T07:47:33Z",
|
"revisionTime": "2017-04-14T13:46:38Z",
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"versionExact": "1.1.1"
|
"versionExact": "1.1.2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "dvabztWVQX8f6oMLRyv4dLH+TGY=",
|
"checksumSHA1": "dvabztWVQX8f6oMLRyv4dLH+TGY=",
|
||||||
@ -65,10 +65,10 @@
|
|||||||
"revisionTime": "2017-02-08T20:51:15Z"
|
"revisionTime": "2017-02-08T20:51:15Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "fsrFs762jlaILyqqQImS1GfvIvw=",
|
"checksumSHA1": "8sVsMTphul+B0sI0qAv4TE1ZxUk=",
|
||||||
"path": "golang.org/x/crypto/ssh",
|
"path": "golang.org/x/crypto/ssh",
|
||||||
"revision": "40541ccb1c6e64c947ed6f606b8a6cb4b67d7436",
|
"revision": "cbc3d0884eac986df6e78a039b8792e869bff863",
|
||||||
"revisionTime": "2017-02-12T21:20:41Z"
|
"revisionTime": "2017-04-09T18:29:52Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "SJ3Ma3Ozavxpbh1usZWBCnzMKIc=",
|
"checksumSHA1": "SJ3Ma3Ozavxpbh1usZWBCnzMKIc=",
|
||||||
|
Loading…
Reference in New Issue
Block a user