add support for UpstreamHostKeyCallback
This commit is contained in:
parent
f5e2f9fc68
commit
48e477cb34
2 changed files with 53 additions and 20 deletions
|
|
@ -39,6 +39,13 @@ type SSHPiperConfig struct {
|
|||
//
|
||||
// More info: https://github.com/tg123/sshpiper#publickey-sign-again
|
||||
MapPublicKey func(conn ConnMetadata, key PublicKey) (Signer, error)
|
||||
|
||||
// HostKeyCallback 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
|
||||
}
|
||||
|
||||
type upstream struct{ *connection }
|
||||
|
|
@ -122,7 +129,11 @@ func (s *SSHPiperConfig) AddHostKey(key Signer) {
|
|||
func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn, err error) {
|
||||
|
||||
if piper.FindUpstream == nil {
|
||||
panic("FindUpstream func not found")
|
||||
return nil, errors.New("sshpiper: must specify FindUpstream")
|
||||
}
|
||||
|
||||
if piper.UpstreamHostKeyCallback == nil {
|
||||
return nil, errors.New("sshpiper: must specify UpstreamHostKeyCallback")
|
||||
}
|
||||
|
||||
d, err := newDownstream(conn, &ServerConfig{
|
||||
|
|
@ -191,7 +202,9 @@ func NewSSHPiperConn(conn net.Conn, piper *SSHPiperConfig) (pipe *SSHPiperConn,
|
|||
mappedUser = d.user
|
||||
}
|
||||
|
||||
u, err := newUpstream(upconn, addr, &ClientConfig{})
|
||||
u, err := newUpstream(upconn, addr, &ClientConfig{
|
||||
HostKeyCallback: piper.UpstreamHostKeyCallback,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -596,15 +609,19 @@ func (c *connection) clientHandshakeNoAuth(dialAddress string, config *ClientCon
|
|||
c.transport = newClientTransport(
|
||||
newTransport(c.sshConn.conn, config.Rand, true /* is client */),
|
||||
c.clientVersion, c.serverVersion, config, dialAddress, c.sshConn.RemoteAddr())
|
||||
if err := c.transport.requestKeyChange(); err != nil {
|
||||
|
||||
if err := c.transport.waitSession(); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
if packet, err := c.transport.readPacket(); err != nil {
|
||||
return err
|
||||
} else if packet[0] != msgNewKeys {
|
||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
||||
}
|
||||
c.sessionID = c.transport.getSessionID()
|
||||
|
||||
// if packet, err := c.transport.readPacket(); err != nil {
|
||||
// return err
|
||||
// } else if packet[0] != msgNewKeys {
|
||||
// return unexpectedMessageError(msgNewKeys, packet[0])
|
||||
// }
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -623,15 +640,17 @@ func (s *connection) serverHandshakeNoAuth(config *ServerConfig) (*Permissions,
|
|||
tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
|
||||
s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
|
||||
|
||||
if err := s.transport.requestKeyChange(); err != nil {
|
||||
if err := s.transport.waitSession(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if packet, err := s.transport.readPacket(); err != nil {
|
||||
return nil, err
|
||||
} else if packet[0] != msgNewKeys {
|
||||
return nil, unexpectedMessageError(msgNewKeys, packet[0])
|
||||
}
|
||||
s.sessionID = s.transport.getSessionID()
|
||||
|
||||
//if packet, err := s.transport.readPacket(); err != nil {
|
||||
// return nil, err
|
||||
//} else if packet[0] != msgNewKeys {
|
||||
// return nil, unexpectedMessageError(msgNewKeys, packet[0])
|
||||
//}
|
||||
|
||||
var packet []byte
|
||||
if packet, err = s.transport.readPacket(); err != nil {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ func ExampleNewSSHPiperConn() {
|
|||
// change upstream username to root
|
||||
return c, "root", nil
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
// add private key
|
||||
|
|
@ -83,6 +84,7 @@ func dialPiper(piper *SSHPiperConfig) (net.Conn, error) {
|
|||
p, err := NewSSHPiperConn(s, piper)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +120,7 @@ func TestFindUpstreamCallback(t *testing.T) {
|
|||
|
||||
return s, "", err
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -125,8 +128,9 @@ func TestFindUpstreamCallback(t *testing.T) {
|
|||
}
|
||||
|
||||
NewClientConn(c, "", &ClientConfig{
|
||||
User: username,
|
||||
Auth: []AuthMethod{Password("password")},
|
||||
User: username,
|
||||
Auth: []AuthMethod{Password("password")},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if !called {
|
||||
|
|
@ -159,6 +163,7 @@ func TestFindUpstreamWithUserCallback(t *testing.T) {
|
|||
|
||||
return s, mappedname, err
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -166,8 +171,9 @@ func TestFindUpstreamWithUserCallback(t *testing.T) {
|
|||
}
|
||||
|
||||
NewClientConn(c, "", &ClientConfig{
|
||||
User: username,
|
||||
Auth: []AuthMethod{Password("password")},
|
||||
User: username,
|
||||
Auth: []AuthMethod{Password("password")},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if !called {
|
||||
|
|
@ -178,7 +184,7 @@ func TestFindUpstreamWithUserCallback(t *testing.T) {
|
|||
func TestMapPublicKey(t *testing.T) {
|
||||
|
||||
certChecker := CertChecker{
|
||||
IsAuthority: func(k PublicKey) bool {
|
||||
IsUserAuthority: func(k PublicKey) bool {
|
||||
return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
|
||||
},
|
||||
UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
||||
|
|
@ -204,6 +210,7 @@ func TestMapPublicKey(t *testing.T) {
|
|||
MapPublicKey: func(conn ConnMetadata, key PublicKey) (Signer, error) {
|
||||
return testSigners["rsa"], nil
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -215,6 +222,7 @@ func TestMapPublicKey(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
PublicKeys(testSigners["rsa"]),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -245,6 +253,7 @@ func TestAdditionalChallenge(t *testing.T) {
|
|||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, "", err
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -262,6 +271,7 @@ func TestAdditionalChallenge(t *testing.T) {
|
|||
Auth: []AuthMethod{
|
||||
KeyboardInteractive(answers.Challenge),
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -317,6 +327,7 @@ func TestPipeData(t *testing.T) {
|
|||
s, err := dialUpstream(simpleEchoHandler, &ServerConfig{NoClientAuth: true}, t)
|
||||
return s, "", err
|
||||
},
|
||||
UpstreamHostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -324,7 +335,10 @@ func TestPipeData(t *testing.T) {
|
|||
}
|
||||
|
||||
// {{{ copy from session_test.go TestClientWriteEOF(t *testing.T)
|
||||
sshc, chans, reqs, err := NewClientConn(c, "", &ClientConfig{User: "testuser"})
|
||||
sshc, chans, reqs, err := NewClientConn(c, "", &ClientConfig{
|
||||
User: "testuser",
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("error create client %v", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue