Explicitly disable Git credential helper (#5367)

* Explicitly disable Git credential helper

If the user running Gitea has configured a credential helper, Git
credentials might leak out of Gitea.

There are two problems with credential helpers when combined with Gitea:

1. Credentials entered by a user when doing a migration or setting up a
   mirror will end up in the credential store. In the worst case, this
   is the plain text file ~/.git-credentials.
2. Credentials in the credential store will be used for migrations and
   mirrors by all users. For example, if user A sets up a mirror, their
   credentials will be stored. If user B later sets up a mirror from the
   same host and does not enter any credentials, user A's credentials
   will be used.

This PR prepends -c credential.helper= to all Git commands to clear the
list of helpers. This requires at least Git version 2.9, as previous
versions will try to load an empty helper instead. For more details, see
24321375cd

* Update git module
This commit is contained in:
Michael Kuhn 2018-11-28 08:00:25 +01:00 committed by Lauris BH
parent 08bf443016
commit 0222623be9
6 changed files with 51 additions and 25 deletions

4
Gopkg.lock generated
View file

@ -3,11 +3,11 @@
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:ebd587087cf937b6d3db7dde843a557d157fd68820a9d3d0157a8d8f4011ad29" digest = "1:ab875622908a804a327a95a1701002b150806a3c5406df51ec231eac16d3a1ca"
name = "code.gitea.io/git" name = "code.gitea.io/git"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "578ad8f1259b0d660d19b05a011596f8fd3fea37" revision = "389d3c803e12a30dffcbb54a15c2242521bc4333"
[[projects]] [[projects]]
branch = "master" branch = "master"

View file

@ -34,6 +34,7 @@ import (
_ "github.com/go-macaron/session/redis" // redis plugin for store session _ "github.com/go-macaron/session/redis" // redis plugin for store session
"github.com/go-xorm/core" "github.com/go-xorm/core"
"github.com/kballard/go-shellquote" "github.com/kballard/go-shellquote"
"github.com/mcuadros/go-version"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"strk.kbt.io/projects/go/libravatar" "strk.kbt.io/projects/go/libravatar"
) )
@ -929,23 +930,7 @@ func NewContext() {
log.Fatal(4, "Error retrieving git version: %v", err) log.Fatal(4, "Error retrieving git version: %v", err)
} }
splitVersion := strings.SplitN(binVersion, ".", 4) if !version.Compare(binVersion, "2.1.2", ">=") {
majorVersion, err := strconv.ParseUint(splitVersion[0], 10, 64)
if err != nil {
log.Fatal(4, "Error parsing git major version: %v", err)
}
minorVersion, err := strconv.ParseUint(splitVersion[1], 10, 64)
if err != nil {
log.Fatal(4, "Error parsing git minor version: %v", err)
}
revisionVersion, err := strconv.ParseUint(splitVersion[2], 10, 64)
if err != nil {
log.Fatal(4, "Error parsing git revision version: %v", err)
}
if !((majorVersion > 2) || (majorVersion == 2 && minorVersion > 1) ||
(majorVersion == 2 && minorVersion == 1 && revisionVersion >= 2)) {
LFS.StartServer = false LFS.StartServer = false
log.Error(4, "LFS server support needs at least Git v2.1.2") log.Error(4, "LFS server support needs at least Git v2.1.2")
@ -1206,6 +1191,16 @@ func NewContext() {
sec = Cfg.Section("U2F") sec = Cfg.Section("U2F")
U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimRight(AppURL, "/"))) U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimRight(AppURL, "/")))
U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimRight(AppURL, "/")) U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimRight(AppURL, "/"))
binVersion, err := git.BinVersion()
if err != nil {
log.Fatal(4, "Error retrieving git version: %v", err)
}
if version.Compare(binVersion, "2.9", ">=") {
// Explicitly disable credential helper, otherwise Git credentials might leak
git.GlobalCommandArgs = append(git.GlobalCommandArgs, "-c", "credential.helper=")
}
} }
// Service settings // Service settings

View file

@ -37,9 +37,12 @@ func (c *Command) String() string {
// NewCommand creates and returns a new Git Command based on given command and arguments. // NewCommand creates and returns a new Git Command based on given command and arguments.
func NewCommand(args ...string) *Command { func NewCommand(args ...string) *Command {
// Make an explicit copy of GlobalCommandArgs, otherwise append might overwrite it
cargs := make([]string, len(GlobalCommandArgs))
copy(cargs, GlobalCommandArgs)
return &Command{ return &Command{
name: "git", name: "git",
args: append(GlobalCommandArgs, args...), args: append(cargs, args...),
} }
} }

View file

@ -18,6 +18,15 @@ func (repo *Repository) getTree(id SHA1) (*Tree, error) {
// GetTree find the tree object in the repository. // GetTree find the tree object in the repository.
func (repo *Repository) GetTree(idStr string) (*Tree, error) { func (repo *Repository) GetTree(idStr string) (*Tree, error) {
if len(idStr) != 40 {
res, err := NewCommand("rev-parse", idStr).RunInDir(repo.Path)
if err != nil {
return nil, err;
}
if len(res) > 0 {
idStr = res[:len(res)-1]
}
}
id, err := NewIDFromString(idStr) id, err := NewIDFromString(idStr)
if err != nil { if err != nil {
return nil, err return nil, err

14
vendor/code.gitea.io/git/tree.go generated vendored
View file

@ -70,3 +70,17 @@ func (t *Tree) ListEntries() (Entries, error) {
t.entries, err = parseTreeEntries(stdout, t) t.entries, err = parseTreeEntries(stdout, t)
return t.entries, err return t.entries, err
} }
// ListEntriesRecursive returns all entries of current tree recursively including all subtrees
func (t *Tree) ListEntriesRecursive() (Entries, error) {
if t.entriesParsed {
return t.entries, nil
}
stdout, err := NewCommand("ls-tree", "-t", "-r", t.ID.String()).RunInDirBytes(t.repo.Path)
if err != nil {
return nil, err
}
t.entries, err = parseTreeEntries(stdout, t)
return t.entries, err
}

View file

@ -18,15 +18,15 @@ type EntryMode int
// one of these. // one of these.
const ( const (
// EntryModeBlob // EntryModeBlob
EntryModeBlob EntryMode = 0100644 EntryModeBlob EntryMode = 0x0100644
// EntryModeExec // EntryModeExec
EntryModeExec EntryMode = 0100755 EntryModeExec EntryMode = 0x0100755
// EntryModeSymlink // EntryModeSymlink
EntryModeSymlink EntryMode = 0120000 EntryModeSymlink EntryMode = 0x0120000
// EntryModeCommit // EntryModeCommit
EntryModeCommit EntryMode = 0160000 EntryModeCommit EntryMode = 0x0160000
// EntryModeTree // EntryModeTree
EntryModeTree EntryMode = 0040000 EntryModeTree EntryMode = 0x0040000
) )
// TreeEntry the leaf in the git tree // TreeEntry the leaf in the git tree
@ -50,6 +50,11 @@ func (te *TreeEntry) Name() string {
return te.name return te.name
} }
// Mode returns the mode of the entry
func (te *TreeEntry) Mode() EntryMode {
return te.mode
}
// Size returns the size of the entry // Size returns the size of the entry
func (te *TreeEntry) Size() int64 { func (te *TreeEntry) Size() int64 {
if te.IsDir() { if te.IsDir() {