diff options
Diffstat (limited to 'plumbing')
-rw-r--r-- | plumbing/format/packfile/decoder.go | 4 | ||||
-rw-r--r-- | plumbing/format/packfile/scanner.go | 5 | ||||
-rw-r--r-- | plumbing/format/packfile/scanner_test.go | 5 | ||||
-rw-r--r-- | plumbing/format/pktline/scanner_test.go | 2 | ||||
-rw-r--r-- | plumbing/object/change_adaptor.go | 9 | ||||
-rw-r--r-- | plumbing/object/change_test.go | 5 | ||||
-rw-r--r-- | plumbing/transport/ssh/auth_method.go | 33 | ||||
-rw-r--r-- | plumbing/transport/ssh/auth_method_test.go | 11 | ||||
-rw-r--r-- | plumbing/transport/ssh/common.go | 8 | ||||
-rw-r--r-- | plumbing/transport/ssh/upload_pack_test.go | 19 |
10 files changed, 72 insertions, 29 deletions
diff --git a/plumbing/format/packfile/decoder.go b/plumbing/format/packfile/decoder.go index f3328ef..21ddbbf 100644 --- a/plumbing/format/packfile/decoder.go +++ b/plumbing/format/packfile/decoder.go @@ -310,13 +310,13 @@ func (d *Decoder) DecodeObjectAt(offset int64) (plumbing.EncodedObject, error) { return nil, ErrNonSeekable } - beforeJump, err := d.s.Seek(offset) + beforeJump, err := d.s.SeekFromStart(offset) if err != nil { return nil, err } defer func() { - _, seekErr := d.s.Seek(beforeJump) + _, seekErr := d.s.SeekFromStart(beforeJump) if err == nil { err = seekErr } diff --git a/plumbing/format/packfile/scanner.go b/plumbing/format/packfile/scanner.go index d8cece6..97512d1 100644 --- a/plumbing/format/packfile/scanner.go +++ b/plumbing/format/packfile/scanner.go @@ -300,8 +300,9 @@ func (s *Scanner) copyObject(w io.Writer) (int64, error) { return io.Copy(w, s.zr) } -// Seek sets a new offset from start, returns the old position before the change -func (s *Scanner) Seek(offset int64) (previous int64, err error) { +// SeekFromStart sets a new offset from start, returns the old position before +// the change. +func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) { // if seeking we assume that you are not interested on the header if s.version == 0 { s.version = VersionSupported diff --git a/plumbing/format/packfile/scanner_test.go b/plumbing/format/packfile/scanner_test.go index f2aa5fb..1ca8b6e 100644 --- a/plumbing/format/packfile/scanner_test.go +++ b/plumbing/format/packfile/scanner_test.go @@ -4,9 +4,10 @@ import ( "bytes" "io" - . "gopkg.in/check.v1" - "github.com/src-d/go-git-fixtures" "gopkg.in/src-d/go-git.v4/plumbing" + + "github.com/src-d/go-git-fixtures" + . "gopkg.in/check.v1" ) type ScannerSuite struct { diff --git a/plumbing/format/pktline/scanner_test.go b/plumbing/format/pktline/scanner_test.go index b8a78ec..048ea38 100644 --- a/plumbing/format/pktline/scanner_test.go +++ b/plumbing/format/pktline/scanner_test.go @@ -218,7 +218,7 @@ func ExampleScanner() { for s.Scan() { payload := s.Bytes() if len(payload) == 0 { // zero sized payloads correspond to flush-pkts. - fmt.Println("FLUSH-PKT DETECTED\n") + fmt.Println("FLUSH-PKT DETECTED") } else { // otherwise, you will be able to access the full payload. fmt.Printf("PAYLOAD = %q\n", string(payload)) } diff --git a/plumbing/object/change_adaptor.go b/plumbing/object/change_adaptor.go index cf8de6c..49b6545 100644 --- a/plumbing/object/change_adaptor.go +++ b/plumbing/object/change_adaptor.go @@ -1,6 +1,7 @@ package object import ( + "errors" "fmt" "gopkg.in/src-d/go-git.v4/utils/merkletrie" @@ -15,11 +16,11 @@ func newChange(c merkletrie.Change) (*Change, error) { var err error if ret.From, err = newChangeEntry(c.From); err != nil { - return nil, fmt.Errorf("From field: ", err) + return nil, fmt.Errorf("From field: %s", err) } if ret.To, err = newChangeEntry(c.To); err != nil { - return nil, fmt.Errorf("To field: ", err) + return nil, fmt.Errorf("To field: %s", err) } return ret, nil @@ -32,7 +33,7 @@ func newChangeEntry(p noder.Path) (ChangeEntry, error) { asTreeNoder, ok := p.Last().(*treeNoder) if !ok { - return ChangeEntry{}, fmt.Errorf("cannot transform non-TreeNoders") + return ChangeEntry{}, errors.New("cannot transform non-TreeNoders") } return ChangeEntry{ @@ -52,7 +53,7 @@ func newChanges(src merkletrie.Changes) (Changes, error) { for i, e := range src { ret[i], err = newChange(e) if err != nil { - return nil, fmt.Errorf("change #%d: %s", err) + return nil, fmt.Errorf("change #%d: %s", i, err) } } diff --git a/plumbing/object/change_test.go b/plumbing/object/change_test.go index 005ceb0..bfd4613 100644 --- a/plumbing/object/change_test.go +++ b/plumbing/object/change_test.go @@ -236,10 +236,7 @@ func (s *ChangeSuite) TestNoFileFilemodes(c *C) { c.Assert(err, IsNil) for _, change := range changes { _, _, err := change.Files() - if err != nil { - panic(err) - c.Assert(err, IsNil) - } + c.Assert(err, IsNil) } prev = commit diff --git a/plumbing/transport/ssh/auth_method.go b/plumbing/transport/ssh/auth_method.go index ad92ee1..a3e1ad1 100644 --- a/plumbing/transport/ssh/auth_method.go +++ b/plumbing/transport/ssh/auth_method.go @@ -1,6 +1,8 @@ package ssh import ( + "crypto/x509" + "encoding/pem" "errors" "fmt" "io/ioutil" @@ -9,9 +11,11 @@ import ( "os/user" "path/filepath" - "github.com/src-d/crypto/ssh/knownhosts" + "gopkg.in/src-d/go-git.v4/plumbing/transport" + "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" + "golang.org/x/crypto/ssh/knownhosts" ) const DefaultUsername = "git" @@ -22,6 +26,7 @@ var ErrEmptySSHAgentAddr = errors.New("SSH_AUTH_SOCK env variable is required") // must implement. The clientConfig method returns the ssh client // configuration needed to establish an ssh connection. type AuthMethod interface { + transport.AuthMethod clientConfig() *ssh.ClientConfig hostKeyCallback() (ssh.HostKeyCallback, error) } @@ -112,9 +117,22 @@ type PublicKeys struct { baseAuthMethod } -// NewPublicKeys returns a PublicKeys from a PEM encoded private key. It -// supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. -func NewPublicKeys(user string, pemBytes []byte) (AuthMethod, error) { +// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An +// encryption password should be given if the pemBytes contains a password +// encrypted PEM block otherwise password should be empty. It supports RSA +// (PKCS#1), DSA (OpenSSL), and ECDSA private keys. +func NewPublicKeys(user string, pemBytes []byte, password string) (AuthMethod, error) { + block, _ := pem.Decode(pemBytes) + if x509.IsEncryptedPEMBlock(block) { + key, err := x509.DecryptPEMBlock(block, []byte(password)) + if err != nil { + return nil, err + } + + block = &pem.Block{Type: block.Type, Bytes: key} + pemBytes = pem.EncodeToMemory(block) + } + signer, err := ssh.ParsePrivateKey(pemBytes) if err != nil { return nil, err @@ -124,14 +142,15 @@ func NewPublicKeys(user string, pemBytes []byte) (AuthMethod, error) { } // NewPublicKeysFromFile returns a PublicKeys from a file containing a PEM -// encoded private key. -func NewPublicKeysFromFile(user string, pemFile string) (AuthMethod, error) { +// encoded private key. An encryption password should be given if the pemBytes +// contains a password encrypted PEM block otherwise password should be empty. +func NewPublicKeysFromFile(user, pemFile, password string) (AuthMethod, error) { bytes, err := ioutil.ReadFile(pemFile) if err != nil { return nil, err } - return NewPublicKeys(user, bytes) + return NewPublicKeys(user, bytes, password) } func (a *PublicKeys) Name() string { diff --git a/plumbing/transport/ssh/auth_method_test.go b/plumbing/transport/ssh/auth_method_test.go index 43b34df..6f3d82f 100644 --- a/plumbing/transport/ssh/auth_method_test.go +++ b/plumbing/transport/ssh/auth_method_test.go @@ -109,7 +109,14 @@ func (s *SuiteCommon) TestNewSSHAgentAuth(c *C) { } func (*SuiteCommon) TestNewPublicKeys(c *C) { - auth, err := NewPublicKeys("foo", testdata.PEMBytes["rsa"]) + auth, err := NewPublicKeys("foo", testdata.PEMBytes["rsa"], "") + c.Assert(err, IsNil) + c.Assert(auth, NotNil) +} + +func (*SuiteCommon) TestNewPublicKeysWithEncryptedPEM(c *C) { + f := testdata.PEMEncryptedKeys[0] + auth, err := NewPublicKeys("foo", f.PEMBytes, f.EncryptionKey) c.Assert(err, IsNil) c.Assert(auth, NotNil) } @@ -122,7 +129,7 @@ func (*SuiteCommon) TestNewPublicKeysFromFile(c *C) { c.Assert(f.Close(), IsNil) defer os.RemoveAll(f.Name()) - auth, err := NewPublicKeysFromFile("foo", f.Name()) + auth, err := NewPublicKeysFromFile("foo", f.Name(), "") c.Assert(err, IsNil) c.Assert(auth, NotNil) } diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go index 9b484f9..7b44a91 100644 --- a/plumbing/transport/ssh/common.go +++ b/plumbing/transport/ssh/common.go @@ -14,6 +14,12 @@ import ( // DefaultClient is the default SSH client. var DefaultClient = common.NewClient(&runner{}) +// DefaultAuthBuilder is the function used to create a default AuthMethod, when +// the user doesn't provide any. +var DefaultAuthBuilder = func(user string) (AuthMethod, error) { + return NewSSHAgentAuth(user) +} + type runner struct{} func (r *runner) Command(cmd string, ep transport.Endpoint, auth transport.AuthMethod) (common.Command, error) { @@ -119,7 +125,7 @@ func (c *command) setAuthFromEndpoint() error { } var err error - c.auth, err = NewSSHAgentAuth(u) + c.auth, err = DefaultAuthBuilder(u) return err } diff --git a/plumbing/transport/ssh/upload_pack_test.go b/plumbing/transport/ssh/upload_pack_test.go index 54d523a..cb9baa5 100644 --- a/plumbing/transport/ssh/upload_pack_test.go +++ b/plumbing/transport/ssh/upload_pack_test.go @@ -16,10 +16,7 @@ type UploadPackSuite struct { var _ = Suite(&UploadPackSuite{}) func (s *UploadPackSuite) SetUpSuite(c *C) { - if os.Getenv("SSH_AUTH_SOCK") == "" { - c.Skip("SSH_AUTH_SOCK is not set") - } - + s.setAuthBuilder(c) s.UploadPackSuite.Client = DefaultClient ep, err := transport.NewEndpoint("git@github.com:git-fixtures/basic.git") @@ -34,3 +31,17 @@ func (s *UploadPackSuite) SetUpSuite(c *C) { c.Assert(err, IsNil) s.UploadPackSuite.NonExistentEndpoint = ep } + +func (s *UploadPackSuite) setAuthBuilder(c *C) { + privateKey := os.Getenv("SSH_TEST_PRIVATE_KEY") + if privateKey != "" { + DefaultAuthBuilder = func(user string) (AuthMethod, error) { + return NewPublicKeysFromFile(user, privateKey, "") + } + } + + if privateKey == "" && os.Getenv("SSH_AUTH_SOCK") == "" { + c.Skip("SSH_AUTH_SOCK or SSH_TEST_PRIVATE_KEY are required") + return + } +} |