aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing/transport')
-rw-r--r--plumbing/transport/common.go2
-rw-r--r--plumbing/transport/git/common.go4
-rw-r--r--plumbing/transport/server/server.go4
-rw-r--r--plumbing/transport/ssh/auth_method.go46
-rw-r--r--plumbing/transport/ssh/common.go24
5 files changed, 53 insertions, 27 deletions
diff --git a/plumbing/transport/common.go b/plumbing/transport/common.go
index a9ee2ca..a2a78f0 100644
--- a/plumbing/transport/common.go
+++ b/plumbing/transport/common.go
@@ -112,7 +112,7 @@ type Endpoint struct {
Port int
// Path is the repository path.
Path string
- // InsecureSkipTLS skips ssl verify if protocal is https
+ // InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CaBundle specify additional ca bundle with system cert pool
CaBundle []byte
diff --git a/plumbing/transport/git/common.go b/plumbing/transport/git/common.go
index 306aae2..c18d600 100644
--- a/plumbing/transport/git/common.go
+++ b/plumbing/transport/git/common.go
@@ -77,14 +77,14 @@ func (c *command) StderrPipe() (io.Reader, error) {
return nil, nil
}
-// StdinPipe return the underlying connection as WriteCloser, wrapped to prevent
+// StdinPipe returns the underlying connection as WriteCloser, wrapped to prevent
// call to the Close function from the connection, a command execution in git
// protocol can't be closed or killed
func (c *command) StdinPipe() (io.WriteCloser, error) {
return ioutil.WriteNopCloser(c.conn), nil
}
-// StdoutPipe return the underlying connection as Reader
+// StdoutPipe returns the underlying connection as Reader
func (c *command) StdoutPipe() (io.Reader, error) {
return c.conn, nil
}
diff --git a/plumbing/transport/server/server.go b/plumbing/transport/server/server.go
index 8ab70fe..11fa0c8 100644
--- a/plumbing/transport/server/server.go
+++ b/plumbing/transport/server/server.go
@@ -189,7 +189,7 @@ func (s *upSession) objectsToUpload(req *packp.UploadPackRequest) ([]plumbing.Ha
}
func (*upSession) setSupportedCapabilities(c *capability.List) error {
- if err := c.Set(capability.Agent, capability.DefaultAgent); err != nil {
+ if err := c.Set(capability.Agent, capability.DefaultAgent()); err != nil {
return err
}
@@ -355,7 +355,7 @@ func (s *rpSession) reportStatus() *packp.ReportStatus {
}
func (*rpSession) setSupportedCapabilities(c *capability.List) error {
- if err := c.Set(capability.Agent, capability.DefaultAgent); err != nil {
+ if err := c.Set(capability.Agent, capability.DefaultAgent()); err != nil {
return err
}
diff --git a/plumbing/transport/ssh/auth_method.go b/plumbing/transport/ssh/auth_method.go
index 3514669..9d3bcd3 100644
--- a/plumbing/transport/ssh/auth_method.go
+++ b/plumbing/transport/ssh/auth_method.go
@@ -10,10 +10,9 @@ import (
"github.com/go-git/go-git/v5/plumbing/transport"
- "github.com/mitchellh/go-homedir"
+ "github.com/skeema/knownhosts"
sshagent "github.com/xanzy/ssh-agent"
"golang.org/x/crypto/ssh"
- "golang.org/x/crypto/ssh/knownhosts"
)
const DefaultUsername = "git"
@@ -44,7 +43,6 @@ const (
type KeyboardInteractive struct {
User string
Challenge ssh.KeyboardInteractiveChallenge
- HostKeyCallbackHelper
}
func (a *KeyboardInteractive) Name() string {
@@ -56,19 +54,18 @@ func (a *KeyboardInteractive) String() string {
}
func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) {
- return a.SetHostKeyCallback(&ssh.ClientConfig{
+ return &ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{
a.Challenge,
},
- })
+ }, nil
}
// Password implements AuthMethod by using the given password.
type Password struct {
User string
Password string
- HostKeyCallbackHelper
}
func (a *Password) Name() string {
@@ -80,10 +77,10 @@ func (a *Password) String() string {
}
func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
- return a.SetHostKeyCallback(&ssh.ClientConfig{
+ return &ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.Password(a.Password)},
- })
+ }, nil
}
// PasswordCallback implements AuthMethod by using a callback
@@ -91,7 +88,6 @@ func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
type PasswordCallback struct {
User string
Callback func() (pass string, err error)
- HostKeyCallbackHelper
}
func (a *PasswordCallback) Name() string {
@@ -103,17 +99,16 @@ func (a *PasswordCallback) String() string {
}
func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) {
- return a.SetHostKeyCallback(&ssh.ClientConfig{
+ return &ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)},
- })
+ }, nil
}
// PublicKeys implements AuthMethod by using the given key pairs.
type PublicKeys struct {
User string
Signer ssh.Signer
- HostKeyCallbackHelper
}
// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An
@@ -152,10 +147,10 @@ func (a *PublicKeys) String() string {
}
func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) {
- return a.SetHostKeyCallback(&ssh.ClientConfig{
+ return &ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)},
- })
+ }, nil
}
func username() (string, error) {
@@ -178,7 +173,6 @@ func username() (string, error) {
type PublicKeysCallback struct {
User string
Callback func() (signers []ssh.Signer, err error)
- HostKeyCallbackHelper
}
// NewSSHAgentAuth returns a PublicKeysCallback based on a SSH agent, it opens
@@ -213,10 +207,10 @@ func (a *PublicKeysCallback) String() string {
}
func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
- return a.SetHostKeyCallback(&ssh.ClientConfig{
+ return &ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
- })
+ }, nil
}
// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a
@@ -224,12 +218,19 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
//
// If list of files is empty, then it will be read from the SSH_KNOWN_HOSTS
// environment variable, example:
-// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file
+//
+// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file
//
// If SSH_KNOWN_HOSTS is not set the following file locations will be used:
-// ~/.ssh/known_hosts
-// /etc/ssh/ssh_known_hosts
+//
+// ~/.ssh/known_hosts
+// /etc/ssh/ssh_known_hosts
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
+ kh, err := newKnownHosts(files...)
+ return ssh.HostKeyCallback(kh), err
+}
+
+func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
var err error
if len(files) == 0 {
@@ -251,7 +252,7 @@ func getDefaultKnownHostsFiles() ([]string, error) {
return files, nil
}
- homeDirPath, err := homedir.Dir()
+ homeDirPath, err := os.UserHomeDir()
if err != nil {
return nil, err
}
@@ -285,6 +286,9 @@ func filterKnownHostsFiles(files ...string) ([]string, error) {
// HostKeyCallbackHelper is a helper that provides common functionality to
// configure HostKeyCallback into a ssh.ClientConfig.
+// Deprecated in favor of SetConfigHostKeyFields (see common.go) which provides
+// a mechanism for also setting ClientConfig.HostKeyAlgorithms for a specific
+// host.
type HostKeyCallbackHelper struct {
// HostKeyCallback is the function type used for verifying server keys.
// If nil default callback will be create using NewKnownHostsCallback
diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go
index 46e7913..4b9ac07 100644
--- a/plumbing/transport/ssh/common.go
+++ b/plumbing/transport/ssh/common.go
@@ -121,10 +121,15 @@ func (c *command) connect() error {
if err != nil {
return err
}
+ hostWithPort := c.getHostWithPort()
+ config, err = SetConfigHostKeyFields(config, hostWithPort)
+ if err != nil {
+ return err
+ }
overrideConfig(c.config, config)
- c.client, err = dial("tcp", c.getHostWithPort(), config)
+ c.client, err = dial("tcp", hostWithPort, config)
if err != nil {
return err
}
@@ -162,6 +167,23 @@ func dial(network, addr string, config *ssh.ClientConfig) (*ssh.Client, error) {
return ssh.NewClient(c, chans, reqs), nil
}
+// SetConfigHostKeyFields sets cfg.HostKeyCallback and cfg.HostKeyAlgorithms
+// based on OpenSSH known_hosts. cfg is modified in-place. hostWithPort must be
+// supplied, since the algorithms will be set based on the known host keys for
+// that specific host. Otherwise, golang.org/x/crypto/ssh can return an error
+// upon connecting to a host whose *first* key is not known, even though other
+// keys (of different types) are known and match properly.
+// For background see https://github.com/go-git/go-git/issues/411 as well as
+// https://github.com/golang/go/issues/29286 for root cause.
+func SetConfigHostKeyFields(cfg *ssh.ClientConfig, hostWithPort string) (*ssh.ClientConfig, error) {
+ kh, err := newKnownHosts()
+ if err == nil {
+ cfg.HostKeyCallback = kh.HostKeyCallback()
+ cfg.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort)
+ }
+ return cfg, err
+}
+
func (c *command) getHostWithPort() string {
if addr, found := c.doGetHostWithPortFromSSHConfig(); found {
return addr