add support for UpstreamHostKeyCallback

This commit is contained in:
Boshi Lian 2017-06-21 00:32:49 +08:00
parent f5e2f9fc68
commit 48e477cb34
2 changed files with 53 additions and 20 deletions

View file

@ -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 {

View file

@ -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)
}