update sshpiper lib
This commit is contained in:
parent
a4a8847e99
commit
dd5a38bd8a
9 changed files with 244 additions and 119 deletions
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
|
@ -40,7 +40,7 @@
|
|||
"ssh",
|
||||
"ssh/testdata"
|
||||
]
|
||||
revision = "c832b236b4049eae471365acd18bc0b462a64a2b"
|
||||
revision = "a3947c90260b2290d5db1b779520e75f21ad8baf"
|
||||
source = "https://github.com/tg123/sshpiper.crypto"
|
||||
|
||||
[solve-meta]
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func getAndInstall(name string, get func(n string) registry.Plugin, install func
|
|||
return install(p)
|
||||
}
|
||||
|
||||
func installDrivers(piper *ssh.SSHPiperConfig, config *piperdConfig, logger *log.Logger) (auditor.Provider, error) {
|
||||
func installDrivers(piper *ssh.PiperConfig, config *piperdConfig, logger *log.Logger) (auditor.Provider, error) {
|
||||
|
||||
// install upstreamProvider driver
|
||||
if config.UpstreamDriver == "" {
|
||||
|
|
@ -115,7 +115,7 @@ func startPiper(config *piperdConfig, logger *log.Logger) error {
|
|||
|
||||
logger.Println("sshpiper is about to start")
|
||||
|
||||
piper := &ssh.SSHPiperConfig{}
|
||||
piper := &ssh.PiperConfig{}
|
||||
|
||||
bigbro, err := installDrivers(piper, config, logger)
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func connectServer(db *sql.DB, sid int64) (net.Conn, error) {
|
|||
|
||||
return net.Dial("tcp", addr)
|
||||
}
|
||||
func (w *mysqlWorkingDir) connectUpstream(db *sql.DB, uid int64, defuser string) (net.Conn, *ssh.SSHPiperAuthPipe, error) {
|
||||
func (w *mysqlWorkingDir) connectUpstream(db *sql.DB, uid int64, defuser string) (net.Conn, *ssh.AuthPipe, error) {
|
||||
|
||||
o := crud.NewUpstream(db)
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ func (w *mysqlWorkingDir) connectUpstream(db *sql.DB, uid int64, defuser string)
|
|||
}
|
||||
|
||||
logger.Printf("connecting upstream id [%v] addr [%v]@[%v] ", uid, user, c.RemoteAddr())
|
||||
return c, &ssh.SSHPiperAuthPipe{
|
||||
return c, &ssh.AuthPipe{
|
||||
User: user,
|
||||
|
||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) {
|
||||
|
|
@ -134,7 +134,7 @@ func findByUsername(db *sql.DB, username string) (int64, error) {
|
|||
}
|
||||
|
||||
//func (w *mysqlWorkingDir) FindUpstream(conn ssh.ConnMetadata, downkey ssh.PublicKey) (net.Conn, *ssh.SSHPiperAuthPipe, error) {
|
||||
func (w *mysqlWorkingDir) FindUpstream(conn ssh.ConnMetadata) (net.Conn, *ssh.SSHPiperAuthPipe, error) {
|
||||
func (w *mysqlWorkingDir) FindUpstream(conn ssh.ConnMetadata) (net.Conn, *ssh.AuthPipe, error) {
|
||||
|
||||
db, err := w.ConnectDB()
|
||||
defer db.Close()
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import (
|
|||
// the returned auth pipe is to map/convert downstream auth method to another auth for
|
||||
// connecting to upstream.
|
||||
// e.g. map downstream public key to another upstream private key
|
||||
type Handler func(conn ssh.ConnMetadata) (net.Conn, *ssh.SSHPiperAuthPipe, error)
|
||||
type Handler func(conn ssh.ConnMetadata) (net.Conn, *ssh.AuthPipe, error)
|
||||
|
||||
// Provider is a factory for Upstream Provider
|
||||
type Provider interface {
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ func parseUpstreamFile(data string) (string, string) {
|
|||
return line, user
|
||||
}
|
||||
|
||||
func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, *ssh.SSHPiperAuthPipe, error) {
|
||||
func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, *ssh.AuthPipe, error) {
|
||||
user := conn.User()
|
||||
|
||||
if !checkUsername(user) {
|
||||
|
|
@ -152,7 +152,7 @@ func findUpstreamFromUserfile(conn ssh.ConnMetadata) (net.Conn, *ssh.SSHPiperAut
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
return c, &ssh.SSHPiperAuthPipe{
|
||||
return c, &ssh.AuthPipe{
|
||||
User: mappedUser,
|
||||
|
||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (ssh.AuthPipeType, ssh.AuthMethod, error) {
|
||||
|
|
|
|||
4
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
4
vendor/golang.org/x/crypto/ssh/client_auth_test.go
generated
vendored
|
|
@ -614,8 +614,8 @@ func TestClientAuthErrorList(t *testing.T) {
|
|||
for i, e := range authErrs.Errors {
|
||||
switch i {
|
||||
case 0:
|
||||
if _, ok := e.(*NoAuthError); !ok {
|
||||
t.Fatalf("errors: got error type %T, want NoAuthError", e)
|
||||
if e != NoAuthError {
|
||||
t.Fatalf("errors: got error %v, want NoAuthError", e)
|
||||
}
|
||||
case 1:
|
||||
if e != publicKeyErr {
|
||||
|
|
|
|||
16
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
16
vendor/golang.org/x/crypto/ssh/server.go
generated
vendored
|
|
@ -297,7 +297,7 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
|
|||
// provided by the user failed to authenticate.
|
||||
type ServerAuthError struct {
|
||||
// Errors contains authentication errors returned by the authentication
|
||||
// callback methods.
|
||||
// callback methods. The first entry typically is NoAuthError.
|
||||
Errors []error
|
||||
}
|
||||
|
||||
|
|
@ -309,13 +309,11 @@ func (l ServerAuthError) Error() string {
|
|||
return "[" + strings.Join(errs, ", ") + "]"
|
||||
}
|
||||
|
||||
// NoAuthError is the unique error that is returned if no authentication method
|
||||
// has been passed yet
|
||||
type NoAuthError struct{}
|
||||
|
||||
func (e *NoAuthError) Error() string {
|
||||
return "no auth passed yet"
|
||||
}
|
||||
// NoAuthError is the unique error that is returned if no
|
||||
// authentication method has been passed yet. This happens as a normal
|
||||
// part of the authentication loop, since the client first tries
|
||||
// 'none' authentication to discover available methods.
|
||||
var NoAuthError = errors.New("ssh: no auth passed yet")
|
||||
|
||||
func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
|
||||
sessionID := s.transport.getSessionID()
|
||||
|
|
@ -371,7 +369,7 @@ userAuthLoop:
|
|||
}
|
||||
|
||||
perms = nil
|
||||
authErr := error(&NoAuthError{})
|
||||
authErr := NoAuthError
|
||||
|
||||
switch userAuthReq.Method {
|
||||
case "none":
|
||||
|
|
|
|||
102
vendor/golang.org/x/crypto/ssh/sshpiper.go
generated
vendored
102
vendor/golang.org/x/crypto/ssh/sshpiper.go
generated
vendored
|
|
@ -11,54 +11,52 @@ import (
|
|||
"net"
|
||||
)
|
||||
|
||||
// AuthPipeType declares how sshpiper handle piped auth message
|
||||
type AuthPipeType int
|
||||
|
||||
const (
|
||||
// Do nothing but pass auth message to upstream
|
||||
// AuthPipeTypePassThrough does nothing but pass auth message to upstream
|
||||
AuthPipeTypePassThrough AuthPipeType = iota
|
||||
|
||||
// Convert auth message to AuthMetod return by callback and pass it to upstream
|
||||
// AuthPipeTypeMap converts auth message to AuthMetod return by callback and pass it to upstream
|
||||
AuthPipeTypeMap
|
||||
|
||||
// Discard auth message, do not pass it to uptream
|
||||
// AuthPipeTypeDiscard discards auth message, do not pass it to uptream
|
||||
AuthPipeTypeDiscard
|
||||
|
||||
// Convert auth message to NoneAuth and pass it to upstream
|
||||
// AuthPipeTypeNone converts auth message to NoneAuth and pass it to upstream
|
||||
AuthPipeTypeNone
|
||||
)
|
||||
|
||||
// SSHPiperAuthPipe:
|
||||
// Convert Auth
|
||||
// Any Auth to Password
|
||||
// AuthPipe contains the callbacks of auth msg mapping from downstream to upstream
|
||||
//
|
||||
// Any Auth to Public Key
|
||||
// when AuthPipeType == AuthPipeTypeMap && AuthMethod == PublicKey
|
||||
// SSHPiper will sign the auth packet message using the returned Signer.
|
||||
// This func might be called twice, one is for query message, the other
|
||||
// is real auth packet message.
|
||||
// If any error occurs during this period, a NoneAuth packet will be sent to
|
||||
// upstream ssh server instead.
|
||||
//
|
||||
// More info: https://github.com/tg123/sshpiper#publickey-sign-again
|
||||
type SSHPiperAuthPipe struct {
|
||||
type AuthPipe struct {
|
||||
// Username to upstream
|
||||
User string
|
||||
|
||||
// PublicKeyCallback, if non-nil, is called when downstream requests a password auth.
|
||||
PasswordCallback func(conn ConnMetadata, password []byte) (AuthPipeType, AuthMethod, error)
|
||||
|
||||
// PublicKeyCallback, if non-nil, is called when downstream requests a publickey auth.
|
||||
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error)
|
||||
|
||||
// HostKeyCallback is called during the cryptographic
|
||||
// UpstreamHostKeyCallback is called during the cryptographic
|
||||
// handshake to validate the uptream server's host key. The piper
|
||||
// configuration must supply this callback for the connection
|
||||
// to succeed. The functions InsecureIgnoreHostKey or
|
||||
// FixedHostKey can be used for simplistic host key checks.
|
||||
// UpstreamHostKeyCallback HostKeyCallback
|
||||
UpstreamHostKeyCallback HostKeyCallback
|
||||
}
|
||||
|
||||
// SSHPiperConfig holds SSHPiper specific configuration data.
|
||||
type SSHPiperConfig struct {
|
||||
// PiperConfig holds SSHPiper specific configuration data.
|
||||
type PiperConfig struct {
|
||||
Config
|
||||
|
||||
hostKeys []Signer
|
||||
|
|
@ -74,7 +72,7 @@ type SSHPiperConfig struct {
|
|||
// and upstream username should be returned.
|
||||
// SSHPiper will use the username from downstream if empty username is returned.
|
||||
// If any error occurs, the piped connection will be closed.
|
||||
FindUpstream func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error)
|
||||
FindUpstream func(conn ConnMetadata) (net.Conn, *AuthPipe, error)
|
||||
|
||||
// ServerVersion is the version identification string to announce in
|
||||
// the public handshake.
|
||||
|
|
@ -97,11 +95,11 @@ type pipedConn struct {
|
|||
hookDownstreamMsg func(msg []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// SSHPiperConn is a piped SSH connection, linking upstream ssh server and
|
||||
// PiperConn is a piped SSH connection, linking upstream ssh server and
|
||||
// downstream ssh client together. After the piped connection was created,
|
||||
// The downstream ssh client is authenticated by upstream ssh server and
|
||||
// AdditionalChallenge from SSHPiper.
|
||||
type SSHPiperConn struct {
|
||||
type PiperConn struct {
|
||||
*pipedConn
|
||||
|
||||
HookUpstreamMsg func(conn ConnMetadata, msg []byte) ([]byte, error)
|
||||
|
|
@ -110,7 +108,7 @@ type SSHPiperConn struct {
|
|||
|
||||
// Wait blocks until the piped connection has shut down, and returns the
|
||||
// error causing the shutdown.
|
||||
func (p *SSHPiperConn) Wait() error {
|
||||
func (p *PiperConn) Wait() error {
|
||||
|
||||
p.pipedConn.hookUpstreamMsg = func(msg []byte) ([]byte, error) {
|
||||
if p.HookUpstreamMsg != nil {
|
||||
|
|
@ -133,22 +131,24 @@ func (p *SSHPiperConn) Wait() error {
|
|||
}
|
||||
|
||||
// Close the piped connection create by SSHPiper
|
||||
func (p *SSHPiperConn) Close() {
|
||||
func (p *PiperConn) Close() {
|
||||
p.pipedConn.Close()
|
||||
}
|
||||
|
||||
func (p *SSHPiperConn) UpstreamConnMeta() ConnMetadata {
|
||||
// UpstreamConnMeta returns the ConnMetadata of the piper and upstream
|
||||
func (p *PiperConn) UpstreamConnMeta() ConnMetadata {
|
||||
return p.pipedConn.upstream
|
||||
}
|
||||
|
||||
func (p *SSHPiperConn) DownstreamConnMeta() ConnMetadata {
|
||||
// DownstreamConnMeta returns the ConnMetadata of the piper and downstream
|
||||
func (p *PiperConn) DownstreamConnMeta() ConnMetadata {
|
||||
return p.pipedConn.downstream
|
||||
}
|
||||
|
||||
// AddHostKey adds a private key as a SSHPiper host key. If an existing host
|
||||
// key exists with the same algorithm, it is overwritten. Each SSHPiper
|
||||
// config must have at least one host key.
|
||||
func (s *SSHPiperConfig) AddHostKey(key Signer) {
|
||||
func (s *PiperConfig) AddHostKey(key Signer) {
|
||||
for i, k := range s.hostKeys {
|
||||
if k.PublicKey().Type() == key.PublicKey().Type() {
|
||||
s.hostKeys[i] = key
|
||||
|
|
@ -162,7 +162,7 @@ func (s *SSHPiperConfig) AddHostKey(key Signer) {
|
|||
// NewSSHPiperConn starts a piped ssh connection witch conn as its downstream transport.
|
||||
// It handshake with downstream ssh client and upstream ssh server provicde by FindUpstream.
|
||||
// If either handshake is unsuccessful, the whole piped connection will be closed.
|
||||
func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn, err error) {
|
||||
func NewSSHPiperConn(conn net.Conn, piper *PiperConfig) (pipe *PiperConn, err error) {
|
||||
|
||||
if piper.FindUpstream == nil {
|
||||
return nil, errors.New("sshpiper: must specify FindUpstream")
|
||||
|
|
@ -251,6 +251,7 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn,
|
|||
u.Close()
|
||||
}
|
||||
}()
|
||||
u.user = mappedUser
|
||||
|
||||
p := &pipedConn{
|
||||
upstream: u,
|
||||
|
|
@ -259,7 +260,7 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn,
|
|||
|
||||
p.processAuthMsg = func(msg *userAuthRequestMsg) (*userAuthRequestMsg, error) {
|
||||
|
||||
var authType AuthPipeType = AuthPipeTypePassThrough
|
||||
var authType = AuthPipeTypePassThrough
|
||||
var authMethod AuthMethod
|
||||
|
||||
switch msg.Method {
|
||||
|
|
@ -290,18 +291,16 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn,
|
|||
|
||||
// discard msg
|
||||
return nil, nil
|
||||
} else {
|
||||
}
|
||||
|
||||
ok, err := p.checkPublicKey(msg, downKey, sig)
|
||||
ok, err := p.checkPublicKey(msg, downKey, sig)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return noneAuthMsg(mappedUser), nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return noneAuthMsg(mappedUser), nil
|
||||
}
|
||||
|
||||
case "password":
|
||||
|
|
@ -406,7 +405,7 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return &SSHPiperConn{pipedConn: p}, nil
|
||||
return &PiperConn{pipedConn: p}, nil
|
||||
}
|
||||
|
||||
func (pipe *pipedConn) ack(key PublicKey) error {
|
||||
|
|
@ -415,11 +414,7 @@ func (pipe *pipedConn) ack(key PublicKey) error {
|
|||
PubKey: key.Marshal(),
|
||||
}
|
||||
|
||||
if err := pipe.downstream.transport.writePacket(Marshal(&okMsg)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return pipe.downstream.transport.writePacket(Marshal(&okMsg))
|
||||
}
|
||||
|
||||
// not used after method to method map enable
|
||||
|
|
@ -638,7 +633,6 @@ func (pipe *pipedConn) pipeAuth(initUserAuthMsg *userAuthRequestMsg) error {
|
|||
if succ {
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var packet []byte
|
||||
|
|
@ -688,11 +682,7 @@ func (u *upstream) sendAuthReq() error {
|
|||
return err
|
||||
}
|
||||
var serviceAccept serviceAcceptMsg
|
||||
if err := Unmarshal(packet, &serviceAccept); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return Unmarshal(packet, &serviceAccept)
|
||||
}
|
||||
|
||||
func newDownstream(c net.Conn, config *ServerConfig) (*downstream, error) {
|
||||
|
|
@ -770,41 +760,39 @@ func (c *connection) clientHandshakeNoAuth(dialAddress string, config *ClientCon
|
|||
|
||||
if err := c.transport.waitSession(); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *connection) serverHandshakeNoAuth(config *ServerConfig) (*Permissions, error) {
|
||||
func (c *connection) serverHandshakeNoAuth(config *ServerConfig) (*Permissions, error) {
|
||||
if len(config.hostKeys) == 0 {
|
||||
return nil, errors.New("ssh: server has no host keys")
|
||||
}
|
||||
|
||||
var err error
|
||||
if config.ServerVersion != "" {
|
||||
s.serverVersion = []byte(config.ServerVersion)
|
||||
c.serverVersion = []byte(config.ServerVersion)
|
||||
} else {
|
||||
s.serverVersion = []byte("SSH-2.0-SSHPiper")
|
||||
c.serverVersion = []byte("SSH-2.0-SSHPiper")
|
||||
}
|
||||
s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
|
||||
c.clientVersion, err = exchangeVersions(c.sshConn.conn, c.serverVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
|
||||
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
|
||||
tr := newTransport(c.sshConn.conn, config.Rand, false /* not client */)
|
||||
c.transport = newServerTransport(tr, c.clientVersion, c.serverVersion, config)
|
||||
|
||||
if err := s.transport.waitSession(); err != nil {
|
||||
if err := c.transport.waitSession(); err != nil {
|
||||
return nil, err
|
||||
|
||||
}
|
||||
s.sessionID = s.transport.getSessionID()
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
|
||||
var packet []byte
|
||||
if packet, err = s.transport.readPacket(); err != nil {
|
||||
if packet, err = c.transport.readPacket(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -818,7 +806,7 @@ func (s *connection) serverHandshakeNoAuth(config *ServerConfig) (*Permissions,
|
|||
serviceAccept := serviceAcceptMsg{
|
||||
Service: serviceUserAuth,
|
||||
}
|
||||
if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
|
||||
if err := c.transport.writePacket(Marshal(&serviceAccept)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
|||
223
vendor/golang.org/x/crypto/ssh/sshpiper_test.go
generated
vendored
223
vendor/golang.org/x/crypto/ssh/sshpiper_test.go
generated
vendored
|
|
@ -20,16 +20,16 @@ func ExampleNewSSHPiperConn() {
|
|||
// upstream addr
|
||||
const serverAddr = "127.0.0.1:22"
|
||||
|
||||
piper := &SSHPiperConfig{
|
||||
piper := &PiperConfig{
|
||||
// return conn dial to serverAddr
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
c, err := net.Dial("tcp", serverAddr)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// change upstream username to root
|
||||
return c, &SSHPiperAuthPipe{
|
||||
return c, &AuthPipe{
|
||||
User: "root",
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, nil
|
||||
|
|
@ -71,7 +71,7 @@ func ExampleNewSSHPiperConn() {
|
|||
|
||||
// }}}
|
||||
|
||||
func dialPiper(piper *SSHPiperConfig) (net.Conn, error) {
|
||||
func dialPiper(piper *PiperConfig, afterConn func(*PiperConn), t *testing.T) (net.Conn, error) {
|
||||
c, s, err := netPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -86,10 +86,14 @@ func dialPiper(piper *SSHPiperConfig) (net.Conn, error) {
|
|||
p, err := NewSSHPiperConn(s, piper)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
t.Errorf("failed to create piper conn %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if afterConn != nil {
|
||||
afterConn(p)
|
||||
}
|
||||
|
||||
p.Wait()
|
||||
}()
|
||||
|
||||
|
|
@ -102,8 +106,8 @@ func TestPiperFindUpstreamCallback(t *testing.T) {
|
|||
|
||||
var called bool
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
if username != conn.User() {
|
||||
t.Errorf("different username")
|
||||
}
|
||||
|
|
@ -124,11 +128,11 @@ func TestPiperFindUpstreamCallback(t *testing.T) {
|
|||
},
|
||||
}, t)
|
||||
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -153,8 +157,8 @@ func TestPiperFindUpstreamWithUserCallback(t *testing.T) {
|
|||
|
||||
var called bool
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{
|
||||
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||
|
|
@ -168,12 +172,12 @@ func TestPiperFindUpstreamWithUserCallback(t *testing.T) {
|
|||
},
|
||||
}, t)
|
||||
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
User: mappedname,
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -208,12 +212,12 @@ func TestPiperMapPublicKey(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{
|
||||
PublicKeyCallback: certChecker.Authenticate,
|
||||
}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
|
||||
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) {
|
||||
return AuthPipeTypeMap, PublicKeys(testSigners["rsa"]), nil
|
||||
|
|
@ -222,7 +226,7 @@ func TestPiperMapPublicKey(t *testing.T) {
|
|||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -260,8 +264,8 @@ func TestPiperMapPublicKeyToPassword(t *testing.T) {
|
|||
|
||||
var called bool
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{
|
||||
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||
t.Errorf("PasswordCallback should not be called")
|
||||
|
|
@ -273,7 +277,7 @@ func TestPiperMapPublicKeyToPassword(t *testing.T) {
|
|||
return certChecker.Authenticate(conn, key)
|
||||
},
|
||||
}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
PasswordCallback: func(conn ConnMetadata, password []byte) (AuthPipeType, AuthMethod, error) {
|
||||
if string(password) != "mypassword" {
|
||||
t.Errorf("password not equal")
|
||||
|
|
@ -285,7 +289,7 @@ func TestPiperMapPublicKeyToPassword(t *testing.T) {
|
|||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -311,8 +315,8 @@ func TestPiperMapPublicKeyToPassword(t *testing.T) {
|
|||
func TestPiperPasswordToMapPublicKey(t *testing.T) {
|
||||
var called bool
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{
|
||||
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||
called = true
|
||||
|
|
@ -329,7 +333,7 @@ func TestPiperPasswordToMapPublicKey(t *testing.T) {
|
|||
return nil, nil
|
||||
},
|
||||
}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
|
||||
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) {
|
||||
return AuthPipeTypeMap, Password("mypassword"), nil
|
||||
|
|
@ -338,7 +342,7 @@ func TestPiperPasswordToMapPublicKey(t *testing.T) {
|
|||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -368,8 +372,8 @@ func TestPiperServerWithBanner(t *testing.T) {
|
|||
|
||||
var called bool
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
if username != conn.User() {
|
||||
t.Errorf("different username")
|
||||
}
|
||||
|
|
@ -387,12 +391,12 @@ func TestPiperServerWithBanner(t *testing.T) {
|
|||
},
|
||||
}, t)
|
||||
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
User: mappedname,
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -437,8 +441,8 @@ func TestPiperUsernameNotChangedWithinSession(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{
|
||||
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||
if conn.User() != mappedname {
|
||||
|
|
@ -459,10 +463,10 @@ func TestPiperUsernameNotChangedWithinSession(t *testing.T) {
|
|||
t.Errorf("bad mapped username")
|
||||
}
|
||||
|
||||
callcount += 1
|
||||
callcount++
|
||||
},
|
||||
}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
User: mappedname,
|
||||
|
||||
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (AuthPipeType, AuthMethod, error) {
|
||||
|
|
@ -472,7 +476,7 @@ func TestPiperUsernameNotChangedWithinSession(t *testing.T) {
|
|||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -498,7 +502,7 @@ func TestPiperUsernameNotChangedWithinSession(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPiperAdditionalChallenge(t *testing.T) {
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
AdditionalChallenge: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (bool, error) {
|
||||
ans, err := challenge("user",
|
||||
"instruction",
|
||||
|
|
@ -516,13 +520,13 @@ func TestPiperAdditionalChallenge(t *testing.T) {
|
|||
}
|
||||
return false, fmt.Errorf("keyboard-interactive failed")
|
||||
},
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
})
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
|
|
@ -588,17 +592,152 @@ func dialUpstream(handler serverType, upstream *ServerConfig, t *testing.T) (net
|
|||
return c, nil
|
||||
}
|
||||
|
||||
func TestPiperPipeData(t *testing.T) {
|
||||
func TestPiperConnMeta(t *testing.T) {
|
||||
|
||||
c, err := dialPiper(&SSHPiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *SSHPiperAuthPipe, error) {
|
||||
wait := make(chan int)
|
||||
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, &SSHPiperAuthPipe{
|
||||
return s, &AuthPipe{
|
||||
User: "up",
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
}, func(p *PiperConn) {
|
||||
|
||||
if p.DownstreamConnMeta().User() != "down" {
|
||||
t.Errorf("different downstream user")
|
||||
}
|
||||
|
||||
if p.UpstreamConnMeta().User() != "up" {
|
||||
t.Errorf("different upstream user")
|
||||
}
|
||||
|
||||
wait <- 0
|
||||
}, t)
|
||||
|
||||
_, _, _, err = NewClientConn(c, "", &ClientConfig{
|
||||
User: "down",
|
||||
Auth: []AuthMethod{new(noneAuth)},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("can connect to piper %v", err)
|
||||
}
|
||||
|
||||
<-wait
|
||||
}
|
||||
|
||||
func TestPiperConnMsgHook(t *testing.T) {
|
||||
|
||||
wait := make(chan int)
|
||||
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, &AuthPipe{
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
}, func(p *PiperConn) {
|
||||
|
||||
p.HookDownstreamMsg = func(conn ConnMetadata, msg []byte) ([]byte, error) {
|
||||
if msg[0] == msgChannelData {
|
||||
m := channelDataMsg{}
|
||||
Unmarshal(msg, &m)
|
||||
if string(m.Rest) != "123456" {
|
||||
t.Errorf("msg not equal")
|
||||
}
|
||||
|
||||
m.Length = 3
|
||||
m.Rest = []byte("654")
|
||||
|
||||
return Marshal(m), nil
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
p.HookUpstreamMsg = func(conn ConnMetadata, msg []byte) ([]byte, error) {
|
||||
if msg[0] == msgChannelData {
|
||||
m := channelDataMsg{}
|
||||
Unmarshal(msg, &m)
|
||||
if string(m.Rest) != "654" {
|
||||
t.Errorf("msg not equal")
|
||||
}
|
||||
|
||||
m.Length = 7
|
||||
m.Rest = []byte("abcdefg")
|
||||
|
||||
return Marshal(m), nil
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
wait <- 0
|
||||
}, t)
|
||||
|
||||
sshc, chans, reqs, err := NewClientConn(c, "", &ClientConfig{
|
||||
User: "test",
|
||||
Auth: []AuthMethod{new(noneAuth)},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("can connect to piper %v", err)
|
||||
}
|
||||
<-wait
|
||||
|
||||
conn := NewClient(sshc, chans, reqs)
|
||||
defer conn.Close()
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
stdin, err := session.StdinPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("StdinPipe failed: %v", err)
|
||||
}
|
||||
stdout, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("StdoutPipe failed: %v", err)
|
||||
}
|
||||
|
||||
data := []byte(`123456`)
|
||||
_, err = stdin.Write(data)
|
||||
if err != nil {
|
||||
t.Fatalf("Write failed: %v", err)
|
||||
}
|
||||
stdin.Close()
|
||||
|
||||
res, err := ioutil.ReadAll(stdout)
|
||||
if err != nil {
|
||||
t.Fatalf("Read failed: %v", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal([]byte(`abcdefg`), res) {
|
||||
t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestPiperPipeData(t *testing.T) {
|
||||
|
||||
c, err := dialPiper(&PiperConfig{
|
||||
FindUpstream: func(conn ConnMetadata) (net.Conn, *AuthPipe, error) {
|
||||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, &AuthPipe{
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}, err
|
||||
},
|
||||
}, nil, t)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("connect dial to piper: %v", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue