aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing/transport')
-rw-r--r--plumbing/transport/common.go7
-rw-r--r--plumbing/transport/common_test.go35
-rw-r--r--plumbing/transport/file/client.go19
-rw-r--r--plumbing/transport/http/common.go6
-rw-r--r--plumbing/transport/http/common_test.go6
-rw-r--r--plumbing/transport/http/upload_pack_test.go3
-rw-r--r--plumbing/transport/ssh/auth_method.go13
-rw-r--r--plumbing/transport/ssh/auth_method_test.go106
-rw-r--r--plumbing/transport/ssh/common.go17
-rw-r--r--plumbing/transport/test/receive_pack.go5
10 files changed, 188 insertions, 29 deletions
diff --git a/plumbing/transport/common.go b/plumbing/transport/common.go
index b05437f..fae1aa9 100644
--- a/plumbing/transport/common.go
+++ b/plumbing/transport/common.go
@@ -19,6 +19,7 @@ import (
"fmt"
"io"
"net/url"
+ "path/filepath"
"strconv"
"strings"
@@ -295,7 +296,11 @@ func parseFile(endpoint string) (*Endpoint, bool) {
return nil, false
}
- path := endpoint
+ path, err := filepath.Abs(endpoint)
+ if err != nil {
+ return nil, false
+ }
+
return &Endpoint{
Protocol: "file",
Path: path,
diff --git a/plumbing/transport/common_test.go b/plumbing/transport/common_test.go
index 3efc555..1501f73 100644
--- a/plumbing/transport/common_test.go
+++ b/plumbing/transport/common_test.go
@@ -3,6 +3,9 @@ package transport
import (
"fmt"
"net/url"
+ "os"
+ "path/filepath"
+ "runtime"
"testing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
@@ -120,6 +123,14 @@ func (s *SuiteCommon) TestNewEndpointSCPLikeWithPort(c *C) {
}
func (s *SuiteCommon) TestNewEndpointFileAbs(c *C) {
+ var err error
+ abs := "/foo.git"
+
+ if runtime.GOOS == "windows" {
+ abs, err = filepath.Abs(abs)
+ c.Assert(err, IsNil)
+ }
+
e, err := NewEndpoint("/foo.git")
c.Assert(err, IsNil)
c.Assert(e.Protocol, Equals, "file")
@@ -127,11 +138,14 @@ func (s *SuiteCommon) TestNewEndpointFileAbs(c *C) {
c.Assert(e.Password, Equals, "")
c.Assert(e.Host, Equals, "")
c.Assert(e.Port, Equals, 0)
- c.Assert(e.Path, Equals, "/foo.git")
- c.Assert(e.String(), Equals, "file:///foo.git")
+ c.Assert(e.Path, Equals, abs)
+ c.Assert(e.String(), Equals, "file://"+abs)
}
func (s *SuiteCommon) TestNewEndpointFileRel(c *C) {
+ abs, err := filepath.Abs("foo.git")
+ c.Assert(err, IsNil)
+
e, err := NewEndpoint("foo.git")
c.Assert(err, IsNil)
c.Assert(e.Protocol, Equals, "file")
@@ -139,11 +153,20 @@ func (s *SuiteCommon) TestNewEndpointFileRel(c *C) {
c.Assert(e.Password, Equals, "")
c.Assert(e.Host, Equals, "")
c.Assert(e.Port, Equals, 0)
- c.Assert(e.Path, Equals, "foo.git")
- c.Assert(e.String(), Equals, "file://foo.git")
+ c.Assert(e.Path, Equals, abs)
+ c.Assert(e.String(), Equals, "file://"+abs)
}
func (s *SuiteCommon) TestNewEndpointFileWindows(c *C) {
+ abs := "C:\\foo.git"
+
+ if runtime.GOOS != "windows" {
+ cwd, err := os.Getwd()
+ c.Assert(err, IsNil)
+
+ abs = filepath.Join(cwd, "C:\\foo.git")
+ }
+
e, err := NewEndpoint("C:\\foo.git")
c.Assert(err, IsNil)
c.Assert(e.Protocol, Equals, "file")
@@ -151,8 +174,8 @@ func (s *SuiteCommon) TestNewEndpointFileWindows(c *C) {
c.Assert(e.Password, Equals, "")
c.Assert(e.Host, Equals, "")
c.Assert(e.Port, Equals, 0)
- c.Assert(e.Path, Equals, "C:\\foo.git")
- c.Assert(e.String(), Equals, "file://C:\\foo.git")
+ c.Assert(e.Path, Equals, abs)
+ c.Assert(e.String(), Equals, "file://"+abs)
}
func (s *SuiteCommon) TestNewEndpointFileURL(c *C) {
diff --git a/plumbing/transport/file/client.go b/plumbing/transport/file/client.go
index 38714e2..d921d0a 100644
--- a/plumbing/transport/file/client.go
+++ b/plumbing/transport/file/client.go
@@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
+ "runtime"
"strings"
"github.com/go-git/go-git/v5/plumbing/transport"
@@ -95,7 +96,23 @@ func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.Auth
}
}
- return &command{cmd: execabs.Command(cmd, ep.Path)}, nil
+ return &command{cmd: execabs.Command(cmd, adjustPathForWindows(ep.Path))}, nil
+}
+
+func isDriveLetter(c byte) bool {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+}
+
+// On Windows, the path that results from a file: URL has a leading slash. This
+// has to be removed if there's a drive letter
+func adjustPathForWindows(p string) string {
+ if runtime.GOOS != "windows" {
+ return p
+ }
+ if len(p) >= 3 && p[0] == '/' && isDriveLetter(p[1]) && p[2] == ':' {
+ return p[1:]
+ }
+ return p
}
type command struct {
diff --git a/plumbing/transport/http/common.go b/plumbing/transport/http/common.go
index 1c4ceee..120008d 100644
--- a/plumbing/transport/http/common.go
+++ b/plumbing/transport/http/common.go
@@ -430,11 +430,11 @@ func NewErr(r *http.Response) error {
switch r.StatusCode {
case http.StatusUnauthorized:
- return transport.ErrAuthenticationRequired
+ return fmt.Errorf("%w: %s", transport.ErrAuthenticationRequired, reason)
case http.StatusForbidden:
- return transport.ErrAuthorizationFailed
+ return fmt.Errorf("%w: %s", transport.ErrAuthorizationFailed, reason)
case http.StatusNotFound:
- return transport.ErrRepositoryNotFound
+ return fmt.Errorf("%w: %s", transport.ErrRepositoryNotFound, reason)
}
return plumbing.NewUnexpectedError(&Err{r, reason})
diff --git a/plumbing/transport/http/common_test.go b/plumbing/transport/http/common_test.go
index c831ac3..f0eb68d 100644
--- a/plumbing/transport/http/common_test.go
+++ b/plumbing/transport/http/common_test.go
@@ -76,15 +76,15 @@ func (s *ClientSuite) TestNewErrOK(c *C) {
}
func (s *ClientSuite) TestNewErrUnauthorized(c *C) {
- s.testNewHTTPError(c, http.StatusUnauthorized, "authentication required")
+ s.testNewHTTPError(c, http.StatusUnauthorized, ".*authentication required.*")
}
func (s *ClientSuite) TestNewErrForbidden(c *C) {
- s.testNewHTTPError(c, http.StatusForbidden, "authorization failed")
+ s.testNewHTTPError(c, http.StatusForbidden, ".*authorization failed.*")
}
func (s *ClientSuite) TestNewErrNotFound(c *C) {
- s.testNewHTTPError(c, http.StatusNotFound, "repository not found")
+ s.testNewHTTPError(c, http.StatusNotFound, ".*repository not found.*")
}
func (s *ClientSuite) TestNewHTTPError40x(c *C) {
diff --git a/plumbing/transport/http/upload_pack_test.go b/plumbing/transport/http/upload_pack_test.go
index abb7adf..3a1610a 100644
--- a/plumbing/transport/http/upload_pack_test.go
+++ b/plumbing/transport/http/upload_pack_test.go
@@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
+ . "github.com/go-git/go-git/v5/internal/test"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/transport"
@@ -37,7 +38,7 @@ func (s *UploadPackSuite) TestAdvertisedReferencesNotExists(c *C) {
r, err := s.Client.NewUploadPackSession(s.NonExistentEndpoint, s.EmptyAuth)
c.Assert(err, IsNil)
info, err := r.AdvertisedReferences()
- c.Assert(err, Equals, transport.ErrRepositoryNotFound)
+ c.Assert(err, ErrorIs, transport.ErrRepositoryNotFound)
c.Assert(info, IsNil)
}
diff --git a/plumbing/transport/ssh/auth_method.go b/plumbing/transport/ssh/auth_method.go
index ac4e358..f9c598e 100644
--- a/plumbing/transport/ssh/auth_method.go
+++ b/plumbing/transport/ssh/auth_method.go
@@ -230,11 +230,11 @@ func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
// ~/.ssh/known_hosts
// /etc/ssh/ssh_known_hosts
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
- kh, err := newKnownHosts(files...)
- return ssh.HostKeyCallback(kh), err
+ db, err := newKnownHostsDb(files...)
+ return db.HostKeyCallback(), err
}
-func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
+func newKnownHostsDb(files ...string) (*knownhosts.HostKeyDB, error) {
var err error
if len(files) == 0 {
@@ -247,7 +247,7 @@ func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
return nil, err
}
- return knownhosts.New(files...)
+ return knownhosts.NewDB(files...)
}
func getDefaultKnownHostsFiles() ([]string, error) {
@@ -301,11 +301,12 @@ type HostKeyCallbackHelper struct {
// HostKeyCallback is empty a default callback is created using
// NewKnownHostsCallback.
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
- var err error
if m.HostKeyCallback == nil {
- if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil {
+ db, err := newKnownHostsDb()
+ if err != nil {
return cfg, err
}
+ m.HostKeyCallback = db.HostKeyCallback()
}
cfg.HostKeyCallback = m.HostKeyCallback
diff --git a/plumbing/transport/ssh/auth_method_test.go b/plumbing/transport/ssh/auth_method_test.go
index b275018..e3f652e 100644
--- a/plumbing/transport/ssh/auth_method_test.go
+++ b/plumbing/transport/ssh/auth_method_test.go
@@ -18,7 +18,8 @@ import (
type (
SuiteCommon struct{}
- mockKnownHosts struct{}
+ mockKnownHosts struct{}
+ mockKnownHostsWithCert struct{}
)
func (mockKnownHosts) host() string { return "github.com" }
@@ -27,6 +28,19 @@ func (mockKnownHosts) knownHosts() []byte {
}
func (mockKnownHosts) Network() string { return "tcp" }
func (mockKnownHosts) String() string { return "github.com:22" }
+func (mockKnownHosts) Algorithms() []string {
+ return []string{ssh.KeyAlgoRSA, ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512}
+}
+
+func (mockKnownHostsWithCert) host() string { return "github.com" }
+func (mockKnownHostsWithCert) knownHosts() []byte {
+ return []byte(`@cert-authority github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==`)
+}
+func (mockKnownHostsWithCert) Network() string { return "tcp" }
+func (mockKnownHostsWithCert) String() string { return "github.com:22" }
+func (mockKnownHostsWithCert) Algorithms() []string {
+ return []string{ssh.CertAlgoRSASHA512v01, ssh.CertAlgoRSASHA256v01, ssh.CertAlgoRSAv01}
+}
var _ = Suite(&SuiteCommon{})
@@ -230,3 +244,93 @@ func (*SuiteCommon) TestNewKnownHostsCallback(c *C) {
err = clb(mock.String(), mock, hostKey)
c.Assert(err, IsNil)
}
+
+func (*SuiteCommon) TestNewKnownHostsDbWithoutCert(c *C) {
+ if runtime.GOOS == "js" {
+ c.Skip("not available in wasm")
+ }
+
+ var mock = mockKnownHosts{}
+
+ f, err := util.TempFile(osfs.Default, "", "known-hosts")
+ c.Assert(err, IsNil)
+
+ _, err = f.Write(mock.knownHosts())
+ c.Assert(err, IsNil)
+
+ err = f.Close()
+ c.Assert(err, IsNil)
+
+ defer util.RemoveAll(osfs.Default, f.Name())
+
+ f, err = osfs.Default.Open(f.Name())
+ c.Assert(err, IsNil)
+
+ defer f.Close()
+
+ db, err := newKnownHostsDb(f.Name())
+ c.Assert(err, IsNil)
+
+ algos := db.HostKeyAlgorithms(mock.String())
+ c.Assert(algos, HasLen, len(mock.Algorithms()))
+
+ contains := func(container []string, value string) bool {
+ for _, inner := range container {
+ if inner == value {
+ return true
+ }
+ }
+ return false
+ }
+
+ for _, algorithm := range mock.Algorithms() {
+ if !contains(algos, algorithm) {
+ c.Error("algos does not contain ", algorithm)
+ }
+ }
+}
+
+func (*SuiteCommon) TestNewKnownHostsDbWithCert(c *C) {
+ if runtime.GOOS == "js" {
+ c.Skip("not available in wasm")
+ }
+
+ var mock = mockKnownHostsWithCert{}
+
+ f, err := util.TempFile(osfs.Default, "", "known-hosts")
+ c.Assert(err, IsNil)
+
+ _, err = f.Write(mock.knownHosts())
+ c.Assert(err, IsNil)
+
+ err = f.Close()
+ c.Assert(err, IsNil)
+
+ defer util.RemoveAll(osfs.Default, f.Name())
+
+ f, err = osfs.Default.Open(f.Name())
+ c.Assert(err, IsNil)
+
+ defer f.Close()
+
+ db, err := newKnownHostsDb(f.Name())
+ c.Assert(err, IsNil)
+
+ algos := db.HostKeyAlgorithms(mock.String())
+ c.Assert(algos, HasLen, len(mock.Algorithms()))
+
+ contains := func(container []string, value string) bool {
+ for _, inner := range container {
+ if inner == value {
+ return true
+ }
+ }
+ return false
+ }
+
+ for _, algorithm := range mock.Algorithms() {
+ if !contains(algos, algorithm) {
+ c.Error("algos does not contain ", algorithm)
+ }
+ }
+}
diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go
index 05dea44..a37024f 100644
--- a/plumbing/transport/ssh/common.go
+++ b/plumbing/transport/ssh/common.go
@@ -11,7 +11,6 @@ import (
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
- "github.com/skeema/knownhosts"
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
@@ -127,17 +126,25 @@ func (c *command) connect() error {
}
hostWithPort := c.getHostWithPort()
if config.HostKeyCallback == nil {
- kh, err := newKnownHosts()
+ db, err := newKnownHostsDb()
if err != nil {
return err
}
- config.HostKeyCallback = kh.HostKeyCallback()
- config.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort)
+
+ config.HostKeyCallback = db.HostKeyCallback()
+ config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort)
} else if len(config.HostKeyAlgorithms) == 0 {
// Set the HostKeyAlgorithms based on HostKeyCallback.
// 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.
- config.HostKeyAlgorithms = knownhosts.HostKeyAlgorithms(config.HostKeyCallback, hostWithPort)
+ db, err := newKnownHostsDb()
+ if err != nil {
+ return err
+ }
+
+ // Note that the knownhost database is used, as it provides additional functionality
+ // to handle ssh cert-authorities.
+ config.HostKeyAlgorithms = db.HostKeyAlgorithms(hostWithPort)
}
overrideConfig(c.config, config)
diff --git a/plumbing/transport/test/receive_pack.go b/plumbing/transport/test/receive_pack.go
index 9414fba..d4d2b10 100644
--- a/plumbing/transport/test/receive_pack.go
+++ b/plumbing/transport/test/receive_pack.go
@@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
+ . "github.com/go-git/go-git/v5/internal/test"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
@@ -42,7 +43,7 @@ func (s *ReceivePackSuite) TestAdvertisedReferencesNotExists(c *C) {
r, err := s.Client.NewReceivePackSession(s.NonExistentEndpoint, s.EmptyAuth)
c.Assert(err, IsNil)
ar, err := r.AdvertisedReferences()
- c.Assert(err, Equals, transport.ErrRepositoryNotFound)
+ c.Assert(err, ErrorIs, transport.ErrRepositoryNotFound)
c.Assert(ar, IsNil)
c.Assert(r.Close(), IsNil)
@@ -54,7 +55,7 @@ func (s *ReceivePackSuite) TestAdvertisedReferencesNotExists(c *C) {
}
writer, err := r.ReceivePack(context.Background(), req)
- c.Assert(err, Equals, transport.ErrRepositoryNotFound)
+ c.Assert(err, ErrorIs, transport.ErrRepositoryNotFound)
c.Assert(writer, IsNil)
c.Assert(r.Close(), IsNil)
}