diff --git a/ssh/sshpiper.go b/ssh/sshpiper.go index 4011de7a..6a5bbbcf 100644 --- a/ssh/sshpiper.go +++ b/ssh/sshpiper.go @@ -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 { diff --git a/ssh/sshpiper_test.go b/ssh/sshpiper_test.go index 8c07c851..cc47f737 100644 --- a/ssh/sshpiper_test.go +++ b/ssh/sshpiper_test.go @@ -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) }